From 61af3dc3044b1a0f135eafbae564873d34d3c6bc Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 15 Feb 2017 13:37:59 +0100
Subject: [PATCH 001/402] thread safety in BinaryMapNode

---
 .../truffle/r/nodes/binary/BinaryArithmeticNode.java       | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index cbf0003eec..828f41b479 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -167,10 +167,11 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
 
         public BinaryMapNode get(BinaryArithmetic arithmetic, RAbstractVector left, RAbstractVector right) {
             CompilerAsserts.neverPartOfCompilation();
-            if (!cached.isSupported(left, right)) {
-                cached = cached.replace(createCached(arithmetic, left, right));
+            BinaryMapNode map = cached;
+            if (!map.isSupported(left, right)) {
+                cached = map = map.replace(createCached(arithmetic, left, right));
             }
-            return cached;
+            return map;
         }
     }
 }
-- 
GitLab


From 62b2a90f971b07f518f0a490e815c8f486d126b2 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Wed, 15 Feb 2017 14:09:41 +0100
Subject: [PATCH 002/402] Fixed failing mx R with TraceNativeCalls option.

---
 com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c | 6 +++---
 1 file changed, 3 insertions(+), 3 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 affaab5f72..2753180542 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -247,9 +247,9 @@ void init_internals(JNIEnv *env) {
 
     // static JNI-specific methods
 	JNIUpCallsRFFIImplClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl");
-	logNotCharSXPWrapperMethodID = checkGetMethodID(env, UpCallsRFFIClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1);
-	restoreHandlerStacksMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1);
-    setCompleteMethodID = checkGetMethodID(env, UpCallsRFFIClass, "setComplete", "(Ljava/lang/Object;Z)V", 1);
+	logNotCharSXPWrapperMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1);
+	restoreHandlerStacksMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1);
+    setCompleteMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "setComplete", "(Ljava/lang/Object;Z)V", 1);
 }
 
 static jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) {
-- 
GitLab


From 338bf871c2a8380bb3e239015bcbdcb2d62de63a Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 14 Feb 2017 09:44:21 -0800
Subject: [PATCH 003/402] rffi: fix signature of R_NewHashedEnv

---
 com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c     | 2 +-
 com.oracle.truffle.r.native/version.source                   | 2 +-
 .../com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java  | 5 +++--
 .../src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java | 2 +-
 .../oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java   | 2 +-
 .../src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java | 2 +-
 6 files changed, 8 insertions(+), 7 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 2753180542..d35c32ed46 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -166,7 +166,7 @@ void init_internals(JNIEnv *env) {
 	Rf_allocateArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_duplicateMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_duplicate", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 	Rf_anyDuplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_anyDuplicated", "(Ljava/lang/Object;I)I", 0);
-	R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;I)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0);
+	R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0);
 	Rf_classgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_classgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)V", 0);
 	R_do_MAKE_CLASS_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_MAKE_CLASS", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 78c24caea0..61286da084 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-2/10/17
+2/14/17
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 a12d923fd9..9dbf07932a 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
@@ -1146,8 +1146,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) {
-        REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, initialSize);
+    public REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize) {
+        // We know this is an RIntVector from use site in gramRd.c
+        REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, ((RIntVector) initialSize).getDataAt(0));
         RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame());
         return env;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index a998220115..0c9427a05f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -69,7 +69,7 @@ public enum RFFIUpCallMethod {
     R_Interactive("() : sint32"),
     R_MakeExternalPtr("(object, object, object) : object"),
     R_NamespaceRegistry("() : object"),
-    R_NewHashedEnv("(object, sint32) : object"),
+    R_NewHashedEnv("(object, object) : object"),
     R_ParseVector("(object, sint32, object) : object"),
     R_PromiseExpr("(object) : object"),
     R_SetExternalPtrAddr("(object, object) : void"),
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 fd78becb64..110cb51fbf 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
@@ -700,7 +700,7 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) {
+    public REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize) {
         RFFIUtils.traceUpCall("R_NewHashedEnv", parent, initialSize);
         return delegate.R_NewHashedEnv(parent, initialSize);
     }
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 3d96124a1c..7521fdc944 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
@@ -240,7 +240,7 @@ public interface StdUpCallsRFFI {
 
     void R_CleanUp(int sa, int status, int runlast);
 
-    REnvironment R_NewHashedEnv(REnvironment parent, int initialSize);
+    REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize);
 
     int PRSEEN(Object x);
 
-- 
GitLab


From 7070441bb74d09cfa125af1941690fc2d6286467 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 14 Feb 2017 11:43:47 -0800
Subject: [PATCH 004/402] rffi: fix NFI signatures for RFFICstring parameters

---
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java  | 14 +++++++-------
 .../truffle/r/runtime/ffi/RFFICstring.java     |  5 +++--
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java  |  2 +-
 .../r/test/tools/RFFIUpCallMethodGenerate.java | 18 +++++++++++++++---
 4 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index 0c9427a05f..22921b1a2c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -77,7 +77,7 @@ public enum RFFIUpCallMethod {
     R_SetExternalPtrTag("(object, object) : void"),
     R_ToplevelExec("() : object"),
     R_computeIdentical("(object, object, sint32) : sint32"),
-    R_do_MAKE_CLASS("(pointer) : object"),
+    R_do_MAKE_CLASS("(string) : object"),
     R_getContextCall("(object) : object"),
     R_getContextEnv("(object) : object"),
     R_getContextFun("(object) : object"),
@@ -110,7 +110,7 @@ public enum RFFIUpCallMethod {
     Rf_copyMatrix("(object, object, sint32) : void"),
     Rf_defineVar("(object, object, object) : void"),
     Rf_duplicate("(object, sint32) : object"),
-    Rf_error("(pointer) : void"),
+    Rf_error("(string) : void"),
     Rf_eval("(object, object) : object"),
     Rf_findVar("(object, object) : object"),
     Rf_findVarInFrame("(object, object) : object"),
@@ -118,8 +118,8 @@ public enum RFFIUpCallMethod {
     Rf_findfun("(object, object) : object"),
     Rf_getAttrib("(object, object) : object"),
     Rf_gsetVar("(object, object, object) : void"),
-    Rf_inherits("(pointer, object) : sint32"),
-    Rf_install("(pointer) : object"),
+    Rf_inherits("(string, object) : sint32"),
+    Rf_install("(string) : object"),
     Rf_isNull("(object) : sint32"),
     Rf_isString("(object) : sint32"),
     Rf_lengthgets("(object, sint32) : object"),
@@ -127,9 +127,9 @@ public enum RFFIUpCallMethod {
     Rf_ncols("(object) : sint32"),
     Rf_nrows("(object) : sint32"),
     Rf_setAttrib("(object, object, object) : void"),
-    Rf_warning("(pointer) : void"),
-    Rf_warningcall("(object, pointer) : void"),
-    Rprintf("(pointer) : void"),
+    Rf_warning("(string) : void"),
+    Rf_warningcall("(object, string) : void"),
+    Rprintf("(string) : void"),
     SETCADR("(object, object) : object"),
     SETCAR("(object, object) : object"),
     SETCDR("(object, object) : object"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
index c8dbee39e1..5d50ed6f2c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
@@ -28,10 +28,11 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * Tags an upcall argument as being (on the native side) a C string.
+ * Tags an upcall argument as being (on the native side) a C string. By default the C string is
+ * converted to a {@link String}, which requires it to be null-terminated.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.PARAMETER)
 public @interface RFFICstring {
-
+    boolean convert() default true;
 }
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 7521fdc944..8dae3d3e8a 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
@@ -65,7 +65,7 @@ public interface StdUpCallsRFFI {
 
     Object Rf_coerceVector(Object x, int mode);
 
-    Object Rf_mkCharLenCE(@RFFICstring Object bytes, int len, int encoding);
+    Object Rf_mkCharLenCE(@RFFICstring(convert = false) Object bytes, int len, int encoding);
 
     Object Rf_cons(Object car, Object cdr);
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
index 85f600102e..569be1c98c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
@@ -73,12 +73,24 @@ public class RFFIUpCallMethodGenerate {
         return sb.toString();
     }
 
-    static String nfiParamName(Class<?> paramType, Annotation[] annotation) {
+    static String nfiParamName(Class<?> paramType, Annotation[] annotations) {
         String paramName = paramType.getSimpleName();
-        Class<?> klass = annotation.length == 0 ? null : annotation[0].annotationType();
+        RFFICstring rffiCstring = null;
+        if (annotations.length > 0) {
+            for (Annotation annotation : annotations) {
+                if (annotation instanceof RFFICstring) {
+                    rffiCstring = (RFFICstring) annotation;
+                    break;
+                }
+            }
+        }
         switch (paramName) {
             case "Object":
-                return klass == null ? "object" : "pointer";
+                if (rffiCstring == null) {
+                    return "object";
+                } else {
+                    return rffiCstring.convert() ? "string" : "pointer";
+                }
             case "int":
                 return "sint32";
             case "double":
-- 
GitLab


From 11ed93f69b0d066da1ad513c8f16cd9669509cda Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 14 Feb 2017 13:11:21 -0800
Subject: [PATCH 005/402] rffi; add Rf_installChar as separate method

---
 com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c    | 5 +++--
 .../com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java | 6 ++++++
 .../com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java    | 1 +
 .../oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java  | 6 ++++++
 .../com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java    | 2 ++
 5 files changed, 18 insertions(+), 2 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 d35c32ed46..00d867ef64 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -52,6 +52,7 @@ static jmethodID Rf_getAttribMethodID;
 static jmethodID Rf_setAttribMethodID;
 static jmethodID Rf_isStringMethodID;
 static jmethodID Rf_isNullMethodID;
+static jmethodID Rf_installCharMethodID;
 static jmethodID Rf_installMethodID;
 static jmethodID Rf_warningcallMethodID;
 static jmethodID Rf_warningMethodID;
@@ -158,6 +159,7 @@ void init_internals(JNIEnv *env) {
 	Rf_isStringMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isString", "(Ljava/lang/Object;)I", 0);
 	Rf_isNullMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isNull", "(Ljava/lang/Object;)I", 0);
 	Rf_installMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_install", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
+	Rf_installCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_installChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)V", 0);
 	Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 	Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)V", 0);
@@ -497,8 +499,7 @@ SEXP Rf_install(const char *name) {
 SEXP Rf_installChar(SEXP charsxp) {
 	TRACE(TARGp, charsxp);
 	JNIEnv *thisenv = getEnv();
-	jstring string = stringFromCharSXP(thisenv, charsxp);
-	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_installMethodID, string);
+	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_installCharMethodID, charsxp);
 	return checkRef(thisenv, result);
 }
 
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 9dbf07932a..87aa0607ff 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
@@ -315,6 +315,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return RDataFactory.createSymbolInterned((String) name);
     }
 
+    @Override
+    public Object Rf_installChar(Object name) {
+        CharSXPWrapper charSXP = guaranteeInstanceOf(name, CharSXPWrapper.class);
+        return RDataFactory.createSymbolInterned(charSXP.getContents());
+    }
+
     @Override
     public Object Rf_lengthgets(Object x, int newSize) {
         RAbstractVector vec = (RAbstractVector) RRuntime.asAbstractVector(x);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index 22921b1a2c..d475cc1f9e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -120,6 +120,7 @@ public enum RFFIUpCallMethod {
     Rf_gsetVar("(object, object, object) : void"),
     Rf_inherits("(string, object) : sint32"),
     Rf_install("(string) : object"),
+    Rf_installChar("(object) : object"),
     Rf_isNull("(object) : sint32"),
     Rf_isString("(object) : sint32"),
     Rf_lengthgets("(object, sint32) : object"),
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 110cb51fbf..2943d37a76 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
@@ -159,6 +159,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.Rf_install(name);
     }
 
+    @Override
+    public Object Rf_installChar(Object name) {
+        RFFIUtils.traceUpCall("Rf_installChar", name);
+        return delegate.Rf_installChar(name);
+    }
+
     @Override
     public Object Rf_lengthgets(Object x, int newSize) {
         RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize);
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 8dae3d3e8a..1bd2e8efe2 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
@@ -90,6 +90,8 @@ public interface StdUpCallsRFFI {
 
     Object Rf_install(@RFFICstring Object name);
 
+    Object Rf_installChar(Object name);
+
     Object Rf_lengthgets(Object x, int newSize);
 
     int Rf_isString(Object x);
-- 
GitLab


From b19b7a684c13b2f4385e1cf2f8e7829868d297df Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 15 Feb 2017 17:14:55 +0100
Subject: [PATCH 006/402] fixed minor typo in condition

---
 .../com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 2f45bf6836..0ce9433368 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -233,7 +233,7 @@ public class GrepFunctions {
             boolean[] matches = new boolean[len];
             if (fixed && !perl) {
                 // TODO case
-                if (!fixed) {
+                if (fixed) {
                     pattern = RegExp.checkPreDefinedClasses(pattern);
                 }
                 findAllMatches(matches, pattern, vector, fixed, ignoreCase);
-- 
GitLab


From 80fc3b9ddba137803ad3d8a4bb4fcecb3b47d877 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Feb 2017 13:38:59 +0100
Subject: [PATCH 007/402] =?UTF-8?q?add=20missing=20CompilationFinal=20in?=
 =?UTF-8?q?=20PositionCheckSubsetNode=20and=20add=20=E2=80=9Cinherits?=
 =?UTF-8?q?=E2=80=9D=20to=20EvaluatedArgumentsVisitor?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../r/nodes/access/vector/PositionCheckSubsetNode.java      | 3 ++-
 .../truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java  | 6 +++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
index e7c74e62eb..22dfb909a4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.access.vector;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
@@ -257,7 +258,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
     }
 
     private final BranchProfile noZeroes = BranchProfile.create();
-    private boolean checkForScalarPosition = true;
+    @CompilationFinal private boolean checkForScalarPosition = true;
 
     private RAbstractVector doIntegerProfiled(PositionProfile profile, int dimensionLength, RAbstractIntVector intPosition, int positionLength, boolean hasSeenPositive, boolean hasSeenNegative,
                     boolean hasSeenNA, int outOfBoundsCount, int zeroCount, int maxOutOfBoundsIndex) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
index b24242d838..99bed23f0f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,8 +77,8 @@ final class Info {
 public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> {
 
     private static final Set<String> wellKnownFunctions = new HashSet<>(Arrays.asList("c", "$", "@", "[", "[[", "any", "dim", "dimnames", "rownames", "colnames", "is.null", "list", "names", "return",
-                    "print", "length", "rep", "min", "max", "matrix", "table", "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "proc.time", "as.integer",
-                    "as.character", "as.matrix", ".Call", "sum", "order", "rev", "integer", "double", "as.numeric", "as.list", "as.integer", ".Call", ".FastR", "unname", "log", "lgamma",
+                    "print", "length", "rep", "inherits", "min", "max", "matrix", "table", "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "proc.time",
+                    "as.integer", "as.character", "as.matrix", ".Call", "sum", "order", "rev", "integer", "double", "as.numeric", "as.list", "as.integer", ".Call", ".FastR", "unname", "log", "lgamma",
                     "sin", "cos", "tan", "exp", "log", "expm1", "sinh", "sinpi", "cosh", "cospi", "tanh", "tanpi", "asin", "asinh", "acos", "acosh", "atan", "atanh", "<-", "+", "-",
                     "*", "/", "%%", "^", ":", ">=", ">", "<=", "<", "==", "!=", "||", "|", "&&", "&", "!", "%o%", "%*%", "%/%", "%in%", "{", "for", "while", "repeat", "if", "attributes", "attr"));
 
-- 
GitLab


From 63ec48a2e934e2ac2fac1ae5c88ca0bf69f00fc1 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 15 Feb 2017 09:05:56 -0800
Subject: [PATCH 008/402] rffi: make factory creation more flexible

---
 com.oracle.truffle.r.native/version.source    |  2 +-
 .../truffle/r/runtime/ffi/RFFIFactory.java    | 53 ++++++++++++++++---
 .../test/tools/RFFIUpCallMethodGenerate.java  |  1 +
 3 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 61286da084..60d3b2f4a4 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-2/14/17
+15
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index 35fdd63dac..963d98cc59 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -33,8 +33,22 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState;
  * must support the {@link #newContextState()} method.
  */
 public abstract class RFFIFactory {
-    private static final String FACTORY_CLASS_PROPERTY = "fastr.ffi.factory.class";
-    private static final String DEFAULT_FACTORY_CLASS = "com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory";
+    private enum Factory {
+        JNI("com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory"),
+        LLVM("com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_RFFIFactory"),
+        NFI("com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_RFFIFactory");
+
+        private final String klassName;
+
+        Factory(String klassName) {
+            this.klassName = klassName;
+        }
+    }
+
+    private static final String FACTORY_CLASS_PROPERTY = "fastr.rffi.factory.class";
+    private static final String FACTORY_CLASS_NAME_PROPERTY = "fastr.rffi.factory";
+    private static final String FACTORY_CLASS_ENV = "FASTR_RFFI_FACTORY";
+    private static final Factory DEFAULT_FACTORY = Factory.JNI;
 
     /**
      * Singleton instance of the factory.
@@ -45,20 +59,43 @@ public abstract class RFFIFactory {
 
     public static RFFIFactory initialize() {
         if (instance == null) {
-            String prop = System.getProperty(FACTORY_CLASS_PROPERTY);
+            String klassName = getFactoryClassName();
             try {
-                if (prop == null) {
-                    prop = DEFAULT_FACTORY_CLASS;
-                }
-                instance = (RFFIFactory) Class.forName(prop).newInstance();
+                instance = (RFFIFactory) Class.forName(klassName).newInstance();
                 theRFFI = instance.createRFFI();
             } catch (Exception ex) {
-                throw Utils.rSuicide("Failed to instantiate class: " + prop + ": " + ex);
+                throw Utils.rSuicide("Failed to instantiate class: " + klassName + ": " + ex);
             }
         }
         return instance;
     }
 
+    private static String getFactoryClassName() {
+        String prop = System.getProperty(FACTORY_CLASS_PROPERTY);
+        if (prop != null) {
+            return prop;
+        }
+        prop = System.getProperty(FACTORY_CLASS_NAME_PROPERTY);
+        if (prop != null) {
+            return checkFactoryName(prop);
+        }
+        prop = System.getenv(FACTORY_CLASS_ENV);
+        if (prop != null) {
+            return checkFactoryName(prop);
+        }
+        return DEFAULT_FACTORY.klassName;
+    }
+
+    private static String checkFactoryName(String prop) {
+        try {
+            Factory factory = Factory.valueOf(prop.toUpperCase());
+            return factory.klassName;
+        } catch (IllegalArgumentException ex) {
+            throw Utils.rSuicide("No RFFI factory: " + prop);
+        }
+
+    }
+
     public static RFFIFactory getInstance() {
         assert instance != null;
         return instance;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
index 569be1c98c..b538c5c44d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
@@ -28,6 +28,7 @@ import java.util.Arrays;
 import java.util.Comparator;
 
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
+import com.oracle.truffle.r.runtime.ffi.RFFICstring;
 import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
-- 
GitLab


From 7a13f67899893bdb0ebf948e79ccde49b0bccf50 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Thu, 16 Feb 2017 13:50:45 +0100
Subject: [PATCH 009/402] added autocompletion based on utils:::.completeToken

---
 .../r/engine/shell/JLineConsoleCompleter.java | 151 ++++++++++++++++
 .../r/engine/shell/JLineConsoleHandler.java   |   1 +
 .../shell/TestJLineConsoleCompleter.java      | 162 ++++++++++++++++++
 mx.fastr/mx_fastr.py                          |   2 +-
 4 files changed, 315 insertions(+), 1 deletion(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
new file mode 100644
index 0000000000..15cbe86905
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.shell;
+
+import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
+import com.oracle.truffle.r.runtime.RCaller;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import jline.console.completer.Completer;
+
+public class JLineConsoleCompleter implements Completer {
+    private final ConsoleHandler console;
+
+    private static boolean isTesting = false;
+
+    public static void testingMode() {
+        isTesting = true;
+    }
+
+    public JLineConsoleCompleter(ConsoleHandler console) {
+        this.console = console;
+    }
+
+    @Override
+    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
+        try {
+            return completeImpl(buffer, cursor, candidates);
+        } catch (Throwable e) {
+            if (isTesting) {
+                throw e;
+            }
+            RInternalError.reportErrorAndConsoleLog(e, console, 0);
+        }
+        return cursor;
+    }
+
+    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
+        if (buffer.isEmpty()) {
+            return cursor;
+        }
+
+        REnvironment utils = REnvironment.getRegisteredNamespace("utils");
+        Object o = utils.get(".completeToken");
+        if (o instanceof RPromise) {
+            o = PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
+        }
+        RFunction completeToken;
+        if (o instanceof RFunction) {
+            completeToken = (RFunction) o;
+        } else {
+            return cursor;
+        }
+
+        o = utils.get(".CompletionEnv");
+        if (!(o instanceof RPromise)) {
+            return cursor;
+        }
+        REnvironment env = (REnvironment) PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
+        int start = getStart(buffer, env, cursor);
+        env.safePut("start", start);
+        env.safePut("end", cursor);
+        env.safePut("linebuffer", buffer);
+        env.safePut("token", buffer.substring(start, cursor));
+
+        MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame();
+        RContext.getEngine().evalFunction(completeToken, callingFrame, RCaller.createInvalid(callingFrame), null, new Object[]{});
+
+        o = env.get("comps");
+        if (!(o instanceof RAbstractStringVector)) {
+            return cursor;
+        }
+
+        RAbstractStringVector comps = (RAbstractStringVector) o;
+        List<String> ret = new ArrayList<>(comps.getLength());
+        for (int i = 0; i < comps.getLength(); i++) {
+            ret.add(comps.getDataAt(i));
+        }
+        Collections.sort(ret, String.CASE_INSENSITIVE_ORDER);
+        candidates.addAll(ret);
+        return start;
+    }
+
+    private int getStart(String buffer, REnvironment env, int cursor) {
+        int start = 0;
+        Object o = env.get("options");
+        if (o instanceof RList) {
+            RList opt = (RList) o;
+            start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor);
+            start = lastIdxOf(buffer, opt, "function.suffix", start, cursor);
+        }
+        start = lastIdxOf(buffer, "\"", start, cursor);
+        start = lastIdxOf(buffer, "'", start, cursor);
+        return start;
+    }
+
+    private int lastIdxOf(String buffer, RList opt, String key, int start, int cursor) {
+        int optIdx = opt.getElementIndexByName(key);
+        if (optIdx > -1) {
+            Object o = opt.getDataAt(optIdx);
+            if (o instanceof RAbstractStringVector) {
+                RAbstractStringVector v = (RAbstractStringVector) o;
+                return lastIdxOf(buffer, v.getLength() > 0 ? v.getDataAt(0) : null, start, cursor);
+            }
+        }
+        return start;
+    }
+
+    private int lastIdxOf(String buffer, String subs, int start, int cursor) {
+        if (null != subs && !subs.isEmpty()) {
+            int idx = buffer.lastIndexOf(subs, cursor);
+            if (idx == cursor) {
+                idx = buffer.lastIndexOf(subs, cursor - 1);
+            }
+            if (idx > -1) {
+                idx += subs.length();
+                return idx > start ? idx : start;
+            }
+        }
+        return start;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
index 2c6f86297d..e8f01bbdb7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
@@ -47,6 +47,7 @@ class JLineConsoleHandler implements ConsoleHandler {
     JLineConsoleHandler(RStartParams startParams, InputStream inStream, OutputStream outStream) {
         try {
             console = new ConsoleReader(inStream, outStream);
+            console.addCompleter(new JLineConsoleCompleter(this));
             console.setHandleUserInterrupt(true);
             console.setExpandEvents(false);
         } catch (IOException ex) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
new file mode 100644
index 0000000000..e7d55912a9
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.engine.shell;
+
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.engine.shell.JLineConsoleCompleter;
+import com.oracle.truffle.r.runtime.RCmdOptions;
+import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.RContext;
+import java.io.File;
+import org.junit.Test;
+
+import java.util.LinkedList;
+import org.junit.After;
+import org.junit.Assert;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+
+public class TestJLineConsoleCompleter {
+
+    private PolyglotEngine engine;
+    private ConsoleHandler consoleHandler;
+    private JLineConsoleCompleter consoleCompleter;
+
+    @Before
+    public void before() {
+        consoleHandler = new DummyConsoleHandler();
+        consoleCompleter = new JLineConsoleCompleter(consoleHandler);
+        JLineConsoleCompleter.testingMode();
+        ContextInfo info = ContextInfo.createNoRestore(RCmdOptions.Client.R, null, RContext.ContextKind.SHARE_NOTHING, null, consoleHandler);
+        engine = info.createVM(PolyglotEngine.newBuilder());
+    }
+
+    @After
+    public void dispose() {
+        if (engine != null) {
+            engine.dispose();
+        }
+    }
+
+    @Test
+    public void testCompl() {
+        assertCompl("", 0);
+        assertCompl("", 1);
+        assertCompl(" ", 1);
+
+        assertCompl("(", 0);
+        assertCompl("(", 1);
+        assertCompl("=", 1);
+        assertCompl("$", 1);
+
+        assertCompl("strt", 4, "strtoi", "strtrim");
+        assertCompl("strto", 5, "strtoi");
+        assertCompl("strtoi", 5, "strtoi");
+        assertCompl("strtoi", 4, "strtoi", "strtrim");
+        assertCompl("strto ", 6);
+
+        assertCompl("base::strt", 10, "base::strtoi", "base::strtrim");
+        assertCompl("base:::strt", 11, "base:::strtoi", "base:::strtrim");
+        assertCompl("base:::strttrt", 14, "base:::");
+
+        assertCompl("strt(", 4, "strtoi", "strtrim");
+        assertCompl("strt(", 5);
+        assertCompl("f(strt", 6, "strtoi", "strtrim");
+        assertCompl("f(base::strt", 12, "base::strtoi", "base::strtrim");
+        assertCompl("f(strt(trt", 6, "strtoi", "strtrim");
+        assertCompl("f(strt(trt", 10);
+        assertCompl("f(strt(strto", 11, "strtoi", "strtrim");
+        assertCompl("f(strt(strto", 12, "strtoi");
+
+        String noName = "_f_f_f_";
+        assertCompl(noName + ".", 7);
+        assertCompl(noName + ".", 8);
+        assertCompl(noName + "." + File.separator, 9);
+        assertCompl(noName + "'", 7);
+        assertCompl(noName + "'", 8, NOT_EMPTY);
+        assertCompl(noName + "'." + File.separator, 8, NOT_EMPTY);
+        assertCompl(noName + "'." + File.separator, 9, NOT_EMPTY);
+        assertCompl(noName + "'." + File.separator, 10, NOT_EMPTY);
+        assertCompl(noName + "\"." + File.separator, 8, NOT_EMPTY);
+    }
+
+    // e.g. check if the file path completion returned at least something
+    private static final String NOT_EMPTY = "_@_Only.Check.If.Result.Not.Empty_@_";
+
+    private void assertCompl(String buffer, int cursor, String... expected) {
+        LinkedList<CharSequence> l = new LinkedList<>();
+        consoleCompleter.complete(buffer, cursor, l);
+
+        if (expected == null || expected.length == 0) {
+            assertTrue(l.isEmpty());
+        } else if (expected.length == 1 && NOT_EMPTY.equals(expected[0])) {
+            assertFalse(l.isEmpty());
+        } else {
+            Assert.assertArrayEquals(expected, l.toArray(new CharSequence[l.size()]));
+        }
+    }
+
+    private class DummyConsoleHandler implements ConsoleHandler {
+        @Override
+        public void println(String s) {
+        }
+
+        @Override
+        public void print(String s) {
+        }
+
+        @Override
+        public void printErrorln(String s) {
+        }
+
+        @Override
+        public void printError(String s) {
+        }
+
+        @Override
+        public String readLine() {
+            return "";
+        }
+
+        @Override
+        public boolean isInteractive() {
+            return false;
+        }
+
+        @Override
+        public String getPrompt() {
+            return "";
+        }
+
+        @Override
+        public void setPrompt(String prompt) {
+        }
+
+        @Override
+        public String getInputDescription() {
+            return "";
+        }
+    }
+}
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 5e9c6ebfd3..e19d9ffd43 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -407,7 +407,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return ','.join(map(_test_subpackage, ['library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data']))
+    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data']))
 
 def _simple_unit_tests():
     return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
-- 
GitLab


From a5a52c93731124b339cfcc564998683958a96ce5 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 10 Feb 2017 17:27:47 +0100
Subject: [PATCH 010/402] implemented function 'rawConnection' and
 'rawConnectionValue'; Until now supporting basic reading and writing
 operations. However, refactorings to identify commonalities between file
 connections will be necessary.

---
 .../r/nodes/builtin/base/BasePackage.java     |   2 +
 .../builtin/base/ConnectionFunctions.java     |  52 +++++
 .../com/oracle/truffle/r/runtime/RError.java  |   4 +-
 .../r/runtime/conn/ConnectionSupport.java     |   1 +
 .../r/runtime/conn/FileConnections.java       |   2 +
 .../r/runtime/conn/RawConnections.java        | 182 ++++++++++++++++++
 6 files changed, 242 insertions(+), 1 deletion(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 9e64e26493..de8e99dfb3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -265,6 +265,8 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.ReadLines.class, ConnectionFunctionsFactory.ReadLinesNodeGen::create);
         add(ConnectionFunctions.Seek.class, ConnectionFunctionsFactory.SeekNodeGen::create);
         add(ConnectionFunctions.SocketConnection.class, ConnectionFunctionsFactory.SocketConnectionNodeGen::create);
+        add(ConnectionFunctions.RawConnection.class, ConnectionFunctionsFactory.RawConnectionNodeGen::create);
+        add(ConnectionFunctions.RawConnectionValue.class, ConnectionFunctionsFactory.RawConnectionValueNodeGen::create);
         add(ConnectionFunctions.Stderr.class, ConnectionFunctionsFactory.StderrNodeGen::create);
         add(ConnectionFunctions.Stdin.class, ConnectionFunctionsFactory.StdinNodeGen::create);
         add(ConnectionFunctions.Stdout.class, ConnectionFunctionsFactory.StdoutNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 59a02ba800..17946a59bf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -71,6 +71,7 @@ import com.oracle.truffle.r.runtime.conn.CompressedConnections.CompressedRConnec
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.FileRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection;
+import com.oracle.truffle.r.runtime.conn.RawConnections.RawRConnection;
 import com.oracle.truffle.r.runtime.conn.SocketConnections.RSocketConnection;
 import com.oracle.truffle.r.runtime.conn.TextConnections.TextRConnection;
 import com.oracle.truffle.r.runtime.conn.URLConnections.URLRConnection;
@@ -417,6 +418,57 @@ public abstract class ConnectionFunctions {
         }
     }
 
+    @RBuiltin(name = "rawConnection", kind = INTERNAL, parameterNames = {"description", "object", "open"}, behavior = IO)
+    public abstract static class RawConnection extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(RawConnection.class);
+            CastsHelper.description(casts);
+            casts.arg("object").mustBe(stringValue().or(rawValue()));
+            CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")).or(equalTo("wb")).or(equalTo("rb")))), RError.Message.UNSUPPORTED_MODE);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected RAbstractIntVector rawConnection(String description, @SuppressWarnings("unused") RAbstractStringVector text, String open) {
+            try {
+                return new RawRConnection(description, null, open).asVector();
+            } catch (IOException ex) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected RAbstractIntVector rawConnection(String description, RAbstractRawVector text, String open) {
+            try {
+                return new RawRConnection(description, text.materialize().getDataTemp(), open).asVector();
+            } catch (IOException ex) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @RBuiltin(name = "rawConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
+    public abstract static class RawConnectionValue extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(RawConnectionValue.class);
+            casts.arg("con").defaultError(Message.NOT_A_RAW_CONNECTION).mustBe(integerValue()).asIntegerVector().findFirst();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object textConnection(int con) {
+            RConnection connection = RConnection.fromIndex(con);
+            if (connection instanceof RawRConnection) {
+                return RDataFactory.createRawVector(((RawRConnection) connection).getValue());
+            } else {
+                throw RError.error(RError.SHOW_CALLER, Message.NOT_A_RAW_CONNECTION);
+            }
+        }
+    }
+
     @RBuiltin(name = "summary.connection", kind = INTERNAL, parameterNames = {"object"}, behavior = IO)
     public abstract static class Summary extends RBuiltinNode {
         private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"description", "class", "mode", "text", "opened", "can read", "can write"},
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index da3597e880..27066fb19d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -787,7 +787,9 @@ public final class RError extends RuntimeException {
         LOSS_OF_ACCURACY_MOD("probable complete loss of accuracy in modulus"),
         LENGTH_MISAPPLIED("LENGTH or similar applied to %s object"),
         TOO_MANY_ARGS("too many arguments"),
-        UNIMPLEMENTED_TYPE_IN_R("type \"%s\" unimplemented in R");
+        UNIMPLEMENTED_TYPE_IN_R("type \"%s\" unimplemented in R"),
+        NOT_AN_OUTPUT_RAW_CONNECTION("'con' is not an output rawConnection"),
+        NOT_A_RAW_CONNECTION("'con' is not a rawConnection");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 2d00f37c27..3bb1c6fed0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -313,6 +313,7 @@ public class ConnectionSupport {
         Socket("sockconn"),
         Text("textConnection"),
         URL("url"),
+        RAW("rawConnection"),
         Internal("internal");
 
         private final String printName;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 77c0e2875e..d12a2ac515 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -32,6 +32,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 import java.util.zip.GZIPInputStream;
 
 import org.tukaani.xz.XZInputStream;
@@ -42,6 +43,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.TempPathName;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
new file mode 100644
index 0000000000..ee68ecb86b
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -0,0 +1,182 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+public class RawConnections {
+
+    public static class RawRConnection extends BaseRConnection {
+
+        private byte[] data;
+
+        public RawRConnection(String description, byte[] dataTemp, String open) throws IOException {
+            super(ConnectionClass.RAW, open, AbstractOpenMode.Read);
+            this.data = dataTemp;
+            openNonLazyConnection();
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            DelegateRConnection delegate = null;
+            switch (getOpenMode().abstractOpenMode) {
+                case Read:
+                case ReadBinary:
+                    delegate = new RawReadTextRConnection(this, data);
+                    break;
+                case Write:
+                case Append:
+                    delegate = new RawWriteBinaryConnection(this);
+                    break;
+                case ReadWriteTrunc:
+                case ReadWriteTruncBinary:
+                    delegate = null;
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
+            }
+            setDelegate(delegate);
+        }
+
+        @Override
+        public String getSummaryDescription() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+        public byte[] getValue() {
+            try {
+                return ((ByteArrayOutputStream) getOutputStream()).toByteArray();
+            } catch (IOException e) {
+                throw RInternalError.shouldNotReachHere("Receiving output stream failed");
+            }
+        }
+
+    }
+
+    static class RawReadTextRConnection extends DelegateReadRConnection implements ReadWriteHelper {
+        private InputStream inputStream;
+
+        RawReadTextRConnection(BaseRConnection base, byte[] data) {
+            super(base);
+            this.inputStream = new ByteArrayInputStream(data);
+        }
+
+        RawReadTextRConnection(BaseRConnection base) {
+            super(base);
+        }
+
+        @Override
+        public int readBin(ByteBuffer buffer) throws IOException {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
+        }
+
+        @Override
+        public byte[] readBinChars() throws IOException {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
+        }
+
+        @TruffleBoundary
+        @Override
+        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+            return readLinesHelper(inputStream, n, warn, skipNul);
+        }
+
+        @Override
+        public String readChar(int nchars, boolean useBytes) throws IOException {
+            return readCharHelper(nchars, inputStream, useBytes);
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            return inputStream;
+        }
+
+        @Override
+        public void closeAndDestroy() throws IOException {
+            base.closed = true;
+            close();
+        }
+
+        @Override
+        public void close() throws IOException {
+            inputStream.close();
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_AN_OUTPUT_RAW_CONNECTION);
+        }
+    }
+
+    private static class RawWriteBinaryConnection extends DelegateWriteRConnection implements ReadWriteHelper {
+        private final OutputStream outputStream;
+
+        RawWriteBinaryConnection(BaseRConnection base) {
+            super(base);
+            outputStream = new ByteArrayOutputStream();
+        }
+
+        @Override
+        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+            writeCharHelper(outputStream, s, pad, eos);
+        }
+
+        @Override
+        public void writeBin(ByteBuffer buffer) throws IOException {
+            outputStream.write(buffer.array());
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            return outputStream;
+        }
+
+        @Override
+        public void closeAndDestroy() throws IOException {
+            base.closed = true;
+            close();
+        }
+
+        @Override
+        public void close() throws IOException {
+            flush();
+            outputStream.close();
+        }
+
+        @Override
+        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+            for (int i = 0; i < lines.getLength(); i++) {
+                String line = lines.getDataAt(i);
+                outputStream.write(line.getBytes());
+                outputStream.write(sep.getBytes());
+            }
+        }
+
+        @Override
+        public void writeString(String s, boolean nl) throws IOException {
+            writeStringHelper(outputStream, s, nl);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            outputStream.flush();
+        }
+    }
+
+}
-- 
GitLab


From d7fbd71ef9443d6ee8f746dd4396a72069b0604f Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 16 Feb 2017 17:15:09 +0100
Subject: [PATCH 011/402] fix: method 'writeChar' did not append mandatory null
 character

---
 .../truffle/r/runtime/conn/ConnectionSupport.java   | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 3bb1c6fed0..3eb19bd3cc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -302,6 +302,11 @@ public class ConnectionSupport {
              */
             return modeString;
         }
+
+        @Override
+        public String toString() {
+            return modeString;
+        }
     }
 
     public enum ConnectionClass {
@@ -880,8 +885,12 @@ public class ConnectionSupport {
                     out.write(0);
                 }
             }
-            if (eos != null && eos.length() > 0) {
-                out.write(eos.getBytes());
+            if (eos != null) {
+                if (eos.length() > 0) {
+                    out.write(eos.getBytes());
+                }
+                // function writeChar is defined to append the null character if eos != null
+                out.write(0);
             }
         }
 
-- 
GitLab


From 5353ae284833b7b42555ae50c1746c435b1aab2b Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 16 Feb 2017 17:20:29 +0100
Subject: [PATCH 012/402] Implemented rawConnections adhering to the current
 implementation style of other connections. However, already used a byte
 channel for implementation which is a preparation for a refactoring of
 connection implementations. Added class SeekableMemoryByteChannel is like a
 byte buffer but resizable. Also added unit tests; wanted to add more but read
 and write function implementations are often incomplete.

---
 .../builtin/base/ConnectionFunctions.java     |   5 +-
 .../r/runtime/conn/RawConnections.java        | 193 ++++++++++++---
 .../conn/SeekableMemoryByteChannel.java       | 224 ++++++++++++++++++
 .../truffle/r/test/ExpectedTestOutput.test    |  57 ++++-
 .../builtins/TestBuiltin_rawConnection.java   |  51 ++++
 .../connection/R/rawConnection_readBin.R      |  21 ++
 .../connection/R/rawConnection_readWriteBin.R |  12 +
 .../connection/R/rawConnection_writeBin.R     |  16 ++
 8 files changed, 537 insertions(+), 42 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 17946a59bf..c27987b063 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -425,7 +425,10 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(RawConnection.class);
             CastsHelper.description(casts);
             casts.arg("object").mustBe(stringValue().or(rawValue()));
-            CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")).or(equalTo("wb")).or(equalTo("rb")))), RError.Message.UNSUPPORTED_MODE);
+            CastsHelper.open(casts).mustBe(
+                            equalTo("").or(equalTo("r")).or(equalTo("rt")).or(equalTo("rb")).or(equalTo("r+")).or(equalTo("w")).or(equalTo("wt")).or(equalTo("wb")).or(equalTo("w+")).or(
+                                            equalTo("a")).or(equalTo("a+")),
+                            RError.Message.UNSUPPORTED_MODE);
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index ee68ecb86b..ad43d4603f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -1,11 +1,10 @@
 package com.oracle.truffle.r.runtime.conn;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
@@ -15,6 +14,7 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -23,11 +23,13 @@ public class RawConnections {
 
     public static class RawRConnection extends BaseRConnection {
 
-        private byte[] data;
+        private final SeekableMemoryByteChannel channel;
+        private final String description;
 
         public RawRConnection(String description, byte[] dataTemp, String open) throws IOException {
             super(ConnectionClass.RAW, open, AbstractOpenMode.Read);
-            this.data = dataTemp;
+            this.channel = new SeekableMemoryByteChannel(dataTemp);
+            this.description = description;
             openNonLazyConnection();
         }
 
@@ -37,15 +39,22 @@ public class RawConnections {
             switch (getOpenMode().abstractOpenMode) {
                 case Read:
                 case ReadBinary:
-                    delegate = new RawReadTextRConnection(this, data);
+                    delegate = new RawReadRConnection(this, channel);
                     break;
                 case Write:
+                case WriteBinary:
+                    delegate = new RawWriteBinaryConnection(this, channel, false);
+                    break;
                 case Append:
-                    delegate = new RawWriteBinaryConnection(this);
+                    delegate = new RawWriteBinaryConnection(this, channel, true);
+                    break;
+                case ReadAppend:
+                    delegate = new RawReadWriteConnection(this, channel, true);
                     break;
+                case ReadWrite:
                 case ReadWriteTrunc:
                 case ReadWriteTruncBinary:
-                    delegate = null;
+                    delegate = new RawReadWriteConnection(this, channel, false);
                     break;
                 default:
                     throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
@@ -55,56 +64,72 @@ public class RawConnections {
 
         @Override
         public String getSummaryDescription() {
-            // TODO Auto-generated method stub
-            return null;
+            return description;
+        }
+
+        @Override
+        public String getSummaryText() {
+            return "binary";
         }
 
         public byte[] getValue() {
-            try {
-                return ((ByteArrayOutputStream) getOutputStream()).toByteArray();
-            } catch (IOException e) {
-                throw RInternalError.shouldNotReachHere("Receiving output stream failed");
-            }
+            return channel.getBuffer();
         }
 
     }
 
-    static class RawReadTextRConnection extends DelegateReadRConnection implements ReadWriteHelper {
-        private InputStream inputStream;
+    static class RawReadRConnection extends DelegateReadRConnection implements ReadWriteHelper {
+        private SeekableMemoryByteChannel channel;
 
-        RawReadTextRConnection(BaseRConnection base, byte[] data) {
+        RawReadRConnection(BaseRConnection base, SeekableMemoryByteChannel channel) {
             super(base);
-            this.inputStream = new ByteArrayInputStream(data);
+            this.channel = channel;
+            try {
+                channel.position(0L);
+            } catch (IOException e) {
+                RInternalError.shouldNotReachHere();
+            }
         }
 
-        RawReadTextRConnection(BaseRConnection base) {
+        RawReadRConnection(BaseRConnection base) {
             super(base);
         }
 
         @Override
         public int readBin(ByteBuffer buffer) throws IOException {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
+            return channel.read(buffer);
         }
 
         @Override
         public byte[] readBinChars() throws IOException {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
+            // acquire copy from buffer without advancing the cursor
+            final byte[] buffer = channel.getBufferFromCursor();
+            int i = 0;
+            while (i < buffer.length && buffer[i] != (byte) 0) {
+                i++;
+            }
+            if (i < buffer.length) {
+                ByteBuffer readBuf = ByteBuffer.allocate(i + 1);
+                channel.read(readBuf);
+                return readBuf.array();
+            }
+            return new byte[0];
         }
 
         @TruffleBoundary
         @Override
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(inputStream, n, warn, skipNul);
+            return readLinesHelper(channel.getInputStream(), n, warn, skipNul);
         }
 
         @Override
         public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, inputStream, useBytes);
+            return readCharHelper(nchars, channel.getInputStream(), useBytes);
         }
 
         @Override
         public InputStream getInputStream() throws IOException {
-            return inputStream;
+            return channel.getInputStream();
         }
 
         @Override
@@ -115,7 +140,7 @@ public class RawConnections {
 
         @Override
         public void close() throws IOException {
-            inputStream.close();
+            channel.close();
         }
 
         @Override
@@ -125,26 +150,33 @@ public class RawConnections {
     }
 
     private static class RawWriteBinaryConnection extends DelegateWriteRConnection implements ReadWriteHelper {
-        private final OutputStream outputStream;
+        private final SeekableMemoryByteChannel channel;
 
-        RawWriteBinaryConnection(BaseRConnection base) {
+        RawWriteBinaryConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
             super(base);
-            outputStream = new ByteArrayOutputStream();
+            this.channel = Objects.requireNonNull(channel);
+            if (!append) {
+                try {
+                    channel.position(0);
+                } catch (IOException e) {
+                    RInternalError.shouldNotReachHere();
+                }
+            }
         }
 
         @Override
         public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(outputStream, s, pad, eos);
+            writeCharHelper(channel.getOutputStream(), s, pad, eos);
         }
 
         @Override
         public void writeBin(ByteBuffer buffer) throws IOException {
-            outputStream.write(buffer.array());
+            channel.write(buffer);
         }
 
         @Override
         public OutputStream getOutputStream() throws IOException {
-            return outputStream;
+            return channel.getOutputStream();
         }
 
         @Override
@@ -156,27 +188,116 @@ public class RawConnections {
         @Override
         public void close() throws IOException {
             flush();
-            outputStream.close();
+            channel.close();
         }
 
         @Override
         public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
             for (int i = 0; i < lines.getLength(); i++) {
                 String line = lines.getDataAt(i);
-                outputStream.write(line.getBytes());
-                outputStream.write(sep.getBytes());
+                channel.write(line.getBytes());
+                channel.write(sep.getBytes());
             }
         }
 
         @Override
         public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(outputStream, s, nl);
+            writeStringHelper(channel.getOutputStream(), s, nl);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            // nothing to do
+        }
+    }
+
+    private static class RawReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper {
+
+        private final SeekableMemoryByteChannel channel;
+
+        protected RawReadWriteConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
+            super(base);
+            this.channel = Objects.requireNonNull(channel);
+            if (!append) {
+                try {
+                    channel.position(0);
+                } catch (IOException e) {
+                    RInternalError.shouldNotReachHere();
+                }
+            }
+        }
+
+        @Override
+        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+            throw RInternalError.unimplemented();
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            return channel.getInputStream();
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            return channel.getOutputStream();
+        }
+
+        @Override
+        public void closeAndDestroy() throws IOException {
+            close();
+        }
+
+        @Override
+        public void close() throws IOException {
+            channel.close();
+        }
+
+        @Override
+        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+            for (int i = 0; i < lines.getLength(); i++) {
+                channel.write(lines.getDataAt(i).getBytes());
+                channel.write(sep.getBytes());
+            }
         }
 
         @Override
         public void flush() throws IOException {
-            outputStream.flush();
+            // nothing to do
+        }
+
+        @Override
+        public void writeString(String s, boolean nl) throws IOException {
+            channel.write(s.getBytes());
+            if (nl) {
+                channel.write(System.lineSeparator().getBytes());
+            }
         }
+
+        @Override
+        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+            writeCharHelper(channel.getOutputStream(), s, pad, eos);
+        }
+
+        @Override
+        public String readChar(int nchars, boolean useBytes) throws IOException {
+            throw RInternalError.unimplemented();
+        }
+
+        @Override
+        public void writeBin(ByteBuffer buffer) throws IOException {
+            channel.write(buffer);
+        }
+
+        @Override
+        public int readBin(ByteBuffer buffer) throws IOException {
+            return channel.read(buffer);
+        }
+
+        @Override
+        public byte[] readBinChars() throws IOException {
+            throw RInternalError.unimplemented();
+        }
+
     }
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
new file mode 100644
index 0000000000..1d0b946530
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -0,0 +1,224 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SeekableByteChannel;
+import java.util.Arrays;
+import java.util.Objects;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+
+/**
+ * A resizable byte channel backed by a byte array.
+ */
+public class SeekableMemoryByteChannel implements SeekableByteChannel {
+
+    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
+    /** current cursor position */
+    private long position = 0L;
+
+    /** position of the last available byte (exclusive) */
+    private long endPos = 0L;
+
+    private long offset = 0L;
+    private byte[] buf;
+    private boolean open = true;
+
+    public SeekableMemoryByteChannel(int initialCapacity) {
+        if (initialCapacity < 0) {
+            throw new IllegalArgumentException("'initialCapacity' must not be negative");
+        }
+        buf = new byte[initialCapacity];
+    }
+
+    /**
+     * Find next power of two (see Hacker's Delight).
+     * 
+     * @param n the number
+     */
+    private static int clp2(final int n) {
+        int x = n;
+        x = x - 1;
+        x = x | (x >> 1);
+        x = x | (x >> 2);
+        x = x | (x >> 4);
+        x = x | (x >> 8);
+        x = x | (x >> 16);
+        return x + 1;
+    }
+
+    public byte[] getBufferFromCursor() {
+        return Arrays.copyOfRange(buf, (int) (position - offset), (int) (endPos - offset));
+    }
+
+    public byte[] getBuffer() {
+        return Arrays.copyOfRange(buf, (int) offset, (int) (endPos - offset));
+    }
+
+    public SeekableMemoryByteChannel() {
+        this(32);
+    }
+
+    public SeekableMemoryByteChannel(byte[] initialBuffer) {
+        this(clp2(Objects.requireNonNull(initialBuffer).length));
+        assert buf.length >= initialBuffer.length;
+        endPos = initialBuffer.length;
+        position = initialBuffer.length;
+        System.arraycopy(initialBuffer, 0, buf, 0, initialBuffer.length);
+    }
+
+    @Override
+    public boolean isOpen() {
+        return open;
+    }
+
+    @Override
+    public int read(ByteBuffer dst) throws IOException {
+        if (!open) {
+            throw new ClosedChannelException();
+        }
+        Objects.requireNonNull(dst);
+        RInternalError.guarantee(dst.remaining() <= Integer.MAX_VALUE);
+        final int nCanRead = (int) Math.min(dst.remaining(), size());
+        dst.put(buf, (int) (position - offset), nCanRead);
+        position += nCanRead;
+        return nCanRead;
+    }
+
+    @Override
+    public int write(ByteBuffer src) throws IOException {
+        if (!open) {
+            throw new ClosedChannelException();
+        }
+        Objects.requireNonNull(src);
+        final int len = src.remaining();
+        ensureCapacity((int) (position - offset + len));
+        src.get(buf, (int) (position - offset), len);
+        position += len;
+        endPos = Math.max(position, endPos);
+        return len;
+    }
+
+    public int write(byte[] data) throws IOException {
+        if (!open) {
+            throw new ClosedChannelException();
+        }
+        Objects.requireNonNull(data);
+        ensureCapacity((int) (position - offset + data.length));
+        System.arraycopy(data, 0, buf, (int) (position - offset), data.length);
+        position += data.length;
+        endPos = Math.max(position, endPos);
+        return data.length;
+    }
+
+    public void write(int b) throws IOException {
+        // this is probably bad, but duplicating code is also bad and this case is probably
+        // rarely used
+        write(new byte[]{(byte) b});
+    }
+
+    private void ensureCapacity(int minCapacity) {
+        // overflow-conscious code
+        if (minCapacity - buf.length > 0)
+            grow(minCapacity);
+
+    }
+
+    private void grow(int minCapacity) {
+        // overflow-conscious code
+        int oldCapacity = buf.length;
+        int newCapacity = oldCapacity << 1;
+        if (newCapacity - minCapacity < 0)
+            newCapacity = minCapacity;
+        if (newCapacity - MAX_ARRAY_SIZE > 0)
+            newCapacity = hugeCapacity(minCapacity);
+        buf = Arrays.copyOf(buf, newCapacity);
+    }
+
+    private static int hugeCapacity(int minCapacity) {
+        if (minCapacity < 0) // overflow
+            throw new OutOfMemoryError();
+        return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
+    }
+
+    @Override
+    public long position() throws IOException {
+        return position;
+    }
+
+    @Override
+    public long size() {
+        return endPos - offset;
+    }
+
+    @Override
+    public SeekableByteChannel position(long newPosition) throws IOException {
+        if (newPosition < 0) {
+            throw new IllegalArgumentException("newPosition must not be negative");
+        }
+        position = newPosition + offset;
+        return this;
+    }
+
+    @Override
+    public SeekableByteChannel truncate(long size) throws IOException {
+        // avoid security leak by nulling previous data
+        Arrays.fill(buf, (byte) 0);
+
+        offset = 0;
+        position = 0;
+        endPos = 0;
+        return this;
+    }
+
+    @Override
+    public void close() throws IOException {
+        open = false;
+    }
+
+    public InputStream getInputStream() {
+        return new SyncIS();
+    }
+
+    private class SyncIS extends InputStream {
+
+        @Override
+        public int read() throws IOException {
+            return SeekableMemoryByteChannel.this.read();
+        }
+
+    }
+
+    public OutputStream getOutputStream() {
+        return new SyncOS();
+    }
+
+    public int read() throws IOException {
+        final ByteBuffer bf = ByteBuffer.allocate(1);
+        read(bf);
+        return bf.get();
+    }
+
+    private class SyncOS extends OutputStream {
+
+        @Override
+        public void write(int b) throws IOException {
+            SeekableMemoryByteChannel.this.write(b);
+        }
+
+        @Override
+        public void write(byte[] b) throws IOException {
+            SeekableMemoryByteChannel.this.write(b);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            SeekableMemoryByteChannel.this.write(ByteBuffer.wrap(b, off, len));
+        }
+    }
+
+}
\ No newline at end of file
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 366264daa3..8eb9faa021 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
@@ -42134,6 +42134,57 @@ numeric(0)
 #argv <- structure(list(length = 0), .Names = 'length');do.call('raw', argv)
 raw(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
+#{ rc <- rawConnection(raw(0), "a+"); close(rc); write(charToRaw("A"), rc) }
+Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
+  invalid connection
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 48 65 6c 6c 6f 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34
+[26] 0a
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] "Hello2c 20 57 6f 72\n6c 64\n"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] "Hello, World"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
+#{ rc <- rawConnection(raw(0), "r+"); close(rc); write(charToRaw("A"), rc) }
+Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
+  invalid connection
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34 0a
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] "2c 20 57 6f 72\n6c 64\n"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
+[1] 2c 20 57 6f 72 6c 64 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] ", World"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteText#
+#{ rc <- rawConnection(raw(0), "w"); writeChar("Hello", rc); writeChar(", World", rc); rawConnectionValue(rc) }
+ [1] 48 65 6c 6c 6f 00 2c 20 57 6f 72 6c 64 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteText#
+#{ s <- "äöüß"; rc <- rawConnection(raw(0), "w"); writeChar(s, rc); rawConnectionValue(rc) }
+[1] c3 a4 c3 b6 c3 bc c3 9f 00
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawShift.testrawShift1#
 #argv <- structure(list(x = as.raw(c(0, 1, 32, 127, 128, 255, 123)), n = -1.1), .Names = c('x', 'n'));do.call('rawShift', argv)
 [1] 00 00 10 3f 40 7f 3d
@@ -73178,7 +73229,7 @@ f first 1
 #{f<-function(x){UseMethod("f")};f.logical<-function(x){print("logical")};f(TRUE)}
 [1] "logical"
 
-##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#Ignored.Unknown#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R") }
 
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#Ignored.Unknown#
@@ -73198,10 +73249,6 @@ f first 1
 NULL
 [1] "exit fun0"
 
-##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
-#myCondition <- function(message, call=NULL)<<<NEWLINE>>> structure(list(message=message, call=call),<<<NEWLINE>>> class=c("myCondition", "condition"))<<<NEWLINE>>>tryCatch(signalCondition(myCondition("foo")),<<<NEWLINE>>> myCondition=function(cond) {cat("<my>");123L})
-<my>[1] 123
-
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
 #{ e <- simpleError("test error"); f <- function() { tryCatch(1, finally = print("Hello")); stop(e)}; f() }
 [1] "Hello"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
new file mode 100644
index 0000000000..759a3c0d37
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
@@ -0,0 +1,51 @@
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestRBase;
+
+// Checkstyle: stop line length check
+public class TestBuiltin_rawConnection extends TestRBase {
+
+    @Override
+    protected String getTestDir() {
+        return "builtins/connection";
+    }
+
+    @Test
+    public void testReadAppendText() {
+
+        assertEval("{ rc <- rawConnection(raw(0), \"a+\"); close(rc); write(charToRaw(\"A\"), rc) }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+    }
+
+    @Test
+    public void testReadWriteText() {
+
+        assertEval("{ rc <- rawConnection(raw(0), \"r+\"); close(rc); write(charToRaw(\"A\"), rc) }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+    }
+
+    @Test
+    public void testWriteText() {
+
+        assertEval("{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"w\"); writeChar(s, rc); rawConnectionValue(rc) }");
+        assertEval("{ rc <- rawConnection(raw(0), \"w\"); writeChar(\"Hello\", rc); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
+    }
+
+    @Test
+    public void testWriteBinary() {
+
+        // this test is currently ignored, since 'charToRaw' is not compliant
+        assertEval(Ignored.Unknown, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval(Output.IgnoreWarningContext,
+                        "{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R
new file mode 100644
index 0000000000..cbcaa99672
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R
@@ -0,0 +1,21 @@
+zz <- rawConnection(raw(0), "wb")
+writeBin(1:10, zz)
+writeBin(pi, zz)
+writeBin(pi, zz)
+writeBin(pi^2, zz)
+writeBin(pi+3i, zz)
+writeBin("A test of a connection", zz)
+z <- paste("A very long string", 1:100, collapse = " + ")
+writeBin(z, zz)
+res <- rawConnectionValue(zz)
+close(zz)
+
+zz <- rawConnection(res, "rb")
+readBin(zz, integer())
+readBin(zz, integer())
+readBin(zz, numeric())
+readBin(zz, complex())
+readBin(zz, character())
+z2 <- readBin(zz, character())
+close(zz)
+z2
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R
new file mode 100644
index 0000000000..3731f5f219
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R
@@ -0,0 +1,12 @@
+## signed vs unsigned ints
+len <- 100000
+zz <- rawConnection(raw(0), "wb")
+x <- as.raw((1:len) %% 255)
+writeBin(x, zz)
+res <- rawConnectionValue(zz)
+close(zz)
+
+zz <- rawConnection(res, "rb")
+res1 <- readBin(zz, "raw", len)
+close(zz)
+Reduce(`&&`, res == res1, TRUE)
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R
new file mode 100644
index 0000000000..62ad8c98d4
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R
@@ -0,0 +1,16 @@
+zz <- rawConnection(raw(0), "wb")
+writeBin(1:10, zz)
+writeBin(pi, zz, endian = "swap")
+writeBin(pi, zz, size = 4)
+writeBin(pi^2, zz, size = 4, endian = "swap")
+writeBin(pi+3i, zz)
+writeBin("A test of a connection", zz)
+z <- paste("A very long string", 1:100, collapse = " + ")
+writeBin(z, zz)
+if(.Machine$sizeof.long == 8 || .Machine$sizeof.longlong == 8)
+    writeBin(as.integer(5^(1:10)), zz, size = 8)
+if((s <- .Machine$sizeof.longdouble) > 8)
+    writeBin((pi/3)^(1:10), zz, size = s)
+res <- rawConnectionValue(zz)
+close(zz)
+res
\ No newline at end of file
-- 
GitLab


From ca5af1dfb15c44373a158c1f310b33e59d8f59b0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 16 Feb 2017 17:59:19 +0100
Subject: [PATCH 013/402] Generated expected output. Fixed some more bugs in
 method 'writeChar'. Added more tests for rawConnections.

---
 .../builtin/base/ConnectionFunctions.java     | 27 +++++++----
 .../com/oracle/truffle/r/runtime/RError.java  |  2 +-
 .../r/runtime/conn/RawConnections.java        | 22 +++++++++
 .../conn/SeekableMemoryByteChannel.java       | 48 ++++++++++++++-----
 .../truffle/r/test/ExpectedTestOutput.test    | 24 +++++++++-
 .../builtins/TestBuiltin_rawConnection.java   | 22 +++++++++
 6 files changed, 124 insertions(+), 21 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index c27987b063..024c5bfa62 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -748,19 +748,25 @@ public abstract class ConnectionFunctions {
             CastsHelper.useBytes(casts);
         }
 
-        @TruffleBoundary
         @Specialization
         protected RNull writeChar(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
+            return writeCharGeneric(object, con, nchars, sep, useBytes);
+        }
+
+        @TruffleBoundary
+        private RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wb")) {
                 int length = object.getLength();
                 for (int i = 0; i < length; i++) {
-                    String s = object.getDataAt(i);
+                    // FIXME: 'i % length' is probably wrong
                     int nc = nchars.getDataAt(i % length);
+                    String s = object.getDataAt(i);
+                    final int writeLen = Math.min(s.length(), nc);
                     int pad = nc - s.length();
                     if (pad > 0) {
                         RError.warning(this, RError.Message.MORE_CHARACTERS);
                     }
-                    openConn.writeChar(s, pad, sep.getDataAt(i % length), useBytes);
+                    openConn.writeChar(s.substring(0, writeLen), pad, getSepFor(sep, i), useBytes);
                 }
             } catch (IOException x) {
                 throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
@@ -768,11 +774,16 @@ public abstract class ConnectionFunctions {
             return RNull.instance;
         }
 
-        @SuppressWarnings("unused")
-        @TruffleBoundary
+        private static String getSepFor(RAbstractStringVector sep, int i) {
+            if (sep != null) {
+                return sep.getDataAt(i % sep.getLength());
+            }
+            return null;
+        }
+
         @Specialization
-        protected RNull writeChar(RAbstractStringVector object, int con, RAbstractIntVector nchars, RNull sep, boolean useBytes) {
-            throw RError.nyi(this, "writeChar(sep=NULL)");
+        protected RNull writeChar(RAbstractStringVector object, int con, RAbstractIntVector nchars, @SuppressWarnings("unused") RNull sep, boolean useBytes) {
+            return writeCharGeneric(object, con, nchars, null, useBytes);
         }
     }
 
@@ -929,7 +940,7 @@ public abstract class ConnectionFunctions {
             int s = 0;
             while (s < n) {
                 byte[] chars = con.readBinChars();
-                if (chars == null) {
+                if (chars == null || chars.length == 0) {
                     break;
                 }
                 int npos = 0;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 27066fb19d..4a1889bfca 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -336,7 +336,7 @@ public final class RError extends RuntimeException {
         NOT_A_TEXT_CONNECTION("'con' is not a textConnection"),
         UNSEEKABLE_CONNECTION("'con' is not seekable"),
         MUST_BE_STRING_OR_CONNECTION("'%s' must be a character string or a connection"),
-        MORE_CHARACTERS("more characters requested than are in the string - will zero-pad"),
+        MORE_CHARACTERS("writeChar: more characters requested than are in the string - will zero-pad"),
         TOO_FEW_LINES_READ_LINES("too few lines read in readLineWRITE_ONs"),
         INVALID_CONNECTION("invalid connection"),
         OUT_OF_RANGE("out-of-range values treated as 0 in coercion to raw"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index ad43d4603f..96cc3ad9cd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
index 1d0b946530..dbf3a84ef6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
@@ -18,10 +40,10 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
 
     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 
-    /** current cursor position */
+    /** Current cursor position. */
     private long position = 0L;
 
-    /** position of the last available byte (exclusive) */
+    /** Position of the last available byte (exclusive). */
     private long endPos = 0L;
 
     private long offset = 0L;
@@ -37,7 +59,7 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
 
     /**
      * Find next power of two (see Hacker's Delight).
-     * 
+     *
      * @param n the number
      */
     private static int clp2(final int n) {
@@ -122,26 +144,30 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
     }
 
     private void ensureCapacity(int minCapacity) {
-        // overflow-conscious code
-        if (minCapacity - buf.length > 0)
+        // borrowed from ByteArrayOutputStream
+        if (minCapacity - buf.length > 0) {
             grow(minCapacity);
-
+        }
     }
 
     private void grow(int minCapacity) {
-        // overflow-conscious code
+        // borrowed from ByteArrayOutputStream
         int oldCapacity = buf.length;
         int newCapacity = oldCapacity << 1;
-        if (newCapacity - minCapacity < 0)
+        if (newCapacity - minCapacity < 0) {
             newCapacity = minCapacity;
-        if (newCapacity - MAX_ARRAY_SIZE > 0)
+        }
+        if (newCapacity - MAX_ARRAY_SIZE > 0) {
             newCapacity = hugeCapacity(minCapacity);
+        }
         buf = Arrays.copyOf(buf, newCapacity);
     }
 
     private static int hugeCapacity(int minCapacity) {
-        if (minCapacity < 0) // overflow
+        // borrowed from ByteArrayOutputStream
+        if (minCapacity < 0) {
             throw new OutOfMemoryError();
+        }
         return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
     }
 
@@ -221,4 +247,4 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
         }
     }
 
-}
\ No newline at end of file
+}
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 8eb9faa021..0a9f202a00 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
@@ -42134,6 +42134,15 @@ numeric(0)
 #argv <- structure(list(length = 0), .Names = 'length');do.call('raw', argv)
 raw(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R") }
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R") }
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
 #{ rc <- rawConnection(raw(0), "a+"); close(rc); write(charToRaw("A"), rc) }
 Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
@@ -42177,8 +42186,21 @@ Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
 #{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
 [1] ", World"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteBinary#Ignored.Unknown#
+#{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteBinary#Output.IgnoreWarningContext#
+#{ zz <- rawConnection(raw(0), "wb"); x <- c("a", "this will be truncated", "abc"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = "\r\n"); res <- rawConnectionValue(zz); close(zz); res }
+ [1] 61 00 00 74 68 69 73 20 77 69 6c 6c 20 61 62 63 61 0d 0a 00 74 68 69 73 20
+[26] 77 69 6c 6c 20 62 65 20 74 72 75 6e 63 61 74 65 64 0d 0a 00 61 62 63 0d 0a
+[51] 00
+Warning message:
+In writeChar(x, zz, nc, eos = NULL) :
+  writeChar: more characters requested than are in the string - will zero-pad
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteText#
-#{ rc <- rawConnection(raw(0), "w"); writeChar("Hello", rc); writeChar(", World", rc); rawConnectionValue(rc) }
+#{ rc <- rawConnection(raw(0), "w"); writeChar("Hello", rc); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
  [1] 48 65 6c 6c 6f 00 2c 20 57 6f 72 6c 64 00
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteText#
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
index 759a3c0d37..e4de9fa076 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.test.builtins;
 
 import org.junit.Test;
-- 
GitLab


From fb479bb9546b56e64b48dfb4d5b21b6ee537a9b1 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 16 Feb 2017 09:46:35 -0800
Subject: [PATCH 014/402] [GR-2857] Fix location of gnur Rscript under graalvm
 testing.

---
 .../r/install.cran.packages.R                 | 22 +++++++++++++++----
 mx.fastr/mx_fastr_pkgs.py                     | 21 +++++++++++++-----
 2 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R b/com.oracle.truffle.r.test.cran/r/install.cran.packages.R
index a92c95ff4a..a9e905e9a5 100644
--- a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R
+++ b/com.oracle.truffle.r.test.cran/r/install.cran.packages.R
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -684,10 +684,24 @@ install.pkg <- function(pkgname) {
 	return(rc)
 }
 
+# when testing under graalvm, fastr is not built so we must use the (assumed) sibling gnur repo
+check_graalvm <- function() {
+	if (!is.na(Sys.getenv('FASTR_GRAALVM', unset=NA)) || !is.na(Sys.getenv('GRAALVM_FASTR', unset=NA))) {
+		normalizePath(Sys.glob(file.path("..", 'gnur', 'gnur', 'R-*')))
+	} else {
+		NA
+	}
+}
+
 gnu_rscript <- function() {
-	rv <- R.Version()
-	dirv <- paste0('R-', rv$major, '.', rv$minor)
-	file.path("com.oracle.truffle.r.native/gnur", dirv, 'bin/Rscript')
+	gnur_dir <- check_graalvm()
+	if (!is.na(gnur_dir)) {
+		file.path(gnur_dir, 'bin', 'Rscript')
+	} else {
+		rv <- R.Version()
+		dirv <- paste0('R-', rv$major, '.', rv$minor)
+		file.path("com.oracle.truffle.r.native/gnur", dirv, 'bin', 'Rscript')
+	}
 }
 
 system.install <- function(pkgname) {
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index 874dbf5e65..730622e8a3 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 The pkgtest command operates in two modes:
 1. In development mode it uses the FastR 'Rscript' command and the internal GNU R for test comparison
 2. In production mode it uses the GraalVM 'Rscript' command and a GNU R loaded as a sibling suite. This is indicated
-by the environment variable 'GRAALVM_FASTR' being set.
+by the environment variable 'FASTR_GRAALVM' being set. (GRAALVM_FASTR is also accepted for backwards cmpatibility)
 
 Evidently in case 2, there is the potential for a version mismatch between FastR and GNU R, and this is checked.
 
@@ -48,17 +48,28 @@ def _mx_gnur():
     return mx.suite('gnur')
 
 def _gnur_rscript():
+    '''
+    returns path to Rscript in sibling gnur directory
+    '''
     return _mx_gnur().extensions._gnur_rscript_path()
 
 def _graalvm_rscript():
     assert graalvm is not None
     return join(graalvm, 'bin', 'Rscript')
 
+def _check_graalvm():
+    if os.environ.has_key('FASTR_GRAALVM'):
+        return os.environ['FASTR_GRAALVM']
+    elif os.environ.has_key('GRAALVM_FASTR'):
+        return os.environ['GRAALVM_FASTR']
+    else:
+        return None
+
 def _graalvm():
     global graalvm
     if graalvm is None:
-        if os.environ.has_key('GRAALVM_FASTR'):
-            graalvm = os.environ['GRAALVM_FASTR']
+        graalvm = _check_graalvm()
+        if graalvm:
             # version check
             gnur_version = _mx_gnur().extensions.r_version().split('-')[1]
             graalvm_version = subprocess.check_output([_graalvm_rscript(), '--version'], stderr=subprocess.STDOUT).rstrip()
@@ -106,7 +117,7 @@ def _installpkgs(args, **kwargs):
     '''
     Runs the R script that does package/installation and testing.
     If we are running in a binary graalvm environment, which is indicated
-    by the GRAALVM_FASTR environment variable, we can't use mx to invoke
+    by the FASTR_GRAALVM environment variable, we can't use mx to invoke
     FastR, but instead have to invoke the command directly.
     '''
     script = _installpkgs_script()
-- 
GitLab


From 77bb425c7ff5fee50670a8a1d8a8db0ad9dc42d1 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 16 Feb 2017 13:18:55 -0800
Subject: [PATCH 015/402] [GR-2527] Complete Nodification of RFFI interfaces

---
 .../r/nodes/builtin/base/LaFunctions.java     |  83 ++++++-----
 .../truffle/r/nodes/builtin/base/Sum.java     |   7 +-
 .../r/nodes/builtin/base/foreign/Dqrcf.java   |   4 +-
 .../r/nodes/builtin/base/foreign/Dqrdc2.java  |   4 +-
 .../r/nodes/builtin/fastr/FastrDqrls.java     |   4 +-
 .../truffle/r/runtime/ffi/jni/JNI_Lapack.java | 109 ++++++++++++---
 .../truffle/r/runtime/ffi/jni/JNI_Misc.java   |  25 ++--
 .../truffle/r/runtime/ffi/jni/JNI_RAppl.java  |  30 +++-
 .../truffle/r/runtime/ffi/LapackRFFI.java     | 129 ++++++++++++++++--
 .../truffle/r/runtime/ffi/MiscRFFI.java       |  14 +-
 .../truffle/r/runtime/ffi/RApplRFFI.java      |  33 ++++-
 11 files changed, 340 insertions(+), 102 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 1a27658726..3be554555f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -67,26 +67,24 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  */
 public class LaFunctions {
 
-    protected abstract static class Adapter extends RBuiltinNode {
-        @Child protected LapackRFFI.LapackRFFINode lapackRFFINode = RFFIFactory.getRFFI().getLapackRFFI().createLapackRFFINode();
-    }
-
     @RBuiltin(name = "La_version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class Version extends Adapter {
+    public abstract static class Version extends RBuiltinNode {
+        @Child LapackRFFI.IlaverNode ilaverNode = RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode();
+
         @Specialization
         @TruffleBoundary
         protected String doVersion() {
             int[] version = new int[3];
-            lapackRFFINode.ilaver(version);
+            ilaverNode.execute(version);
             return version[0] + "." + version[1] + "." + version[2];
         }
     }
 
-    private abstract static class RsgAdapter extends Adapter {
+    private abstract static class RsgRBuiltinNode extends RBuiltinNode {
         protected static final String[] NAMES = new String[]{"values", "vectors"};
         protected final BranchProfile errorProfile = BranchProfile.create();
 
-        protected static Casts createCasts(Class<? extends RsgAdapter> extClass) {
+        protected static Casts createCasts(Class<? extends RsgRBuiltinNode> extClass) {
             Casts casts = new Casts(extClass);
             casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_NUMERIC, "x");
             casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().notNA().map(toBoolean());
@@ -95,7 +93,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_rg", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE)
-    public abstract static class Rg extends RsgAdapter {
+    public abstract static class Rg extends RsgRBuiltinNode {
 
         private final ConditionProfile hasComplexValues = ConditionProfile.createBinaryProfile();
 
@@ -105,7 +103,8 @@ public class LaFunctions {
 
         @Specialization
         protected Object doRg(RDoubleVector matrix, boolean onlyValues,
-                        @Cached("create()") GetDimAttributeNode getDimsNode) {
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") LapackRFFI.DgeevNode dgeevNode) {
             int[] dims = getDimsNode.getDimensions(matrix);
             // copy array component of matrix as Lapack destroys it
             int n = dims[0];
@@ -123,7 +122,7 @@ public class LaFunctions {
             double[] wi = new double[n];
             double[] work = new double[1];
             // ask for optimal size of work array
-            int info = lapackRFFINode.dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1);
+            int info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1);
             if (info != 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev");
@@ -131,7 +130,7 @@ public class LaFunctions {
             // now allocate work array and make the actual call
             int lwork = (int) work[0];
             work = new double[lwork];
-            info = lapackRFFINode.dgeev(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork);
+            info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork);
             if (info != 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev");
@@ -196,7 +195,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_rs", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE)
-    public abstract static class Rs extends RsgAdapter {
+    public abstract static class Rs extends RsgRBuiltinNode {
 
         static {
             createCasts(Rs.class);
@@ -204,7 +203,8 @@ public class LaFunctions {
 
         @Specialization
         protected Object doRs(RDoubleVector matrix, boolean onlyValues,
-                        @Cached("create()") GetDimAttributeNode getDimsNode) {
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") LapackRFFI.DsyevrNode dsyevrNode) {
             int[] dims = getDimsNode.getDimensions(matrix);
             int n = dims[0];
             char jobv = onlyValues ? 'N' : 'V';
@@ -229,7 +229,7 @@ public class LaFunctions {
             int[] isuppz = new int[2 * n];
             double[] work = new double[1];
             int[] iwork = new int[1];
-            int info = lapackRFFINode.dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
+            int info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
             if (info != 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr");
@@ -238,7 +238,7 @@ public class LaFunctions {
             liwork = iwork[0];
             work = new double[lwork];
             iwork = new int[liwork];
-            info = lapackRFFINode.dsyevr(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
+            info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
             if (info != 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr");
@@ -258,7 +258,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_qr", kind = INTERNAL, parameterNames = {"in"}, behavior = PURE)
-    public abstract static class Qr extends Adapter {
+    public abstract static class Qr extends RBuiltinNode {
 
         @CompilationFinal private static final String[] NAMES = new String[]{"qr", "rank", "qraux", "pivot"};
 
@@ -272,7 +272,8 @@ public class LaFunctions {
         @Specialization
         protected RList doQr(RAbstractDoubleVector aIn,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
-                        @Cached("create()") SetDimAttributeNode setDimsNode) {
+                        @Cached("create()") SetDimAttributeNode setDimsNode,
+                        @Cached("create()") LapackRFFI.Dgeqp3Node dgeqp3Node) {
             // This implementation is sufficient for B25 matcal-5.
             if (!(aIn instanceof RDoubleVector)) {
                 RError.nyi(this, "non-real vectors not supported (yet)");
@@ -287,14 +288,14 @@ public class LaFunctions {
             double[] tau = new double[m < n ? m : n];
             double[] work = new double[1];
             // ask for optimal size of work array
-            int info = lapackRFFINode.dgeqp3(m, n, a, m, jpvt, tau, work, -1);
+            int info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, -1);
             if (info < 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3");
             }
             int lwork = (int) work[0];
             work = new double[lwork];
-            info = lapackRFFINode.dgeqp3(m, n, a, m, jpvt, tau, work, lwork);
+            info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, lwork);
             if (info < 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3");
@@ -313,7 +314,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "qr_coef_real", kind = INTERNAL, parameterNames = {"q", "b"}, behavior = PURE)
-    public abstract static class QrCoefReal extends Adapter {
+    public abstract static class QrCoefReal extends RBuiltinNode {
 
         private final BranchProfile errorProfile = BranchProfile.create();
 
@@ -329,7 +330,9 @@ public class LaFunctions {
         @Specialization
         protected RDoubleVector doQrCoefReal(RList qIn, RDoubleVector bIn,
                         @Cached("create()") GetDimAttributeNode getBDimsNode,
-                        @Cached("create()") GetDimAttributeNode getQDimsNode) {
+                        @Cached("create()") GetDimAttributeNode getQDimsNode,
+                        @Cached("create()") LapackRFFI.DormqrNode dormqrNode,
+                        @Cached("create()") LapackRFFI.DtrtrsNode dtrtrsNode) {
             // If bIn was coerced this extra copy is unnecessary
             RDoubleVector b = (RDoubleVector) bIn.copy();
 
@@ -353,19 +356,19 @@ public class LaFunctions {
             // we work directly in the internal data of b
             double[] bData = b.getDataWithoutCopying();
             // ask for optimal size of work array
-            int info = lapackRFFINode.dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1);
+            int info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1);
             if (info < 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr");
             }
             int lwork = (int) work[0];
             work = new double[lwork];
-            info = lapackRFFINode.dormqr(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork);
+            info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork);
             if (info < 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr");
             }
-            info = lapackRFFINode.dtrtrs('U', 'N', 'N', k, nrhs, qrData, n, bData, n);
+            info = dtrtrsNode.execute('U', 'N', 'N', k, nrhs, qrData, n, bData, n);
             if (info < 0) {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dtrtrs");
@@ -376,7 +379,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "det_ge_real", kind = INTERNAL, parameterNames = {"a", "uselog"}, behavior = PURE)
-    public abstract static class DetGeReal extends Adapter {
+    public abstract static class DetGeReal extends RBuiltinNode {
 
         private static final RStringVector NAMES_VECTOR = RDataFactory.createStringVector(new String[]{"modulus", "sign"}, RDataFactory.COMPLETE_VECTOR);
         private static final RStringVector DET_CLASS = RDataFactory.createStringVector(new String[]{"det"}, RDataFactory.COMPLETE_VECTOR);
@@ -397,14 +400,15 @@ public class LaFunctions {
 
         @Specialization
         protected RList doDetGeReal(RDoubleVector aIn, boolean useLog,
-                        @Cached("create()") GetDimAttributeNode getDimsNode) {
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") LapackRFFI.DgetrfNode dgetrfNode) {
             RDoubleVector a = (RDoubleVector) aIn.copy();
             int[] aDims = getDimsNode.getDimensions(aIn);
             int n = aDims[0];
             int[] ipiv = new int[n];
             double modulus = 0;
             double[] aData = a.getDataWithoutCopying();
-            int info = lapackRFFINode.dgetrf(n, n, aData, n, ipiv);
+            int info = dgetrfNode.execute(n, n, aData, n, ipiv);
             int sign = 1;
             if (info < 0) {
                 errorProfile.enter();
@@ -458,7 +462,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_chol", kind = INTERNAL, parameterNames = {"a", "pivot", "tol"}, behavior = PURE)
-    public abstract static class LaChol extends Adapter {
+    public abstract static class LaChol extends RBuiltinNode {
 
         private final BranchProfile errorProfile = BranchProfile.create();
         private final ConditionProfile noPivot = ConditionProfile.createBinaryProfile();
@@ -480,7 +484,9 @@ public class LaFunctions {
         protected RDoubleVector doDetGeReal(RDoubleVector aIn, boolean piv, double tol,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                        @Cached("create()") GetDimNamesAttributeNode getDimNamesNode) {
+                        @Cached("create()") GetDimNamesAttributeNode getDimNamesNode,
+                        @Cached("create()") LapackRFFI.DpotrfNode dpotrfNode,
+                        @Cached("create()") LapackRFFI.DpstrfNode dpstrfNode) {
             RDoubleVector a = (RDoubleVector) aIn.copy();
             int[] aDims = getDimsNode.getDimensions(aIn);
             int n = aDims[0];
@@ -494,7 +500,7 @@ public class LaFunctions {
             }
             int info;
             if (noPivot.profile(!piv)) {
-                info = lapackRFFINode.dpotrf('U', m, aData, m);
+                info = dpotrfNode.execute('U', m, aData, m);
                 if (info != 0) {
                     errorProfile.enter();
                     // TODO informative error message (aka GnuR)
@@ -504,7 +510,7 @@ public class LaFunctions {
                 int[] ipiv = new int[m];
                 double[] work = new double[2 * m];
                 int[] rank = new int[1];
-                info = lapackRFFINode.dpstrf('U', n, aData, n, ipiv, rank, tol, work);
+                info = dpstrfNode.execute('U', n, aData, n, ipiv, rank, tol, work);
                 if (info != 0) {
                     errorProfile.enter();
                     // TODO informative error message (aka GnuR)
@@ -527,7 +533,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_solve", kind = INTERNAL, parameterNames = {"a", "bin", "tolin"}, behavior = PURE)
-    public abstract static class LaSolve extends Adapter {
+    public abstract static class LaSolve extends RBuiltinNode {
         @Child private CastDoubleNode castDouble = CastDoubleNodeGen.create(false, false, false);
 
         private static Function<RAbstractDoubleVector, Object> getDimVal(int dim) {
@@ -552,7 +558,10 @@ public class LaFunctions {
                         @Cached("create()") SetDimNamesAttributeNode setBDimNamesNode,
                         @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
                         @Cached("create()") GetDimNamesAttributeNode getBinDimNamesNode,
-                        @Cached("create()") SetNamesAttributeNode setNamesNode) {
+                        @Cached("create()") SetNamesAttributeNode setNamesNode,
+                        @Cached("create()") LapackRFFI.DgesvNode dgesvNode,
+                        @Cached("create()") LapackRFFI.DgeconNode dgeconNode,
+                        @Cached("create()") LapackRFFI.DlangeNode dlangeNode) {
             int[] aDims = getADimsNode.getDimensions(a);
             int n = aDims[0];
             if (n == 0) {
@@ -618,7 +627,7 @@ public class LaFunctions {
                 assert aDouble != a;
                 avals = aDouble.getInternalStore();
             }
-            int info = lapackRFFINode.dgesv(n, p, avals, n, ipiv, bData, n);
+            int info = dgesvNode.execute(n, p, avals, n, ipiv, bData, n);
             if (info < 0) {
                 RError.error(this, RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv");
             }
@@ -626,10 +635,10 @@ public class LaFunctions {
                 RError.error(this, RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
             }
             if (tol > 0) {
-                double anorm = lapackRFFINode.dlange('1', n, n, avals, n, null);
+                double anorm = dlangeNode.execute('1', n, n, avals, n, null);
                 double[] work = new double[4 * n];
                 double[] rcond = new double[1];
-                lapackRFFINode.dgecon('1', n, avals, n, anorm, rcond, work, ipiv);
+                dgeconNode.execute('1', n, avals, n, anorm, rcond, work, ipiv);
                 if (rcond[0] < tol) {
                     RError.error(this, RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]);
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
index b8a914baf1..bcb41b2534 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
@@ -78,12 +78,13 @@ public abstract class Sum extends RBuiltinNode {
                     @Cached("create()") VectorLengthProfile lengthProfile,
                     @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
                     @Cached("create()") NACheck na,
-                    @Cached("createBinaryProfile()") ConditionProfile needsExactSumProfile) {
+                    @Cached("createBinaryProfile()") ConditionProfile needsExactSumProfile,
+                    @Cached("create()") MiscRFFI.ExactSumNode exactSumNode) {
         RDoubleVector vector = (RDoubleVector) args.getArgument(0);
         int length = lengthProfile.profile(vector.getLength());
 
         if (needsExactSumProfile.profile(length >= 3)) {
-            return RFFIFactory.getRFFI().getMiscRFFI().exactSum(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm);
+            return exactSumNode.execute(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm);
         } else {
             na.enable(vector);
             loopProfile.profileCounted(length);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
index d10efffa16..3ef382aa94 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
@@ -27,7 +27,7 @@ import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
 public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 {
-    @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode();
+    @Child private RApplRFFI.DqrcfNode dqcrfNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrcfNode();
 
     private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE;
     private static final RStringVector DQRCF_NAMES = RDataFactory.createStringVector(new String[]{E, E, E, E, E, E, "coef", "info"}, RDataFactory.COMPLETE_VECTOR);
@@ -52,7 +52,7 @@ public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 {
             double[] y = yVec.materialize().getDataTemp();
             double[] b = bVec.materialize().getDataTemp();
             int[] info = infoVec.materialize().getDataTemp();
-            rApplRFFINode.dqrcf(x, nx, k, qraux, y, ny, b, info);
+            dqcrfNode.execute(x, nx, k, qraux, y, ny, b, info);
             RDoubleVector coef = RDataFactory.createDoubleVector(b, RDataFactory.COMPLETE_VECTOR);
             coef.copyAttributesFrom(bVec);
             // @formatter:off
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
index a188007010..b546af2735 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
 public abstract class Dqrdc2 extends RExternalBuiltinNode.Arg9 {
-    @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode();
+    @Child private RApplRFFI.Dqrdc2Node dqrdc2Node = RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node();
 
     private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE;
     private static final RStringVector DQRDC2_NAMES = RDataFactory.createStringVector(new String[]{"qr", E, E, E, E, "rank", "qraux", "pivot", E}, RDataFactory.COMPLETE_VECTOR);
@@ -57,7 +57,7 @@ public abstract class Dqrdc2 extends RExternalBuiltinNode.Arg9 {
         int[] rank = rankVec.materialize().getDataTemp();
         double[] qraux = qrauxVec.materialize().getDataTemp();
         int[] pivot = pivotVec.materialize().getDataTemp();
-        rApplRFFINode.dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, workVec.materialize().getDataCopy());
+        dqrdc2Node.execute(x, ldx, n, p, tol, rank, qraux, pivot, workVec.materialize().getDataCopy());
         // @formatter:off
         Object[] data = new Object[]{
                     RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR, getDimNode.getDimensions(xVec)),
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
index fb4cc5a0b3..badecba152 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
  */
 @RBuiltin(name = ".fastr.dqrls", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x", "n", "p", "y", "ny", "tol", "coeff"}, behavior = PURE)
 public abstract class FastrDqrls extends RBuiltinNode {
-    @Child private RApplRFFI.RApplRFFINode rApplRFFINode = RFFIFactory.getRFFI().getRApplRFFI().createRApplRFFINode();
+    @Child private RApplRFFI.DqrlsNode dqrlsNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode();
 
     private static final String[] NAMES = new String[]{"qr", "coefficients", "residuals", "effects", "rank", "pivot", "qraux", "tol", "pivoted"};
     private static RStringVector namesVector = null;
@@ -78,7 +78,7 @@ public abstract class FastrDqrls extends RBuiltinNode {
             pivot[i] = i + 1;
         }
 
-        rApplRFFINode.dqrls(x, n, p, y, ny, tol, coeff, residuals, effects, rank, pivot, qraux, work);
+        dqrlsNode.execute(x, n, p, y, ny, tol, coeff, residuals, effects, rank, pivot, qraux, work);
 
         RDoubleVector resultCoeffVect = RDataFactory.createDoubleVector(coeff, RDataFactory.COMPLETE_VECTOR);
         resultCoeffVect.copyAttributesFrom(coeffVec);
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
index 7b0a29a0be..798c393675 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,83 +26,160 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 
 public class JNI_Lapack implements LapackRFFI {
-    private static class JNI_LapackRFFINode extends LapackRFFINode {
+    private static class JNI_IlaverNode extends IlaverNode {
         @Override
         @TruffleBoundary
-        public void ilaver(int[] version) {
+        public void execute(int[] version) {
             native_ilaver(version);
         }
+    }
 
+    private static class JNI_DgeevNode extends DgeevNode {
         @Override
         @TruffleBoundary
-        public int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
+        public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
             return native_dgeev(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork);
         }
+    }
 
+    private static class JNI_Dgeqp3Node extends Dgeqp3Node {
         @Override
         @TruffleBoundary
-        public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
+        public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
             return native_dgeqp3(m, n, a, lda, jpvt, tau, work, lwork);
         }
+    }
 
+    private static class JNI_DormqrNode extends DormqrNode {
         @Override
         @TruffleBoundary
-        public int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+        public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
             return native_dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork);
         }
+    }
 
+    private static class JNI_DtrtrsNode extends DtrtrsNode {
         @Override
         @TruffleBoundary
-        public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+        public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
             return native_dtrtrs(uplo, trans, diag, n, nrhs, a, lda, b, ldb);
         }
+    }
 
+    private static class JNI_DgetrfNode extends DgetrfNode {
         @Override
         @TruffleBoundary
-        public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) {
+        public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
             return native_dgetrf(m, n, a, lda, ipiv);
         }
+    }
 
+    private static class JNI_DpotrfNode extends DpotrfNode {
         @Override
         @TruffleBoundary
-        public int dpotrf(char uplo, int n, double[] a, int lda) {
+        public int execute(char uplo, int n, double[] a, int lda) {
             return native_dpotrf(uplo, n, a, lda);
         }
+    }
 
+    private static class JNI_DpstrfNode extends DpstrfNode {
         @Override
         @TruffleBoundary
-        public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
+        public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
             return native_dpstrf(uplo, n, a, lda, piv, rank, tol, work);
         }
+    }
 
+    private static class JNI_DgesvNode extends DgesvNode {
         @Override
         @TruffleBoundary
-        public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
+        public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
             return native_dgesv(n, nrhs, a, lda, ipiv, b, ldb);
         }
+    }
 
+    private static class JNI_DlangeNode extends DlangeNode {
         @Override
         @TruffleBoundary
-        public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) {
+        public double execute(char norm, int m, int n, double[] a, int lda, double[] work) {
             return native_dlange(norm, m, n, a, lda, work);
         }
+    }
 
+    private static class JNI_DgeconNode extends DgeconNode {
         @Override
         @TruffleBoundary
-        public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
+        public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
             return native_dgecon(norm, n, a, lda, anorm, rcond, work, iwork);
         }
+    }
 
+    private static class JNI_DsyevrNode extends DsyevrNode {
         @Override
-        public int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m,
+        public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m,
                         double[] w, double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork) {
             return native_dsyevr(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork);
         }
     }
 
     @Override
-    public LapackRFFINode createLapackRFFINode() {
-        return new JNI_LapackRFFINode();
+    public IlaverNode createIlaverNode() {
+        return new JNI_IlaverNode();
+    }
+
+    @Override
+    public DgeevNode createDgeevNode() {
+        return new JNI_DgeevNode();
+    }
+
+    @Override
+    public Dgeqp3Node createDgeqp3Node() {
+        return new JNI_Dgeqp3Node();
+    }
+
+    @Override
+    public DormqrNode createDormqrNode() {
+        return new JNI_DormqrNode();
+    }
+
+    @Override
+    public DtrtrsNode createDtrtrsNode() {
+        return new JNI_DtrtrsNode();
+    }
+
+    @Override
+    public DgetrfNode createDgetrfNode() {
+        return new JNI_DgetrfNode();
+    }
+
+    @Override
+    public DpotrfNode createDpotrfNode() {
+        return new JNI_DpotrfNode();
+    }
+
+    @Override
+    public DpstrfNode createDpstrfNode() {
+        return new JNI_DpstrfNode();
+    }
+
+    @Override
+    public DgesvNode createDgesvNode() {
+        return new JNI_DgesvNode();
+    }
+
+    @Override
+    public DlangeNode createDlangeNode() {
+        return new JNI_DlangeNode();
+    }
+
+    @Override
+    public DgeconNode createDgeconNode() {
+        return new JNI_DgeconNode();
+    }
+
+    @Override
+    public DsyevrNode createDsyevrNode() {
+        return new JNI_DsyevrNode();
     }
 
     // Checkstyle: stop method name
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
index 25035bfc14..1e4ae3a4ac 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
@@ -30,20 +30,27 @@ import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 
 public class JNI_Misc implements MiscRFFI {
 
-    @Override
-    public double exactSum(double[] values, boolean hasNa, boolean naRm) {
-        if (traceEnabled()) {
-            traceDownCall("exactSum");
-        }
-        try {
-            return exactSumFunc(values, hasNa, naRm);
-        } finally {
+    private static class JNI_ExactSumNode extends ExactSumNode {
+        @Override
+        public double execute(double[] values, boolean hasNa, boolean naRm) {
             if (traceEnabled()) {
-                traceDownCallReturn("exactSum", null);
+                traceDownCall("exactSum");
+            }
+            try {
+                return exactSumFunc(values, hasNa, naRm);
+            } finally {
+                if (traceEnabled()) {
+                    traceDownCallReturn("exactSum", null);
+                }
             }
         }
     }
 
+    @Override
+    public ExactSumNode createExactSumNode() {
+        return new JNI_ExactSumNode();
+    }
+
     private static native double exactSumFunc(double[] values, boolean hasNa, boolean naRm);
 
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
index 995c4d0914..bf64d0c96d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,30 +26,46 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 
 public class JNI_RAppl implements RApplRFFI {
-    private static class JNI_RApplRFFINode extends RApplRFFINode {
+    private static class JNI_Dqrdc2Node extends Dqrdc2Node {
         @Override
         @TruffleBoundary
-        public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
+        public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
             native_dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, work);
         }
+    }
+
+    private static class JNI_DqrcfNode extends DqrcfNode {
 
         @Override
         @TruffleBoundary
-        public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
             native_dqrcf(x, n, k, qraux, y, ny, b, info);
         }
+    }
 
+    private static class JNI_DqrlsNode extends DqrlsNode {
         @Override
         @TruffleBoundary
-        public void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
+        public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
             native_dqrls(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work);
         }
     }
 
     @Override
-    public RApplRFFINode createRApplRFFINode() {
-        return new JNI_RApplRFFINode();
+    public Dqrdc2Node createDqrdc2Node() {
+        return new JNI_Dqrdc2Node();
+    }
+
+    @Override
+    public DqrcfNode createDqrcfNode() {
+        return new JNI_DqrcfNode();
     }
+
+    @Override
+    public DqrlsNode createDqrlsNode() {
+        return new JNI_DqrlsNode();
+    }
+
     // Checkstyle: stop method name
 
     private static native void native_dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
index a8f3622fa4..4d8e072cad 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,65 +30,164 @@ import com.oracle.truffle.api.nodes.Node;
  * the result of the call.
  */
 public interface LapackRFFI {
-    abstract class LapackRFFINode extends Node {
+    abstract class IlaverNode extends Node {
         /**
          * Return version info, mjor, minor, patch, in {@code version}.
          */
-        public abstract void ilaver(int[] version);
+        public abstract void execute(int[] version);
 
+        public static IlaverNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode();
+        }
+    }
+
+    abstract class DgeevNode extends Node {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html">spec</a>.
          */
-        public abstract int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork);
+        public abstract int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork);
+
+        public static DgeevNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDgeevNode();
+        }
+    }
 
+    abstract class Dgeqp3Node extends Node {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/db/de5/dgeqp3_8f.html">spec</a>.
          */
-        public abstract int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork);
+        public abstract int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork);
+
+        public static Dgeqp3Node create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDgeqp3Node();
+        }
+    }
 
+    abstract class DormqrNode extends Node {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/da/d82/dormqr_8f.html">spec</a>.
          */
-        public abstract int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork);
+        public abstract int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork);
+
+        public static DormqrNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDormqrNode();
+        }
+    }
+
+    abstract class DtrtrsNode extends Node {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d6/d6f/dtrtrs_8f.html">spec</a>.
          */
-        public abstract int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb);
+        public abstract int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb);
+
+        public static DtrtrsNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDtrtrsNode();
+        }
+    }
+
+    abstract class DgetrfNode extends Node {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d3/d6a/dgetrf_8f.html">spec</a>.
          */
-        public abstract int dgetrf(int m, int n, double[] a, int lda, int[] ipiv);
+        public abstract int execute(int m, int n, double[] a, int lda, int[] ipiv);
+
+        public static DgetrfNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDgetrfNode();
+        }
+    }
+
+    abstract class DpotrfNode extends Node {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotrf_8f.html">spec</a>.
          */
-        public abstract int dpotrf(char uplo, int n, double[] a, int lda);
+        public abstract int execute(char uplo, int n, double[] a, int lda);
+
+        public static DpotrfNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDpotrfNode();
+        }
+    }
 
+    abstract class DpstrfNode extends Node {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/dd/dad/dpstrf_8f.html">spec</a>.
          */
-        public abstract int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work);
+        public abstract int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work);
+
+        public static DpstrfNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDpstrfNode();
+        }
+    }
 
+    abstract class DgesvNode extends Node {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d8/d72/dgesv_8f.html">spec</a>.
          */
-        public abstract int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb);
+        public abstract int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb);
+
+        public static DgesvNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDgesvNode();
+        }
+    }
+
+    abstract class DlangeNode extends Node {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/dc/d09/dlange_8f.html">spec</a>.
          */
-        public abstract double dlange(char norm, int m, int n, double[] a, int lda, double[] work);
+        public abstract double execute(char norm, int m, int n, double[] a, int lda, double[] work);
+
+        public static DlangeNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDlangeNode();
+        }
+    }
+
+    abstract class DgeconNode extends Node {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/db/de4/dgecon_8f.html">spec</a>.
          */
-        public abstract int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork);
+        public abstract int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork);
+
+        public static DgeconNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDgeconNode();
+        }
+    }
+
+    abstract class DsyevrNode extends Node {
 
-        public abstract int dsyevr(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w,
+        public abstract int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w,
                         double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork);
+
+        public static DsyevrNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDsyevrNode();
+        }
     }
 
-    LapackRFFINode createLapackRFFINode();
+    IlaverNode createIlaverNode();
+
+    DgeevNode createDgeevNode();
+
+    Dgeqp3Node createDgeqp3Node();
+
+    DormqrNode createDormqrNode();
+
+    DtrtrsNode createDtrtrsNode();
+
+    DgetrfNode createDgetrfNode();
+
+    DpotrfNode createDpotrfNode();
+
+    DpstrfNode createDpstrfNode();
+
+    DgesvNode createDgesvNode();
+
+    DlangeNode createDlangeNode();
+
+    DgeconNode createDgeconNode();
+
+    DsyevrNode createDsyevrNode();
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
index 28ad96a3b6..a401f6b1b8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,11 +22,21 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.api.nodes.Node;
+
 /**
  * Miscellaneous methods implemented in native code.
  *
  */
 public interface MiscRFFI {
-    double exactSum(double[] values, boolean hasNa, boolean naRm);
+    abstract class ExactSumNode extends Node {
+        public abstract double execute(double[] values, boolean hasNa, boolean naRm);
+
+        public static ExactSumNode create() {
+            return RFFIFactory.getRFFI().getMiscRFFI().createExactSumNode();
+        }
+    }
+
+    ExactSumNode createExactSumNode();
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java
index 189f88165c..a8e4d2aa6d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,15 +30,34 @@ import com.oracle.truffle.api.nodes.Node;
  * {@code libappl} library in GnuR.
  */
 public interface RApplRFFI {
-    abstract class RApplRFFINode extends Node {
-        // Linpack
-        public abstract void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
+    abstract class Dqrdc2Node extends Node {
+        public abstract void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
 
-        public abstract void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info);
+        public static Dqrdc2Node create() {
+            return RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node();
+        }
+    }
+
+    abstract class DqrcfNode extends Node {
+        public abstract void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info);
 
-        public abstract void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work);
+        public static Dqrdc2Node create() {
+            return RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node();
+        }
     }
 
-    RApplRFFINode createRApplRFFINode();
+    abstract class DqrlsNode extends Node {
+        public abstract void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work);
+
+        public static DqrlsNode create() {
+            return RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode();
+        }
+    }
+
+    Dqrdc2Node createDqrdc2Node();
+
+    DqrcfNode createDqrcfNode();
+
+    DqrlsNode createDqrlsNode();
 
 }
-- 
GitLab


From e92a1df54e7cd6f2d765975bed132a46124f1ea5 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 17 Feb 2017 08:22:48 +0100
Subject: [PATCH 016/402] Moved cast pipeline checking open modes into
 CastsHelper.

---
 .../r/nodes/builtin/base/ConnectionFunctions.java      | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 024c5bfa62..9e6a7dd3b2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -144,6 +144,11 @@ public abstract class ConnectionFunctions {
             return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA();
         }
 
+        private static HeadPhaseBuilder<String> openMode(Casts casts) {
+            return open(casts).mustBe(equalTo("").or(equalTo("r")).or(equalTo("rt")).or(equalTo("rb")).or(equalTo("r+")).or(equalTo("r+b")).or(equalTo("w")).or(equalTo("wt")).or(equalTo("wb")).or(
+                            equalTo("w+")).or(equalTo("w+b")).or(equalTo("a")).or(equalTo("a+")), RError.Message.UNSUPPORTED_MODE);
+        }
+
         private static void encoding(Casts casts) {
             casts.arg("encoding").asStringVector().mustBe(singleElement()).findFirst();
         }
@@ -425,10 +430,7 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(RawConnection.class);
             CastsHelper.description(casts);
             casts.arg("object").mustBe(stringValue().or(rawValue()));
-            CastsHelper.open(casts).mustBe(
-                            equalTo("").or(equalTo("r")).or(equalTo("rt")).or(equalTo("rb")).or(equalTo("r+")).or(equalTo("w")).or(equalTo("wt")).or(equalTo("wb")).or(equalTo("w+")).or(
-                                            equalTo("a")).or(equalTo("a+")),
-                            RError.Message.UNSUPPORTED_MODE);
+            CastsHelper.openMode(casts);
         }
 
         @Specialization
-- 
GitLab


From aeb005e2b21b7010314eadc5977985719a8e2247 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 17 Feb 2017 09:15:07 +0100
Subject: [PATCH 017/402] Added seeking support for raw connections. Although
 documentation of function 'seek' states, that support ist just available for
 file connections, it also works for raw connections.

---
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../r/runtime/conn/RawConnections.java        | 39 ++++++++++++++++++-
 .../conn/SeekableMemoryByteChannel.java       |  1 +
 .../truffle/r/test/ExpectedTestOutput.test    |  3 ++
 .../connection/R/rawConnection_seek.R         |  8 ++++
 5 files changed, 52 insertions(+), 2 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 4a1889bfca..85a79915a5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -789,7 +789,8 @@ public final class RError extends RuntimeException {
         TOO_MANY_ARGS("too many arguments"),
         UNIMPLEMENTED_TYPE_IN_R("type \"%s\" unimplemented in R"),
         NOT_AN_OUTPUT_RAW_CONNECTION("'con' is not an output rawConnection"),
-        NOT_A_RAW_CONNECTION("'con' is not a rawConnection");
+        NOT_A_RAW_CONNECTION("'con' is not a rawConnection"),
+        SEEK_OUTSITE_RAW_CONNECTION("attempt to seek outside the range of the raw connection");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 96cc3ad9cd..f30f83e5b8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -74,6 +74,7 @@ public class RawConnections {
                     delegate = new RawReadWriteConnection(this, channel, true);
                     break;
                 case ReadWrite:
+                case ReadWriteBinary:
                 case ReadWriteTrunc:
                 case ReadWriteTruncBinary:
                     delegate = new RawReadWriteConnection(this, channel, false);
@@ -98,6 +99,27 @@ public class RawConnections {
             return channel.getBuffer();
         }
 
+        public static long seek(SeekableMemoryByteChannel channel, long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            final long origPos = channel.position();
+            final long newPos;
+            switch (seekMode) {
+                case START:
+                    newPos = offset;
+                    break;
+                case CURRENT:
+                    newPos = origPos + offset;
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER, "seek mode");
+            }
+            if (newPos >= 0L && newPos <= channel.size()) {
+                channel.position(newPos);
+            } else {
+                throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_OUTSITE_RAW_CONNECTION);
+            }
+            return origPos;
+        }
+
     }
 
     static class RawReadRConnection extends DelegateReadRConnection implements ReadWriteHelper {
@@ -169,6 +191,11 @@ public class RawConnections {
         public OutputStream getOutputStream() {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_AN_OUTPUT_RAW_CONNECTION);
         }
+
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
+        }
     }
 
     private static class RawWriteBinaryConnection extends DelegateWriteRConnection implements ReadWriteHelper {
@@ -231,6 +258,11 @@ public class RawConnections {
         public void flush() throws IOException {
             // nothing to do
         }
+
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
+        }
     }
 
     private static class RawReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper {
@@ -302,7 +334,7 @@ public class RawConnections {
 
         @Override
         public String readChar(int nchars, boolean useBytes) throws IOException {
-            throw RInternalError.unimplemented();
+            return readCharHelper(nchars, channel.getInputStream(), useBytes);
         }
 
         @Override
@@ -320,6 +352,11 @@ public class RawConnections {
             throw RInternalError.unimplemented();
         }
 
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
+        }
+
     }
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
index dbf3a84ef6..79dd7dfe9e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -226,6 +226,7 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
     public int read() throws IOException {
         final ByteBuffer bf = ByteBuffer.allocate(1);
         read(bf);
+        bf.rewind();
         return bf.get();
     }
 
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 0a9f202a00..3c238793e1 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
@@ -42140,6 +42140,9 @@ raw(0)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R") }
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R") }
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R
new file mode 100644
index 0000000000..2d2fd0d103
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R
@@ -0,0 +1,8 @@
+zz <- rawConnection(raw(0), "r+b")
+writeBin(LETTERS, zz)
+seek(zz, 0)
+readChar(zz, 1)
+seek(zz, 0)
+writeBin(letters[1:3], zz)
+rawConnectionValue(zz)
+close(zz)
-- 
GitLab


From 57a5225993b959245ea60b9c641a88480e0830e2 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 17 Feb 2017 13:23:25 +0100
Subject: [PATCH 018/402] use latest jvmci jdk

---
 ci.hocon | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ci.hocon b/ci.hocon
index 9d80f57bdf..752f2f46a7 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -6,7 +6,7 @@
 # java 7 is needed by Truffle (for now)
 java7 : {name : oraclejdk, version : "7",    platformspecific: true}
 # java 8 must be a jvmci enabled variant
-java8 : {name : labsjdk, version : "8u121-jvmci-0.24", platformspecific: true}
+java8 : {name : labsjdk, version : "8-jvmci-latest", platformspecific: true}
 
 java8Downloads : {
   downloads : {
-- 
GitLab


From 613ca0fc3b35843d2801ad22441e8573903b8341 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Feb 2017 15:43:52 +0100
Subject: [PATCH 019/402] fix erroneous transferToInterpreter

---
 .../com/oracle/truffle/r/nodes/builtin/base/Transpose.java    | 2 +-
 .../oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java | 4 ++--
 .../r/nodes/access/vector/CachedExtractVectorNode.java        | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index f9c7bf4af7..a234a6ce6d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -82,7 +82,7 @@ public abstract class Transpose extends RBuiltinNode {
         int secondDim;
         if (isMatrixProfile.profile(vector.isMatrix())) {
             if (getDimNode == null) {
-                CompilerDirectives.transferToInterpreter();
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 getDimNode = insert(GetDimAttributeNode.create());
             }
             int[] dims = getDimNode.getDimensions(vector);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index b3df6a98a0..08b8964ba8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -206,7 +206,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
                 res = updateDimNames(res, value);
             } else if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) {
                 if (setClassNode == null) {
-                    CompilerDirectives.transferToInterpreter();
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
                     setClassNode = insert(SetClassAttributeNode.create());
                 }
                 if (value == RNull.instance) {
@@ -223,7 +223,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
             } else {
                 if (value == RNull.instance) {
                     if (removeAttrNode == null) {
-                        CompilerDirectives.transferToInterpreter();
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
                         removeAttrNode = insert(RemoveAttributeNode.create());
                     }
                     removeAttrNode.execute(res, attrName);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index a1447c00d9..207a56eb78 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -192,7 +192,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
             if (oneDimensionProfile.profile(numberOfDimensions == 1)) {
                 // names only need to be considered for single dimensional accesses
                 if (getNamesNode == null) {
-                    CompilerDirectives.transferToInterpreter();
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
                     getNamesNode = insert(GetNamesAttributeNode.create());
                 }
                 RStringVector originalNames = getNamesNode.getNames(vector);
-- 
GitLab


From ea4a01d13b277491a34380b1309667ab5e9fc8f9 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 17 Feb 2017 17:12:22 +0100
Subject: [PATCH 020/402] ignore RFrameSlots in FastRDebugTest

---
 .../truffle/r/test/tck/FastRDebugTest.java    | 65 ++++++++++++-------
 1 file changed, 40 insertions(+), 25 deletions(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 0016b0ebc3..2b1520a625 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -47,13 +47,14 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Value;
-import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
+import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase;
+import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 public class FastRDebugTest {
     private Debugger debugger;
@@ -257,31 +258,45 @@ public class FastRDebugTest {
 
     private void assertLocation(final int line, final String code, final Object... expectedFrame) {
         run.addLast(() -> {
-            assertNotNull(suspendedEvent);
-            final int currentLine = suspendedEvent.getSourceSection().getStartLine();
-            assertEquals(line, currentLine);
-            final String currentCode = suspendedEvent.getSourceSection().getCode().trim();
-            assertEquals(code, currentCode);
-            final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
-
-            final AtomicInteger numFrameVars = new AtomicInteger(0);
-            frame.forEach(var -> {
-                numFrameVars.incrementAndGet();
-            });
-            // There is (self) among the variables, hence substract 1:
-            assertEquals(expectedFrame.length / 2, numFrameVars.get() - 1);
-
-            for (int i = 0; i < expectedFrame.length; i = i + 2) {
-                String expectedIdentifier = (String) expectedFrame[i];
-                Object expectedValue = expectedFrame[i + 1];
-                String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null;
-                DebugValue value = frame.getValue(expectedIdentifier);
-                assertNotNull(value);
-                String valueStr = value.as(String.class);
-                assertEquals(expectedValueStr, valueStr);
-            }
+            try {
+                assertNotNull(suspendedEvent);
+                final int currentLine = suspendedEvent.getSourceSection().getStartLine();
+                assertEquals(line, currentLine);
+                final String currentCode = suspendedEvent.getSourceSection().getCode().trim();
+                assertEquals(code, currentCode);
+                final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+
+                final AtomicInteger numFrameVars = new AtomicInteger(0);
+                frame.forEach(var -> {
+                    // skip synthetic slots
+                    for (RFrameSlot slot : RFrameSlot.values()) {
+                        if (slot.name().equals(var.getName())) {
+                            return;
+                        }
+                    }
+                    numFrameVars.incrementAndGet();
+                });
+                assertEquals(line + ": " + code, expectedFrame.length / 2, numFrameVars.get());
+
+                for (int i = 0; i < expectedFrame.length; i = i + 2) {
+                    String expectedIdentifier = (String) expectedFrame[i];
+                    Object expectedValue = expectedFrame[i + 1];
+                    String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null;
+                    DebugValue value = frame.getValue(expectedIdentifier);
+                    assertNotNull(value);
+                    String valueStr = value.as(String.class);
+                    assertEquals(expectedValueStr, valueStr);
+                }
 
-            run.removeFirst().run();
+                run.removeFirst().run();
+            } catch (RuntimeException | Error e) {
+
+                final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+                frame.forEach(var -> {
+                    System.out.println(var);
+                });
+                throw e;
+            }
         });
     }
 
-- 
GitLab


From 1f5b5c8f3d9106fbde793c9c664b7b9342c0a9a9 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 17 Feb 2017 14:25:03 +0100
Subject: [PATCH 021/402] fix escaping/quoting of string printing, various
 printing cleanups

---
 .../r/nodes/builtin/RBuiltinPackages.java     |  4 +-
 .../r/nodes/builtin/base/MatchArg.java        |  2 +-
 .../r/nodes/builtin/base/PrintFunctions.java  |  3 +-
 .../builtin/base/printer/ListPrinter.java     | 40 +++++++++----------
 .../builtin/base/printer/PairListPrinter.java | 22 +++++-----
 .../builtin/base/printer/PrintParameters.java | 14 +++----
 .../base/printer/StringVectorPrinter.java     | 21 +++-------
 .../r/nodes/builtin/base/printer/Utils.java   |  6 ++-
 .../truffle/r/nodes/unary/ToStringNode.java   |  4 +-
 .../oracle/truffle/r/runtime/RDeparse.java    |  2 +-
 .../oracle/truffle/r/runtime/RRuntime.java    | 18 ++++++---
 .../builtins/TestBuiltin_printdefault.java    |  8 ++--
 12 files changed, 68 insertions(+), 76 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
index 535045ab1c..e8bfecd924 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,7 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         }
         // Load the (stub) DLL for base
         String path = baseDirPath.resolve("libs").resolve("base.so").toString();
-        Source loadSource = RSource.fromTextInternal(".Internal(dyn.load(" + RRuntime.quoteString(path, false) + ", TRUE, TRUE, \"\"))", RSource.Internal.R_IMPL);
+        Source loadSource = RSource.fromTextInternal(".Internal(dyn.load(" + RRuntime.escapeString(path, false, true) + ", TRUE, TRUE, \"\"))", RSource.Internal.R_IMPL);
         RContext.getEngine().parseAndEval(loadSource, baseFrame, false);
 
         // Any RBuiltinKind.SUBSTITUTE functions installed above should not be overridden
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
index 170e794180..9247558952 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
@@ -107,7 +107,7 @@ public abstract class MatchArg extends RBuiltinNode {
                 CompilerDirectives.transferToInterpreter();
                 StringBuilder choicesString = new StringBuilder();
                 for (int i = 0; i < choices.getLength(); i++) {
-                    choicesString.append(i == 0 ? "" : ", ").append(RRuntime.quoteString(choices.getDataAt(i), false));
+                    choicesString.append(i == 0 ? "" : ", ").append(RRuntime.escapeString(choices.getDataAt(i), false, true));
                 }
                 throw RError.error(this, Message.ARG_ONE_OF, "arg", choicesString);
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
index 9abaf902ac..61e3e3830d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
@@ -47,7 +47,6 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 
 public class PrintFunctions {
@@ -120,7 +119,7 @@ public class PrintFunctions {
 
         @Specialization
         protected RFunction printFunction(RFunction x, boolean useSource, @SuppressWarnings("unused") RArgsValuesAndNames extra) {
-            valuePrinter.execute(x, PrintParameters.getDefaultDigits(), true, RString.valueOf(RRuntime.STRING_NA), 1, false, PrintParameters.getDefaultMaxPrint(), useSource, false);
+            valuePrinter.execute(x, PrintParameters.getDefaultDigits(), true, RRuntime.STRING_NA, 1, false, PrintParameters.getDefaultMaxPrint(), useSource, false);
             return x;
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index e0915c3817..9c04b376ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -79,33 +79,30 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
                 RAbstractLogicalVector lv = (RAbstractLogicalVector) tmp;
                 if (lv.getLength() == 1) {
                     FormatMetrics fm = LogicalVectorPrinter.formatLogicalVector(lv, 0, 1, pp.getNaWidth());
-                    pbuf = snprintf(115, "%s",
-                                    LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), fm.maxWidth, pp));
+                    pbuf = LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), fm.maxWidth, pp);
                 } else {
-                    pbuf = snprintf(115, "Logical,%d", lv.getLength());
+                    pbuf = "Logical," + lv.getLength();
                 }
             } else if (tmp instanceof RAbstractIntVector) {
                 RAbstractIntVector iv = (RAbstractIntVector) tmp;
                 if (printCtx.printerNode().inherits(iv, RRuntime.CLASS_FACTOR)) {
                     /* factors are stored as integers */
-                    pbuf = snprintf(115, "factor,%d", iv.getLength());
+                    pbuf = "factor," + iv.getLength();
                 } else {
                     if (iv.getLength() == 1) {
                         FormatMetrics fm = IntegerVectorPrinter.formatIntVector(iv, 0, 1, pp.getNaWidth());
-                        pbuf = snprintf(115, "%s",
-                                        IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp));
+                        pbuf = IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp);
                     } else {
-                        pbuf = snprintf(115, "Integer,%d", iv.getLength());
+                        pbuf = "Integer," + iv.getLength();
                     }
                 }
             } else if (tmp instanceof RAbstractDoubleVector) {
                 RAbstractDoubleVector dv = (RAbstractDoubleVector) tmp;
                 if (dv.getLength() == 1) {
                     DoubleVectorMetrics fm = DoubleVectorPrinter.formatDoubleVector(dv, 0, 1, 0, pp);
-                    pbuf = snprintf(115, "%s",
-                                    DoubleVectorPrinter.encodeReal(dv.getDataAt(0), fm, pp));
+                    pbuf = DoubleVectorPrinter.encodeReal(dv.getDataAt(0), fm, pp);
                 } else {
-                    pbuf = snprintf(115, "Numeric,%d", dv.getLength());
+                    pbuf = "Numeric," + dv.getLength();
                 }
             } else if (tmp instanceof RAbstractComplexVector) {
                 RAbstractComplexVector cv = (RAbstractComplexVector) tmp;
@@ -113,36 +110,35 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
                     RComplex x = cv.getDataAt(0);
                     if (RRuntime.isNA(x.getRealPart()) || RRuntime.isNA(x.getImaginaryPart())) {
                         /* formatReal(NA) --> w=R_print.na_width, d=0, e=0 */
-                        pbuf = snprintf(115, "%s",
-                                        DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp));
+                        pbuf = DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp);
                     } else {
                         ComplexVectorMetrics cvm = ComplexVectorPrinter.formatComplexVector(x, 0, 1, 0, pp);
-                        pbuf = snprintf(115, "%s", ComplexVectorPrinter.encodeComplex(x, cvm, pp));
+                        pbuf = ComplexVectorPrinter.encodeComplex(x, cvm, pp);
                     }
                 } else {
-                    pbuf = snprintf(115, "Complex,%d", cv.getLength());
+                    pbuf = "Complex," + cv.getLength();
                 }
             } else if (tmp instanceof RAbstractStringVector) {
                 RAbstractStringVector sv = (RAbstractStringVector) tmp;
                 if (sv.getLength() == 1) {
-                    String ctmp = sv.getDataAt(0);
+                    String ctmp = RRuntime.escapeString(sv.getDataAt(0), true, true);
                     int len = ctmp.length();
                     if (len < 100) {
-                        pbuf = snprintf(115, "\"%s\"", ctmp);
+                        pbuf = ctmp;
                     } else {
-                        pbuf = snprintf(101, "\"%s", ctmp) + "\" [truncated]";
+                        pbuf = Utils.trimSize(101, ctmp) + "\" [truncated]";
                     }
                 } else {
-                    pbuf = snprintf(115, "Character,%d", sv.getLength());
+                    pbuf = "Character," + sv.getLength();
                 }
             } else if (tmp instanceof RAbstractRawVector) {
-                pbuf = snprintf(115, "Raw,%d", ((RAbstractRawVector) (tmp)).getLength());
+                pbuf = "Raw," + ((RAbstractRawVector) (tmp)).getLength();
             } else if (tmp instanceof RAbstractListVector) {
-                pbuf = snprintf(115, "List,%d", ((RAbstractListVector) (tmp)).getLength());
+                pbuf = "List," + ((RAbstractListVector) (tmp)).getLength();
             } else if (tmp instanceof RLanguage) {
-                pbuf = snprintf(115, "Expression");
+                pbuf = "Expression";
             } else {
-                pbuf = snprintf(115, "?");
+                pbuf = "?";
             }
 
             t[i] = pbuf;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
index 5927ddf98e..8d35746952 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
@@ -5,14 +5,12 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
-import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
-
 import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -57,23 +55,23 @@ final class PairListPrinter extends AbstractValuePrinter<RPairList> {
                 if (tmp == null || tmp == RNull.instance) {
                     pbuf = RRuntime.NULL;
                 } else if (tmp instanceof RAbstractLogicalVector) {
-                    pbuf = snprintf(115, "Logical,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "Logical," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractIntVector) {
-                    pbuf = snprintf(115, "Integer,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "Integer," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractDoubleVector) {
-                    pbuf = snprintf(115, "Numeric,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "Numeric," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractComplexVector) {
-                    pbuf = snprintf(115, "Complex,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "Complex," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractStringVector) {
-                    pbuf = snprintf(115, "Character,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "Character," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractRawVector) {
-                    pbuf = snprintf(115, "Raw,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "Raw," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RAbstractListVector) {
-                    pbuf = snprintf(115, "List,%d", ((RAbstractContainer) tmp).getLength());
+                    pbuf = "List," + ((RAbstractContainer) tmp).getLength();
                 } else if (tmp instanceof RLanguage) {
-                    pbuf = snprintf(115, "Expression");
+                    pbuf = "Expression";
                 } else {
-                    pbuf = snprintf(115, "?");
+                    pbuf = "?";
                 }
 
                 t[i] = pbuf;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
index 27deabed40..6f7bbfa855 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -21,7 +21,6 @@ import com.oracle.truffle.r.nodes.builtin.base.Format;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RString;
 
 public final class PrintParameters {
     @CompilationFinal private static int DefaultDigits = -1;
@@ -58,8 +57,7 @@ public final class PrintParameters {
     }
 
     @TruffleBoundary
-    PrintParameters(Object digits, boolean quote, Object naPrint,
-                    Object printGap, boolean right, Object max, boolean useSource, @SuppressWarnings("unused") boolean noOpt) {
+    PrintParameters(Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, @SuppressWarnings("unused") boolean noOpt) {
 
         setDefaults();
 
@@ -79,12 +77,12 @@ public final class PrintParameters {
             // condition, the GnuR application ignores that condition. It was revealed when running
             // test com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault, which fails if the
             // condition is present complaining about an invalid na.print specification.
-            // if (!(naPrint instanceof RString) || ((RString) naPrint).getValue().length() < 1)
+            // if (!(naPrint instanceof String) || ((String) naPrint).getValue().length() < 1)
             // throw new
             // IllegalArgumentException(String.format("invalid 'na.print' specification"));
-            String nav = naPrint.toString();
-            if (!"".equals(nav)) {
-                this.naString = this.naStringNoquote = ((RString) naPrint).getValue();
+            String nav = (String) naPrint;
+            if (!nav.isEmpty()) {
+                this.naString = this.naStringNoquote = nav;
                 this.naWidth = this.naWidthNoquote = this.naString.length();
             }
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
index 7d6228c262..5ba2ea9ebc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -104,7 +104,7 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> {
 
         for (int i = 0; i < n; i++) {
             String s = x.getDataAt(offs + i);
-            String xi = quote ? RRuntime.quoteString(s, false) : s;
+            String xi = RRuntime.escapeString(s, false, quote);
 
             if (xi == RRuntime.STRING_NA) {
                 l = quote ? pp.getNaWidth() : pp.getNaWidthNoquote();
@@ -167,20 +167,11 @@ final class StringVectorPrinter extends VectorPrinter<RAbstractStringVector> {
     }
 
     static String encode(String value, int w, PrintParameters pp) {
-        final boolean quote = pp.getQuote();
-        final String s;
-        if (quote) {
-            if (RRuntime.isNA(value)) {
-                s = pp.getNaString();
-            } else {
-                s = RRuntime.quoteString(value, false);
-            }
+        String s;
+        if (RRuntime.isNA(value)) {
+            s = pp.getQuote() ? pp.getNaString() : pp.getNaStringNoquote();
         } else {
-            if (RRuntime.isNA(value)) {
-                s = pp.getNaStringNoquote();
-            } else {
-                s = value;
-            }
+            s = RRuntime.escapeString(value, false, pp.getQuote());
         }
         return StringVectorPrinter.encode(s, w, pp.getRight() ? PrintJustification.right : PrintJustification.left);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java
index 62e5a9c52f..5c3a70f056 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,10 @@ final class Utils {
         return fs.length() <= size ? fs : fs.substring(0, size);
     }
 
+    public static String trimSize(int size, String value) {
+        return value.length() <= size ? value : value.substring(0, size);
+    }
+
     public static String asBlankArg(int blanks) {
         return blanks == 0 ? "" : blanks + "";
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
index f6c1417827..c597619ecc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@ public abstract class ToStringNode extends RBaseNode {
             return value;
         }
         if (quotes) {
-            return RRuntime.quoteString(value, false);
+            return RRuntime.escapeString(value, false, true);
         }
         return value;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 9c8ae0753b..0c3646dac6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -830,7 +830,7 @@ public class RDeparse {
             switch (type) {
                 case STRSXP:
                     String s = (String) element;
-                    append(RRuntime.isNA(s) ? (singleElement ? "NA_character_" : "NA") : RRuntime.quoteString((String) element, true));
+                    append(RRuntime.isNA(s) ? (singleElement ? "NA_character_" : "NA") : RRuntime.escapeString(s, true, true));
                     break;
                 case LGLSXP:
                     append(RRuntime.logicalToString((byte) element));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index fcda893df1..e2494cc17a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -47,7 +47,7 @@ public class RRuntime {
     // Parts of the welcome message originate from GNU R.
     public static final String WELCOME_MESSAGE =
         "FastR version " + RVersionNumber.FULL + "\n" +
-        "Copyright (c) 2013-16, Oracle and/or its affiliates\n" +
+        "Copyright (c) 2013-17, Oracle and/or its affiliates\n" +
         "Copyright (c) 1995-2016, The R Core Team\n" +
         "Copyright (c) 2016 The R Foundation for Statistical Computing\n" +
         "Copyright (c) 2012-4 Purdue University\n" +
@@ -672,12 +672,14 @@ public class RRuntime {
     }
 
     @TruffleBoundary
-    public static String quoteString(String value, boolean encodeNonASCII) {
+    public static String escapeString(String value, boolean encodeNonASCII, boolean quote) {
         if (isNA(value)) {
             return STRING_NA;
         }
         StringBuilder str = new StringBuilder(value.length() + 2);
-        str.append('\"');
+        if (quote) {
+            str.append('\"');
+        }
         int offset = 0;
         while (offset < value.length()) {
             int codepoint = value.codePointAt(offset);
@@ -707,7 +709,11 @@ public class RRuntime {
                     str.append("\\\\");
                     break;
                 case '"':
-                    str.append("\\\"");
+                    if (quote) {
+                        str.append("\\\"");
+                    } else {
+                        str.append('\"');
+                    }
                     break;
                 default:
                     if (codepoint < 32 || codepoint == 0x7f) {
@@ -727,7 +733,9 @@ public class RRuntime {
             }
             offset += Character.charCount(codepoint);
         }
-        str.append('\"');
+        if (quote) {
+            str.append('\"');
+        }
         return str.toString();
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java
index a70ec7d7b1..1ad5ecd3c4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printdefault.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -29,8 +29,7 @@ public class TestBuiltin_printdefault extends TestBase {
 
     @Test
     public void testprintdefault3() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c('1', '2', '\\\\b', '4', '5', '\\\\040', '\\\\x20', 'c:\\\\spencer\\\\tests', '\\\\t', '\\\\n', '\\\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c('1', '2', '\\\\b', '4', '5', '\\\\040', '\\\\x20', 'c:\\\\spencer\\\\tests', '\\\\t', '\\\\n', '\\\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -50,8 +49,7 @@ public class TestBuiltin_printdefault extends TestBase {
 
     @Test
     public void testprintdefault7() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
-- 
GitLab


From adeae46ebfb59c3e2f090b44b5b900dde1c46758 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 17 Feb 2017 17:12:58 +0100
Subject: [PATCH 022/402] various small cleanups

---
 .../r/engine/shell/JLineConsoleCompleter.java |  8 +++----
 .../nodes/binary/BinaryArithmeticSpecial.java | 23 ++++++++++---------
 .../r/test/library/utils/TestTypeConvert.java |  3 +--
 .../r/test/rffi/TestRFFIPackageCoercions.java |  2 +-
 4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
index 15cbe86905..2c18397bf7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
@@ -64,7 +64,7 @@ public class JLineConsoleCompleter implements Completer {
         return cursor;
     }
 
-    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
+    private static int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
         if (buffer.isEmpty()) {
             return cursor;
         }
@@ -110,7 +110,7 @@ public class JLineConsoleCompleter implements Completer {
         return start;
     }
 
-    private int getStart(String buffer, REnvironment env, int cursor) {
+    private static int getStart(String buffer, REnvironment env, int cursor) {
         int start = 0;
         Object o = env.get("options");
         if (o instanceof RList) {
@@ -123,7 +123,7 @@ public class JLineConsoleCompleter implements Completer {
         return start;
     }
 
-    private int lastIdxOf(String buffer, RList opt, String key, int start, int cursor) {
+    private static int lastIdxOf(String buffer, RList opt, String key, int start, int cursor) {
         int optIdx = opt.getElementIndexByName(key);
         if (optIdx > -1) {
             Object o = opt.getDataAt(optIdx);
@@ -135,7 +135,7 @@ public class JLineConsoleCompleter implements Completer {
         return start;
     }
 
-    private int lastIdxOf(String buffer, String subs, int start, int cursor) {
+    private static int lastIdxOf(String buffer, String subs, int start, int cursor) {
         if (null != subs && !subs.isEmpty()) {
             int idx = buffer.lastIndexOf(subs, cursor);
             if (idx == cursor) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
index 25ecda9880..ce80a9a8b3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.binary;
 
 import com.oracle.truffle.api.CompilerDirectives;
+
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
@@ -44,26 +45,26 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
  * {@link RSpecialFactory#throwFullCallNeeded()} on NA.
  */
 @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
-@NodeChild(value = "arguments", type = RNode[].class)
+@NodeChild(value = "left", type = RNode.class)
+@NodeChild(value = "right", type = RNode.class)
 public abstract class BinaryArithmeticSpecial extends RNode {
+
     private final boolean handleNA;
     @Child private BinaryArithmetic operation;
 
-    public BinaryArithmeticSpecial(BinaryArithmetic operation, boolean handleNA) {
-        this.operation = operation;
-        this.handleNA = handleNA;
+    public BinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) {
+        this.operation = opFactory.createOperation();
+        this.handleNA = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.MOD);
     }
 
-    public static RSpecialFactory createSpecialFactory(final BinaryArithmeticFactory opFactory) {
-        final boolean handleNA = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.MOD);
+    public static RSpecialFactory createSpecialFactory(BinaryArithmeticFactory opFactory) {
         boolean handleIntegers = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.DIV);
         if (handleIntegers) {
             return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 2
-                            ? IntegerBinaryArithmeticSpecialNodeGen.create(opFactory.createOperation(), handleNA, arguments) : null;
+                            ? IntegerBinaryArithmeticSpecialNodeGen.create(opFactory, arguments[0], arguments[1]) : null;
         } else {
             return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 2
-                            ? BinaryArithmeticSpecialNodeGen.create(opFactory.createOperation(), handleNA, arguments)
-                            : null;
+                            ? BinaryArithmeticSpecialNodeGen.create(opFactory, arguments[0], arguments[1]) : null;
         }
     }
 
@@ -103,8 +104,8 @@ public abstract class BinaryArithmeticSpecial extends RNode {
     @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     abstract static class IntegerBinaryArithmeticSpecial extends BinaryArithmeticSpecial {
 
-        IntegerBinaryArithmeticSpecial(BinaryArithmetic op, boolean handleNA) {
-            super(op, handleNA);
+        IntegerBinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) {
+            super(opFactory);
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java
index 2096f7059b..ddce0a78c9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java
@@ -55,8 +55,7 @@ public class TestTypeConvert extends TestBase {
 
     @Test
     public void testFirstTypeMustBeOfModeTest() {
-        // UnsupportedSpecializationException: Unexpected values provided for ...
-        assertEval(Ignored.Unimplemented, "type.convert('NA', 1)");
+        assertEval("type.convert('NA', 1)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java
index 9bff0cf831..12c06a7162 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java
@@ -56,7 +56,7 @@ public class TestRFFIPackageCoercions extends TestRPackages {
         tearDownUninstallTestPackages();
     }
 
-    private String addLib(String test) {
+    private static String addLib(String test) {
         return "{ library('testrffi', lib.loc = '" + TestRPackages.libLoc() + "'); x <- " + test + "; detach('package:testrffi', unload=T); x }";
     }
 
-- 
GitLab


From 9504310646b026888f4a1d00897ce6a79993ddb0 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 1 Feb 2017 11:49:24 +0100
Subject: [PATCH 023/402] cleanups and better errors in ConnectionFunctions

---
 .../builtin/base/ConnectionFunctions.java     | 102 ++++++++----------
 1 file changed, 43 insertions(+), 59 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 9e6a7dd3b2..0c4da51d16 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -217,15 +217,15 @@ public abstract class ConnectionFunctions {
                 } else {
                     if (!(open.equals("w+") || open.equals("w+b"))) {
                         open = "w+";
-                        RError.warning(this, RError.Message.FILE_OPEN_TMP);
+                        RError.warning(RError.SHOW_CALLER, RError.Message.FILE_OPEN_TMP);
                     }
                 }
             }
             try {
                 return new FileRConnection(path, open).asVector();
             } catch (IOException ex) {
-                RError.warning(this, RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
-                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+                RError.warning(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
     }
@@ -261,9 +261,9 @@ public abstract class ConnectionFunctions {
             }
         }
 
-        private RError reportError(String path, IOException ex) throws RError {
-            RError.warning(this, RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage());
-            throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+        private static RError reportError(String path, IOException ex) throws RError {
+            RError.warning(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage());
+            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
         }
     }
 
@@ -315,35 +315,24 @@ public abstract class ConnectionFunctions {
             casts.arg("encoding").asIntegerVector().findFirst().notNA();
         }
 
-        private static RAbstractStringVector forceStringVector(Object text) {
-            if (text instanceof String) {
-                return RDataFactory.createStringVectorFromScalar((String) text);
-            } else {
-                return (RAbstractStringVector) text;
+        @Specialization
+        @TruffleBoundary
+        protected RAbstractIntVector textConnection(String description, RAbstractStringVector text, String open, REnvironment env, @SuppressWarnings("unused") int encoding) {
+            try {
+                return new TextRConnection(description, text, env, open).asVector();
+            } catch (IOException ex) {
+                throw RInternalError.shouldNotReachHere();
             }
         }
 
+        @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector textConnection(String description, Object text, String open, REnvironment env, @SuppressWarnings("unused") int encoding) {
-            RAbstractStringVector object;
+        protected RAbstractIntVector textConnection(String description, RNull text, String open, REnvironment env, int encoding) {
             if (open.length() == 0 || open.equals("r")) {
-                if (text == RNull.instance) {
-                    throw RError.error(this, RError.Message.INVALID_ARGUMENT, "text");
-                } else {
-                    object = forceStringVector(text);
-                }
+                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "text");
             } else {
-                if (text == RNull.instance) {
-                    throw RError.nyi(this, "textConnection: NULL");
-                } else {
-                    object = forceStringVector(text);
-                }
-            }
-            try {
-                return new TextRConnection(description, object, env, open).asVector();
-            } catch (IOException ex) {
-                throw RInternalError.shouldNotReachHere();
+                throw RError.nyi(RError.SHOW_CALLER, "textConnection: NULL");
             }
         }
     }
@@ -383,16 +372,11 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector socketConnection(String host, int port, boolean server, boolean blocking, String open,
-                        @SuppressWarnings("unused") RAbstractStringVector encoding, int timeout) {
+        protected RAbstractIntVector socketConnection(String host, int port, boolean server, boolean blocking, String open, @SuppressWarnings("unused") RAbstractStringVector encoding, int timeout) {
             try {
-                if (server) {
-                    return new RSocketConnection(open, true, host, port, blocking, timeout).asVector();
-                } else {
-                    return new RSocketConnection(open, false, host, port, blocking, timeout).asVector();
-                }
+                return new RSocketConnection(open, server, host, port, blocking, timeout).asVector();
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
     }
@@ -416,9 +400,9 @@ public abstract class ConnectionFunctions {
             try {
                 return new URLRConnection(url, open).asVector();
             } catch (MalformedURLException ex) {
-                throw RError.error(this, RError.Message.UNSUPPORTED_URL_SCHEME);
+                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_URL_SCHEME);
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
     }
@@ -516,15 +500,15 @@ public abstract class ConnectionFunctions {
             try {
                 BaseRConnection baseConn = getBaseConnection(RConnection.fromIndex(con));
                 if (baseConn.isClosed()) {
-                    throw RError.error(this, RError.Message.INVALID_CONNECTION);
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_CONNECTION);
                 }
                 if (baseConn.isOpen()) {
-                    RError.warning(this, RError.Message.ALREADY_OPEN_CONNECTION);
+                    RError.warning(RError.SHOW_CALLER, RError.Message.ALREADY_OPEN_CONNECTION);
                     return RNull.instance;
                 }
                 baseConn.open(open);
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, ex.getMessage());
             }
             return RNull.instance;
         }
@@ -554,7 +538,7 @@ public abstract class ConnectionFunctions {
                     result &= baseCon.canWrite();
                     break;
                 default:
-                    throw RError.error(this, RError.Message.UNKNOWN_VALUE, "rw");
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_VALUE, "rw");
             }
             return RDataFactory.createLogicalVectorFromScalar(result);
         }
@@ -576,7 +560,7 @@ public abstract class ConnectionFunctions {
             try {
                 connection.closeAndDestroy();
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, ex.getMessage());
             }
             return RNull.instance;
         }
@@ -602,11 +586,11 @@ public abstract class ConnectionFunctions {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("rt")) {
                 String[] lines = openConn.readLines(n, warn, skipNul);
                 if (n > 0 && lines.length < n && !ok) {
-                    throw RError.error(this, RError.Message.TOO_FEW_LINES_READ_LINES);
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.TOO_FEW_LINES_READ_LINES);
                 }
                 return RDataFactory.createStringVector(lines, RDataFactory.COMPLETE_VECTOR);
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
             }
         }
     }
@@ -628,7 +612,7 @@ public abstract class ConnectionFunctions {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wt")) {
                 openConn.writeLines(text, sep, useBytes);
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
             }
             return RNull.instance;
         }
@@ -648,7 +632,7 @@ public abstract class ConnectionFunctions {
             try {
                 RConnection.fromIndex(con).flush();
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.ERROR_FLUSHING_CONNECTION, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_FLUSHING_CONNECTION, x.getMessage());
             }
             return RNull.instance;
         }
@@ -728,7 +712,7 @@ public abstract class ConnectionFunctions {
                 }
                 return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
             }
         }
 
@@ -766,12 +750,12 @@ public abstract class ConnectionFunctions {
                     final int writeLen = Math.min(s.length(), nc);
                     int pad = nc - s.length();
                     if (pad > 0) {
-                        RError.warning(this, RError.Message.MORE_CHARACTERS);
+                        RError.warning(RError.SHOW_CALLER, RError.Message.MORE_CHARACTERS);
                     }
                     openConn.writeChar(s.substring(0, writeLen), pad, getSepFor(sep, i), useBytes);
                 }
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
             }
             return RNull.instance;
         }
@@ -824,7 +808,7 @@ public abstract class ConnectionFunctions {
             BaseRConnection connection = RConnection.fromIndex(con);
             try (RConnection openConn = connection.forceOpen("rb")) {
                 if (getBaseConnection(openConn).getOpenMode().isText()) {
-                    throw RError.error(this, RError.Message.ONLY_READ_BINARY_CONNECTION);
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.ONLY_READ_BINARY_CONNECTION);
                 }
                 switch (what) {
                     case "int":
@@ -835,7 +819,7 @@ public abstract class ConnectionFunctions {
                         if (size == 1 || size == 4) {
                             result = readInteger(connection, n, size, swap, signed);
                         } else {
-                            throw RError.nyi(this, "readBin \"int\" size not implemented");
+                            throw RError.nyi(RError.SHOW_CALLER, "readBin \"int\" size not implemented");
                         }
                         break;
                     case "double":
@@ -858,7 +842,7 @@ public abstract class ConnectionFunctions {
                         throw RInternalError.shouldNotReachHere();
                 }
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
             }
             return result;
         }
@@ -1107,19 +1091,19 @@ public abstract class ConnectionFunctions {
         protected Object writeBin(RAbstractVector object, int con, int size, boolean swap, boolean useBytes,
                         @Cached("create()") WriteDataNode writeData) {
             if (object instanceof RList || object instanceof RExpression) {
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "object");
+                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "object");
             }
             if (object.getLength() > 0) {
                 RConnection connection = RConnection.fromIndex(con);
                 try (RConnection openConn = connection.forceOpen("wb")) {
                     if (getBaseConnection(openConn).isTextMode()) {
-                        throw RError.error(this, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
+                        throw RError.error(RError.SHOW_CALLER, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
                     }
                     ByteBuffer buffer = writeData.execute(object, size, swap, useBytes);
                     buffer.flip();
                     connection.writeBin(buffer);
                 } catch (IOException x) {
-                    throw RError.error(this, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
                 }
             }
             return RNull.instance;
@@ -1149,7 +1133,7 @@ public abstract class ConnectionFunctions {
         protected RAbstractIntVector getConnection(int what) {
             BaseRConnection con = RContext.getInstance().stateRConnection.getConnection(what, false);
             if (con == null) {
-                throw RError.error(this, RError.Message.NO_SUCH_CONNECTION, what);
+                throw RError.error(RError.SHOW_CALLER, RError.Message.NO_SUCH_CONNECTION, what);
             } else {
                 return con.asVector();
             }
@@ -1207,11 +1191,11 @@ public abstract class ConnectionFunctions {
             try {
                 long newOffset = RConnection.fromIndex(con).seek(offset, RConnection.SeekMode.values()[origin], RConnection.SeekRWMode.values()[rw]);
                 if (newOffset > Integer.MAX_VALUE) {
-                    throw RError.nyi(this, "seek > Integer.MAX_VALUE");
+                    throw RError.nyi(RError.SHOW_CALLER, "seek > Integer.MAX_VALUE");
                 }
                 return (int) newOffset;
             } catch (IOException x) {
-                throw RError.error(this, RError.Message.GENERIC, x.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, x.getMessage());
             }
         }
     }
-- 
GitLab


From 2cbdb880a3b60c35df96573d1d55c7737399c64d Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 26 Jan 2017 11:31:17 +0100
Subject: [PATCH 024/402] use new DSL layout

---
 .../oracle/truffle/r/library/utils/Rprof.java |   7 +-
 .../builtin/base/ConnectionFunctions.java     |   3 +-
 .../r/nodes/builtin/base/Identical.java       |  39 +-
 .../truffle/r/nodes/builtin/base/MatMult.java |   6 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |  22 +-
 .../nodes/builtin/base/UpdateAttributes.java  |  58 +--
 .../r/nodes/builtin/base/infix/Subscript.java |   4 +-
 .../truffle/r/nodes/access/FrameSlotNode.java |   6 +-
 .../access/variables/ReadVariableNode.java    |   4 +-
 .../truffle/r/nodes/ffi/AsCharNode.java       |   4 +-
 .../truffle/r/nodes/ffi/AsIntegerNode.java    |   5 +-
 .../truffle/r/nodes/ffi/AsLogicalNode.java    |   5 +-
 .../truffle/r/nodes/ffi/AsRealNode.java       |   4 +-
 .../truffle/r/nodes/ffi/ListAccessNodes.java  |  13 +-
 .../oracle/truffle/r/nodes/ffi/MiscNodes.java |   4 +-
 .../oracle/truffle/r/runtime/data/RTypes.java | 179 ++-------
 .../r/runtime/data/RTypesFlatLayout.java      | 377 ------------------
 .../data/model/RAbstractAtomicVector.java     |   5 -
 .../oracle/truffle/r/runtime/nodes/RNode.java | 123 +-----
 .../test/builtins/TestBuiltin_seq_along.java  |   2 -
 20 files changed, 126 insertions(+), 744 deletions(-)
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index e91e16f85a..f783de61da 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -22,6 +22,11 @@
  */
 package com.oracle.truffle.r.library.utils;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -60,8 +65,6 @@ import com.oracle.truffle.r.runtime.instrument.InstrumentationState;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*;
-
 /**
  * Implements the {@code Rprof} external.
  *
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 0c4da51d16..46ffa0411b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -803,7 +803,7 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object readBin(int con, String what, int n, int size, boolean signed, boolean swap) {
+        protected Object readBin(int con, String what, int n, int sizeInput, boolean signed, boolean swap) {
             RVector<?> result = null;
             BaseRConnection connection = RConnection.fromIndex(con);
             try (RConnection openConn = connection.forceOpen("rb")) {
@@ -813,6 +813,7 @@ public abstract class ConnectionFunctions {
                 switch (what) {
                     case "int":
                     case "integer":
+                        int size = sizeInput;
                         if (size == RRuntime.INT_NA) {
                             size = 4;
                         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
index 3f5769de60..bf863d14ac 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
@@ -49,8 +49,6 @@ import com.oracle.truffle.r.runtime.data.RListBase;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.IdenticalVisitor;
@@ -183,18 +181,6 @@ public abstract class Identical extends RBuiltinNode {
         return RRuntime.LOGICAL_FALSE;
     }
 
-    @SuppressWarnings("unused")
-    @Specialization
-    protected byte doInternalIdentical(RAbstractLogicalVector x, REnvironment y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
-        return RRuntime.LOGICAL_FALSE;
-    }
-
-    @SuppressWarnings("unused")
-    @Specialization
-    protected byte doInternalIdentical(REnvironment x, RAbstractLogicalVector y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
-        return RRuntime.LOGICAL_FALSE;
-    }
-
     @SuppressWarnings("unused")
     @Specialization
     protected byte doInternalIdentical(REnvironment x, REnvironment y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
@@ -288,24 +274,6 @@ public abstract class Identical extends RBuiltinNode {
         return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment);
     }
 
-    @SuppressWarnings("unused")
-    @Specialization
-    protected byte doInternalIdenticalGeneric(RFunction x, RAbstractContainer y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
-        return RRuntime.LOGICAL_FALSE;
-    }
-
-    @SuppressWarnings("unused")
-    @Specialization
-    protected byte doInternalIdenticalGeneric(RLanguage x, RAbstractContainer y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
-        return RRuntime.LOGICAL_FALSE;
-    }
-
-    @SuppressWarnings("unused")
-    @Specialization
-    protected byte doInternalIdenticalGeneric(RAbstractContainer x, RFunction y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
-        return RRuntime.LOGICAL_FALSE;
-    }
-
     @Specialization
     protected byte doInternalIdenticalGeneric(RS4Object x, RS4Object y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
         if (x.isS4() != y.isS4()) {
@@ -368,11 +336,8 @@ public abstract class Identical extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Fallback
     protected byte doInternalIdenticalWrongTypes(Object x, Object y, Object numEq, Object singleNA, Object attribAsSet, Object ignoreBytecode, Object ignoreEnvironment) {
-        if (x.getClass() != y.getClass()) {
-            return RRuntime.LOGICAL_FALSE;
-        } else {
-            throw RInternalError.unimplemented();
-        }
+        assert x.getClass() != y.getClass();
+        return RRuntime.LOGICAL_FALSE;
     }
 
     protected boolean vectorsLists(RAbstractVector x, RAbstractVector y) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index 88b10299f8..f75a6b739a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -97,7 +97,7 @@ public abstract class MatMult extends RBuiltinNode {
         return MatMultNodeGen.create(true);
     }
 
-    @Specialization(guards = "bothZeroDim(a, b, getADimsNode, getBDimsNode)")
+    @Specialization(guards = "bothZeroDim(a, b)")
     protected RDoubleVector both0Dim(RAbstractDoubleVector a, RAbstractDoubleVector b) {
         int r = getBDimsNode.getDimensions(b)[1];
         int c = getADimsNode.getDimensions(a)[0];
@@ -697,11 +697,11 @@ public abstract class MatMult extends RBuiltinNode {
 
     // guards
 
-    protected static boolean bothZeroDim(RAbstractVector a, RAbstractVector b, GetDimAttributeNode getADimsNode, GetDimAttributeNode getBDimsNode) {
+    protected boolean bothZeroDim(RAbstractVector a, RAbstractVector b) {
         return hasZeroDim(a, getADimsNode) && hasZeroDim(b, getBDimsNode);
     }
 
-    protected static boolean hasZeroDim(RAbstractVector v, GetDimAttributeNode getDimsNode) {
+    protected boolean hasZeroDim(RAbstractVector v, GetDimAttributeNode getDimsNode) {
         int[] dims = getDimsNode.getDimensions(v);
         if (dims == null || dims.length == 0) {
             return false;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 27ec4be793..15e86c28fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -61,7 +61,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -99,7 +99,7 @@ public final class SeqFunctions {
         }
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class IsNumericNode extends Node {
         public abstract boolean execute(Object obj);
 
@@ -129,7 +129,7 @@ public final class SeqFunctions {
         }
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class IsMissingOrNumericNode extends IsNumericNode {
 
         @Specialization
@@ -138,7 +138,7 @@ public final class SeqFunctions {
         }
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class GetIntegralNumericNode extends Node {
 
         public abstract int execute(Object obj);
@@ -182,7 +182,7 @@ public final class SeqFunctions {
         return IsIntegralNumericNodeGen.create(true);
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     @ImportStatic(SeqFunctions.class)
     public abstract static class SeqFastPath extends FastPathAdapter {
         @Specialization(guards = {"!hasClass(args, getClassAttributeNode)", "lengthSpecials(args)"})
@@ -298,7 +298,7 @@ public final class SeqFunctions {
      * Essentially the same as {@link SeqFastPath} but since the signature is explicit there is no
      * need to reorder arguments.
      */
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class SeqDefaultFastPath extends FastPathAdapter {
         @SuppressWarnings("unused")
         @Specialization(guards = {"fromCheck.execute(fromObj)", "toCheck.execute(toObj)", "byCheck.execute(byObj)"})
@@ -320,7 +320,7 @@ public final class SeqFunctions {
         }
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     @RBuiltin(name = "seq_along", kind = PRIMITIVE, parameterNames = {"along.with"}, behavior = PURE)
     public abstract static class SeqAlong extends RBuiltinNode {
         @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNode.create();
@@ -367,7 +367,7 @@ public final class SeqFunctions {
         }
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     @RBuiltin(name = "seq_len", kind = PRIMITIVE, parameterNames = {"length.out"}, behavior = PURE)
     public abstract static class SeqLen extends RBuiltinNode {
 
@@ -406,7 +406,7 @@ public final class SeqFunctions {
      *
      * N.B. javac gives error "cannot find symbol" on plain "@RBuiltin".
      */
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     @ImportStatic({AsRealNodeGen.class, SeqFunctions.class})
     @com.oracle.truffle.r.runtime.builtins.RBuiltin(name = "seq.int", kind = PRIMITIVE, parameterNames = {"from", "to", "by", "length.out", "along.with",
                     "..."}, dispatch = INTERNAL_GENERIC, genericName = "seq", behavior = PURE)
@@ -417,7 +417,7 @@ public final class SeqFunctions {
 
         /**
          * Used by {@link #getLength} guard. It would be good to cache this in the relevant
-         * specializations but it does not use {@link RTypesFlatLayout} and that causes an
+         * specializations but it does not use {@link RTypes} and that causes an
          * IllegalStateException (no parent).
          */
         @Child private RLengthNode lengthNode = RLengthNode.create();
@@ -759,7 +759,7 @@ public final class SeqFunctions {
          * and often use "1" where "1L" is more appropriate).
          */
 
-        @TypeSystemReference(RTypesFlatLayout.class)
+        @TypeSystemReference(RTypes.class)
         public abstract static class IsIntegralNumericNode extends Node {
             private final boolean checkLength;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 08b8964ba8..541be369d7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -30,6 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode;
@@ -51,7 +52,6 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTypesGen;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -239,54 +239,40 @@ public abstract class UpdateAttributes extends RBuiltinNode {
         return res;
     }
 
-    protected static boolean isAbstractContainer(Object value) {
-        return RTypesGen.isImplicitRAbstractContainer(value);
-    }
-
     /**
      * All other, non-performance centric, {@link RAttributable} types, or error case for RNull
      * value.
      */
-    @Specialization(guards = {"!isAbstractContainer(o)"})
+    @Fallback
     @TruffleBoundary
-    protected Object doOtherNull(Object o, @SuppressWarnings("unused") RNull operand) {
+    protected Object doOtherNull(Object o, Object operand) {
         checkAttributable(o);
         Object obj = getNonShared(o);
         RAttributable attrObj = (RAttributable) obj;
         attrObj.removeAllAttributes();
-        attrObj.setClassAttr(null);
-        return obj;
-    }
 
-    /**
-     * All other, non-performance centric, {@link RAttributable} types, or error case for list
-     * value.
-     */
-    @Specialization(guards = {"!isAbstractContainer(o)"})
-    @TruffleBoundary
-    protected Object doOtherList(Object o, RList operand) {
-        checkAttributable(o);
-        Object obj = getNonShared(o);
-        RAttributable attrObj = (RAttributable) obj;
-        attrObj.removeAllAttributes();
-        RStringVector listNames = operand.getNames();
-        if (listNames == null) {
-            throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
-        }
-        for (int i = 0; i < operand.getLength(); i++) {
-            String attrName = listNames.getDataAt(i);
-            if (attrName == null) {
+        if (operand == RNull.instance) {
+            attrObj.setClassAttr(null);
+        } else {
+            RList list = (RList) operand;
+            RStringVector listNames = list.getNames();
+            if (listNames == null) {
                 throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
             }
-            if (RRuntime.CLASS_ATTR_KEY.equals(attrName)) {
-                Object attrValue = operand.getDataAt(i);
-                if (attrValue == null) {
-                    throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR);
+            for (int i = 0; i < list.getLength(); i++) {
+                String attrName = listNames.getDataAt(i);
+                if (attrName == null) {
+                    throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
+                }
+                if (RRuntime.CLASS_ATTR_KEY.equals(attrName)) {
+                    Object attrValue = list.getDataAt(i);
+                    if (attrValue == null) {
+                        throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR);
+                    }
+                    attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
+                } else {
+                    attrObj.setAttr(attrName.intern(), list.getDataAt(i));
                 }
-
-                attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
-            } else {
-                attrObj.setAttr(attrName.intern(), operand.getDataAt(i));
             }
         }
         return obj;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 144f70966b..f99feb45d8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -54,7 +54,7 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
@@ -184,7 +184,7 @@ abstract class SubscriptSpecial2 extends SubscriptSpecial2Base {
 }
 
 @RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-@TypeSystemReference(RTypesFlatLayout.class)
+@TypeSystemReference(RTypes.class)
 public abstract class Subscript extends RBuiltinNode {
 
     @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE)
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
index 3190231267..6005517090 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,11 +38,11 @@ import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.runtime.data.RTypes;
+import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-@TypeSystemReference(RTypes.class)
+@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class FrameSlotNode extends RBaseNode {
 
     public abstract boolean hasValue(Frame frame);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index 990fdbfe45..2e8a35d214 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -930,7 +930,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
 /*
  * This is RRuntime.checkType in the node form.
  */
-@TypeSystemReference(RTypesFlatLayout.class)
+@TypeSystemReference(RTypes.class)
 abstract class CheckTypeNode extends RBaseNode {
 
     public abstract boolean executeBoolean(Object o);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
index 8f60448bc2..60061c0032 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
@@ -30,12 +30,12 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 
-@TypeSystemReference(RTypesFlatLayout.class)
+@TypeSystemReference(RTypes.class)
 public abstract class AsCharNode extends FFIUpCallNode.Arg1 {
     private static final CharSXPWrapper CharSXPWrapper_NA = CharSXPWrapper.create(RRuntime.STRING_NA);
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
index a9cc0ef6bb..c37f801fcf 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
  * Implements the {@code Rf_asInteger} GNU R function . The behavior is subtly different (more
  * permissive error-wise) that {@link CastIntegerNode}. Non-castable values return {@code NA}.
  */
-@TypeSystemReference(RTypesFlatLayout.class)
+@TypeSystemReference(RTypes.class)
 public abstract class AsIntegerNode extends FFIUpCallNode.Arg1 {
 
     public abstract int execute(Object obj);
@@ -90,5 +90,4 @@ public abstract class AsIntegerNode extends FFIUpCallNode.Arg1 {
     public static AsIntegerNode create() {
         return AsIntegerNodeGen.create();
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
index b56d55b6e4..3f10ca646b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
@@ -29,11 +29,11 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.unary.CastLogicalNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
-@TypeSystemReference(RTypesFlatLayout.class)
+@TypeSystemReference(RTypes.class)
 public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 {
 
     public abstract int execute(Object obj);
@@ -72,5 +72,4 @@ public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 {
     public static AsLogicalNode create() {
         return AsLogicalNodeGen.create();
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
index 0f97790230..b0667ef048 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
@@ -19,7 +19,7 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
  * subtly different (more permissive error-wise) that {@link CastDoubleNode}. Non-castable values
  * return {@code NA}.
  */
-@TypeSystemReference(RTypesFlatLayout.class)
+@TypeSystemReference(RTypes.class)
 public abstract class AsRealNode extends FFIUpCallNode.Arg1 {
 
     public abstract double execute(Object obj);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
index 1b443987e4..7dee1d0b06 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RPairList;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 
 /**
  * Nodes that implement {@code CAR}, {@code CDR}, etc. N.B. GNU R does not error check the
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
  */
 public final class ListAccessNodes {
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class CARNode extends FFIUpCallNode.Arg1 {
         @Specialization
         protected Object car(RPairList pl) {
@@ -56,7 +56,7 @@ public final class ListAccessNodes {
 
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class CDRNode extends FFIUpCallNode.Arg1 {
         @Specialization
         protected Object cdr(RPairList pl) {
@@ -76,7 +76,7 @@ public final class ListAccessNodes {
         }
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class CADRNode extends FFIUpCallNode.Arg1 {
         @Specialization
         protected Object cadr(RPairList pl) {
@@ -95,7 +95,7 @@ public final class ListAccessNodes {
 
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class CADDRNode extends FFIUpCallNode.Arg1 {
         @Specialization
         protected Object caddr(RPairList pl) {
@@ -114,7 +114,7 @@ public final class ListAccessNodes {
 
     }
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class CDDRNode extends FFIUpCallNode.Arg1 {
         @Specialization
         protected Object cddr(RPairList pl) {
@@ -133,5 +133,4 @@ public final class ListAccessNodes {
 
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
index 4d833e1641..f3e2f0edc2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
@@ -28,14 +28,14 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 public final class MiscNodes {
 
-    @TypeSystemReference(RTypesFlatLayout.class)
+    @TypeSystemReference(RTypes.class)
     public abstract static class LENGTHNode extends FFIUpCallNode.Arg1 {
 
         @Specialization
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
index 6b473ad2b6..2ed4032233 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,13 +28,12 @@ import com.oracle.truffle.api.dsl.TypeCheck;
 import com.oracle.truffle.api.dsl.TypeSystem;
 import com.oracle.truffle.api.dsl.internal.DSLOptions;
 import com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator;
-import com.oracle.truffle.api.frame.FrameSlot;
-import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -49,12 +48,27 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  *
  * @see RNode
  */
-@TypeSystem({boolean.class, byte.class, int.class, double.class, RRaw.class, RComplex.class, String.class, RIntSequence.class, RDoubleSequence.class, RIntVector.class, RDoubleVector.class,
-                RRawVector.class, RComplexVector.class, RStringVector.class, RLogicalVector.class, RFunction.class, RNull.class, RMissing.class, REmpty.class, REnvironment.class, RExpression.class,
-                MaterializedFrame.class, FrameSlot.class, RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class,
-                RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RSymbol.class, RPromise.class, RLanguage.class,
-                RPairList.class, RExternalPtr.class, RS4Object.class, RAbstractContainer.class, RAttributable.class, RArgsValuesAndNames.class, RTypedValue.class, RType.class, Object[].class})
-@DSLOptions(defaultGenerator = DSLGenerator.DEFAULT)
+@TypeSystem({
+                byte.class, RAbstractLogicalVector.class,
+                int.class, RAbstractIntVector.class,
+                double.class, RAbstractDoubleVector.class,
+                String.class, RAbstractStringVector.class,
+                RRaw.class, RAbstractRawVector.class,
+                RComplex.class, RAbstractComplexVector.class,
+                RAbstractListVector.class,
+                RNull.class,
+                RExpression.class,
+                RPromise.class,
+                RMissing.class,
+                RPairList.class,
+                RSymbol.class,
+                RLanguage.class,
+                RFunction.class,
+                REnvironment.class,
+                RAbstractContainer.class,
+                RArgsValuesAndNames.class
+})
+@DSLOptions(defaultGenerator = DSLGenerator.FLAT)
 public class RTypes {
 
     @TypeCheck(RNull.class)
@@ -109,56 +123,6 @@ public class RTypes {
         return RDataFactory.createStringVectorFromScalar(value);
     }
 
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RIntVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RDoubleVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RLogicalVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RComplexVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RRawVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RStringVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RDoubleSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RList vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RAbstractVector vector) {
-        return vector;
-    }
-
     @ImplicitCast
     public static RAbstractVector toAbstractVector(int value) {
         return RDataFactory.createIntVectorFromScalar(value);
@@ -189,119 +153,64 @@ public class RTypes {
         return RDataFactory.createStringVectorFromScalar(value);
     }
 
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RIntVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RDoubleVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RLogicalVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RComplexVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RRawVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RStringVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RDoubleSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RList vector) {
-        return vector;
-    }
-
     @ImplicitCast
     public static RAbstractIntVector toAbstractIntVector(int value) {
         return RDataFactory.createIntVectorFromScalar(value);
     }
 
-    @ImplicitCast
-    public static RAbstractIntVector toAbstractIntVector(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractIntVector toAbstractIntVector(RIntVector vector) {
-        return vector;
-    }
-
     @ImplicitCast
     public static RAbstractDoubleVector toAbstractDoubleVector(double value) {
         return RDataFactory.createDoubleVectorFromScalar(value);
     }
 
     @ImplicitCast
-    public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleSequence vector) {
-        return vector;
+    public static RAbstractComplexVector toAbstractComplexVector(RComplex vector) {
+        return RDataFactory.createComplexVectorFromScalar(vector);
     }
 
     @ImplicitCast
-    public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleVector vector) {
-        return vector;
+    public static RAbstractLogicalVector toAbstractLogicalVector(byte vector) {
+        return RDataFactory.createLogicalVectorFromScalar(vector);
     }
 
     @ImplicitCast
-    public static RAbstractComplexVector toAbstractComplexVector(RComplexVector vector) {
-        return vector;
+    public static RAbstractRawVector toAbstractRawVector(RRaw vector) {
+        return RDataFactory.createRawVectorFromScalar(vector);
     }
 
     @ImplicitCast
-    public static RAbstractComplexVector toAbstractComplexVector(RComplex vector) {
-        return RDataFactory.createComplexVectorFromScalar(vector);
+    public static RAbstractStringVector toAbstractStringVector(String vector) {
+        return RDataFactory.createStringVectorFromScalar(vector);
     }
 
     @ImplicitCast
-    public static RAbstractLogicalVector toAbstractLogicalVector(byte vector) {
-        return RDataFactory.createLogicalVectorFromScalar(vector);
+    public static RAbstractAtomicVector toAbstractAtomicVector(int value) {
+        return RDataFactory.createIntVectorFromScalar(value);
     }
 
     @ImplicitCast
-    public static RAbstractLogicalVector toAbstractLogicalVector(RLogicalVector vector) {
-        return vector;
+    public static RAbstractAtomicVector toAbstractAtomicVector(double value) {
+        return RDataFactory.createDoubleVectorFromScalar(value);
     }
 
     @ImplicitCast
-    public static RAbstractRawVector toAbstractRawVector(RRaw vector) {
-        return RDataFactory.createRawVectorFromScalar(vector);
+    public static RAbstractAtomicVector toAbstractAtomicVector(RRaw value) {
+        return RDataFactory.createRawVectorFromScalar(value);
     }
 
     @ImplicitCast
-    public static RAbstractRawVector toAbstractRawVector(RRawVector vector) {
-        return vector;
+    public static RAbstractAtomicVector toAbstractAtomicVector(byte value) {
+        return RDataFactory.createLogicalVectorFromScalar(value);
     }
 
     @ImplicitCast
-    public static RAbstractStringVector toAbstractStringVector(String vector) {
-        return RDataFactory.createStringVectorFromScalar(vector);
+    public static RAbstractAtomicVector toAbstractAtomicVector(RComplex value) {
+        return RDataFactory.createComplexVectorFromScalar(value);
     }
 
     @ImplicitCast
-    public static RAbstractStringVector toAbstractStringVector(RStringVector vector) {
-        return vector;
+    public static RAbstractAtomicVector toAbstractAtomicVector(String value) {
+        return RDataFactory.createStringVectorFromScalar(value);
     }
 
     @ImplicitCast
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java
deleted file mode 100644
index b0c6f4bbb0..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypesFlatLayout.java
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data;
-
-import com.oracle.truffle.api.dsl.ImplicitCast;
-import com.oracle.truffle.api.dsl.TypeCast;
-import com.oracle.truffle.api.dsl.TypeCheck;
-import com.oracle.truffle.api.dsl.TypeSystem;
-import com.oracle.truffle.api.dsl.internal.DSLOptions;
-import com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator;
-import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RNode;
-
-/**
- * Whenever you add a type {@code T} to the list below, make sure a corresponding {@code executeT()}
- * method is added to {@link RNode}, a {@code typeof} method is added to {@code TypeoNode} and a
- * {@code print} method added to {code PrettyPrinterNode}.
- *
- * @see RNode
- */
-@TypeSystem({byte.class, int.class, double.class})
-@DSLOptions(defaultGenerator = DSLGenerator.FLAT)
-public class RTypesFlatLayout {
-
-    @TypeCheck(RNull.class)
-    public static boolean isRNull(Object value) {
-        return value == RNull.instance;
-    }
-
-    @TypeCast(RNull.class)
-    @SuppressWarnings("unused")
-    public static RNull asRNull(Object value) {
-        return RNull.instance;
-    }
-
-    @TypeCheck(RMissing.class)
-    public static boolean isRMissing(Object value) {
-        return value == RMissing.instance;
-    }
-
-    @TypeCast(RMissing.class)
-    @SuppressWarnings("unused")
-    public static RMissing asRMissing(Object value) {
-        return RMissing.instance;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(int value) {
-        return RDataFactory.createIntVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(double value) {
-        return RDataFactory.createDoubleVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RRaw value) {
-        return RDataFactory.createRawVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(byte value) {
-        return RDataFactory.createLogicalVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RComplex value) {
-        return RDataFactory.createComplexVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(String value) {
-        return RDataFactory.createStringVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RIntVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RDoubleVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RLogicalVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RComplexVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RRawVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RStringVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RDoubleSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RList vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractContainer toAbstractContainer(RAbstractVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(int value) {
-        return RDataFactory.createIntVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(double value) {
-        return RDataFactory.createDoubleVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RRaw value) {
-        return RDataFactory.createRawVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(byte value) {
-        return RDataFactory.createLogicalVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RComplex value) {
-        return RDataFactory.createComplexVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(String value) {
-        return RDataFactory.createStringVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RIntVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RDoubleVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RLogicalVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RComplexVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RRawVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RStringVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RDoubleSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractVector(RList vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractIntVector toAbstractIntVector(int value) {
-        return RDataFactory.createIntVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractIntVector toAbstractIntVector(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractIntVector toAbstractIntVector(RIntVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractDoubleVector toAbstractDoubleVector(double value) {
-        return RDataFactory.createDoubleVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractDoubleVector toAbstractDoubleVector(RDoubleVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractComplexVector toAbstractComplexVector(RComplexVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractComplexVector toAbstractComplexVector(RComplex vector) {
-        return RDataFactory.createComplexVectorFromScalar(vector);
-    }
-
-    @ImplicitCast
-    public static RAbstractLogicalVector toAbstractLogicalVector(byte vector) {
-        return RDataFactory.createLogicalVectorFromScalar(vector);
-    }
-
-    @ImplicitCast
-    public static RAbstractLogicalVector toAbstractLogicalVector(RLogicalVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractRawVector toAbstractRawVector(RRaw vector) {
-        return RDataFactory.createRawVectorFromScalar(vector);
-    }
-
-    @ImplicitCast
-    public static RAbstractRawVector toAbstractRawVector(RRawVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractStringVector toAbstractStringVector(String vector) {
-        return RDataFactory.createStringVectorFromScalar(vector);
-    }
-
-    @ImplicitCast
-    public static RAbstractStringVector toAbstractStringVector(RStringVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RMissing toRMissing(@SuppressWarnings("unused") REmpty empty) {
-        return RMissing.instance;
-    }
-
-    // RAbstractAtomicVector
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(int value) {
-        return RDataFactory.createIntVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(double value) {
-        return RDataFactory.createDoubleVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RRaw value) {
-        return RDataFactory.createRawVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(byte value) {
-        return RDataFactory.createLogicalVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RComplex value) {
-        return RDataFactory.createComplexVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(String value) {
-        return RDataFactory.createStringVectorFromScalar(value);
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RIntVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RDoubleVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RLogicalVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RComplexVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RRawVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RStringVector vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractAtomicVector toAbstractAtomicVector(RIntSequence vector) {
-        return vector;
-    }
-
-    @ImplicitCast
-    public static RAbstractVector toAbstractAtomicVector(RDoubleSequence vector) {
-        return vector;
-    }
-
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java
index 839804eb00..bb039d34c6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractAtomicVector.java
@@ -22,9 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
-
 /**
  * Distinguishes what R considers an "atomic" vector, e.g. {@code integer()} from other "vectors",
  * e.g., {@code list()}. Specifically these are the FastR atomic vector types:
@@ -36,8 +33,6 @@ import com.oracle.truffle.r.runtime.data.RTypesFlatLayout;
  * <li>{@link RAbstractStringVector}</li>
  * <li>{@link RAbstractRawVector}</li>
  * </ul>
- *
- * N.B. To use this in a {@link Specialization} you must use {@link RTypesFlatLayout}.
  */
 public interface RAbstractAtomicVector extends RAbstractVector {
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
index 8629846c53..ef19d63069 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
@@ -26,26 +26,16 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrumentation.Instrumentable;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RComplexVector;
-import com.oracle.truffle.r.runtime.data.RDoubleSequence;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RIntSequence;
-import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RRawVector;
-import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.RTypesGen;
@@ -56,11 +46,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory;
 
 @TypeSystemReference(RTypes.class)
-@Instrumentable(factory = com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory.class)
+@Instrumentable(factory = RNodeWrapperFactory.class)
 public abstract class RNode extends RBaseNode implements RInstrumentableNode {
 
     /**
@@ -86,122 +76,47 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode {
     }
 
     public int executeInteger(VirtualFrame frame) throws UnexpectedResultException {
-        Object value = execute(frame);
-        assert value != null;
-        if (value instanceof Integer) {
-            return (int) value;
-        } else {
-            throw new UnexpectedResultException(value);
-        }
+        return RTypesGen.expectInteger(execute(frame));
     }
 
     public RRaw executeRRaw(VirtualFrame frame) throws UnexpectedResultException {
-        Object value = execute(frame);
-        assert value != null;
-        if (value instanceof RRaw) {
-            return (RRaw) value;
-        } else {
-            throw new UnexpectedResultException(value);
-        }
-    }
-
-    public RAbstractVector executeRAbstractVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractVector(execute(frame));
+        return RTypesGen.expectRRaw(execute(frame));
     }
 
     public RComplex executeRComplex(VirtualFrame frame) throws UnexpectedResultException {
-        Object value = execute(frame);
-        assert value != null;
-        assert value != null;
-        if (value instanceof RComplex) {
-            return (RComplex) value;
-        } else {
-            throw new UnexpectedResultException(value);
-        }
-    }
-
-    public RIntSequence executeRIntSequence(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRIntSequence(execute(frame));
-    }
-
-    public RDoubleSequence executeRDoubleSequence(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRDoubleSequence(execute(frame));
-    }
-
-    public RIntVector executeRIntVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRIntVector(execute(frame));
-    }
-
-    public RDoubleVector executeRDoubleVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRDoubleVector(execute(frame));
-    }
-
-    public RRawVector executeRRawVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRRawVector(execute(frame));
-    }
-
-    public RComplexVector executeRComplexVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRComplexVector(execute(frame));
-    }
-
-    public RStringVector executeRStringVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRStringVector(execute(frame));
-    }
-
-    public RList executeRList(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRList(execute(frame));
-    }
-
-    public RLogicalVector executeRLogicalVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRLogicalVector(execute(frame));
+        return RTypesGen.expectRComplex(execute(frame));
     }
 
     public RAbstractDoubleVector executeRAbstractDoubleVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractDoubleVector(executeRAbstractVector(frame));
+        return RTypesGen.expectRAbstractDoubleVector(execute(frame));
     }
 
     public RAbstractIntVector executeRAbstractIntVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractIntVector(executeRAbstractVector(frame));
+        return RTypesGen.expectRAbstractIntVector(execute(frame));
     }
 
     public RAbstractComplexVector executeRAbstractComplexVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractComplexVector(executeRAbstractVector(frame));
+        return RTypesGen.expectRAbstractComplexVector(execute(frame));
     }
 
     public RAbstractLogicalVector executeRAbstractLogicalVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractLogicalVector(executeRAbstractVector(frame));
+        return RTypesGen.expectRAbstractLogicalVector(execute(frame));
     }
 
     public RAbstractRawVector executeRAbstractRawVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractRawVector(executeRAbstractVector(frame));
+        return RTypesGen.expectRAbstractRawVector(execute(frame));
     }
 
     public RAbstractStringVector executeRAbstractStringVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractStringVector(executeRAbstractVector(frame));
+        return RTypesGen.expectRAbstractStringVector(execute(frame));
     }
 
     public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
-        Object value = execute(frame);
-        assert value != null;
-        if (value instanceof Double) {
-            return (double) value;
-        } else {
-            throw new UnexpectedResultException(value);
-        }
+        return RTypesGen.expectDouble(execute(frame));
     }
 
     public byte executeByte(VirtualFrame frame) throws UnexpectedResultException {
-        Object value = execute(frame);
-        assert value != null;
-        if (value instanceof Byte) {
-            return (byte) value;
-        } else {
-            throw new UnexpectedResultException(value);
-        }
-    }
-
-    public Object[] executeArray(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectObjectArray(execute(frame));
+        return RTypesGen.expectByte(execute(frame));
     }
 
     public RFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException {
@@ -217,13 +132,7 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode {
     }
 
     public String executeString(VirtualFrame frame) throws UnexpectedResultException {
-        Object value = execute(frame);
-        assert value != null;
-        if (value instanceof String) {
-            return (String) value;
-        } else {
-            throw new UnexpectedResultException(value);
-        }
+        return RTypesGen.expectString(execute(frame));
     }
 
     public REnvironment executeREnvironment(VirtualFrame frame) throws UnexpectedResultException {
@@ -257,8 +166,4 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode {
     public RArgsValuesAndNames executeRArgsValuesAndNames(VirtualFrame frame) throws UnexpectedResultException {
         return RTypesGen.expectRArgsValuesAndNames(execute(frame));
     }
-
-    public RType executeType(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRType(execute(frame));
-    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java
index afa9fbc4c1..f473c3d01c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java
@@ -139,9 +139,7 @@ public class TestBuiltin_seq_along extends TestBase {
         assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) '48'; seq_along(x) }");
         assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) }");
         assertEval(Output.IgnoreWarningContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) }");
-        // length defined in global env should not get us confused:
         assertEval("{ length <- function(x) 42; seq_along(c(1,2,3)) }");
-        // length in __S3MethodsTable__ should work too
         assertEval("{ assign('length.myclass', function(...) 42, envir=.__S3MethodsTable__.); x <- 1; class(x) <- 'myclass'; res <- seq_along(x); rm('length.myclass', envir=.__S3MethodsTable__.); res }");
     }
 }
-- 
GitLab


From 168320ccf0dcd9510631807ab9b5a42bc059b433 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 1 Feb 2017 11:51:44 +0100
Subject: [PATCH 025/402] remove obsolete EmptyTypeSystemFlatLayout

---
 .../r/library/stats/RandFunctionsNodes.java   |  5 ---
 .../r/nodes/builtin/base/RNGFunctions.java    |  4 --
 .../truffle/r/nodes/builtin/base/Sample2.java |  3 --
 .../r/nodes/builtin/base/UpdateAttr.java      |  3 --
 .../nodes/builtin/base/infix/AccessField.java |  4 --
 .../builtin/base/infix/SpecialsUtils.java     |  6 ---
 .../r/nodes/builtin/base/infix/Subset.java    |  4 --
 .../r/nodes/builtin/base/infix/Tilde.java     |  3 --
 .../nodes/builtin/base/infix/UpdateField.java |  3 --
 .../builtin/base/infix/UpdateSubscript.java   |  3 --
 .../builtin/base/infix/UpdateSubset.java      |  3 --
 .../r/nodes/EmptyTypeSystemFlatLayout.java    | 37 -------------------
 .../truffle/r/nodes/access/FrameSlotNode.java |  3 --
 .../access/vector/ExtractListElement.java     |  3 --
 .../nodes/attributes/AttributeAccessNode.java |  3 --
 .../AttributeIterativeAccessNode.java         |  3 --
 .../nodes/binary/BinaryArithmeticSpecial.java |  4 --
 .../r/nodes/binary/BinaryBooleanSpecial.java  |  3 --
 .../r/nodes/control/ReplacementNode.java      |  3 --
 .../r/nodes/function/ArgumentStatePush.java   |  3 --
 .../r/nodes/function/ClassHierarchyNode.java  |  3 --
 .../truffle/r/nodes/function/RCallNode.java   |  4 --
 .../nodes/function/call/PrepareArguments.java |  3 --
 .../r/nodes/function/opt/ShareObjectNode.java |  4 +-
 .../signature/CombineSignaturesNode.java      |  3 --
 25 files changed, 1 insertion(+), 119 deletions(-)
 delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index 14f9409f3e..d365281f27 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -22,7 +22,6 @@ import java.util.Arrays;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
@@ -30,7 +29,6 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.ConvertToLen
 import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction1NodeGen;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction2NodeGen;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction3NodeGen;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
@@ -99,7 +97,6 @@ public final class RandFunctionsNodes {
      * result vector, and similar. The random function is provided as implementation of
      * {@link RandFunction3_Double}.
      */
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     protected abstract static class RandFunctionExecutorBase extends Node {
         static final class RandGenerationNodeData {
             final BranchProfile nanResult = BranchProfile.create();
@@ -155,7 +152,6 @@ public final class RandFunctionsNodes {
         }
     }
 
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     protected abstract static class RandFunctionIntExecutorNode extends RandFunctionExecutorBase {
         @Child private RandFunction3_Double function;
 
@@ -201,7 +197,6 @@ public final class RandFunctionsNodes {
         }
     }
 
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     protected abstract static class RandFunctionDoubleExecutorNode extends RandFunctionExecutorBase {
         @Child private RandFunction3_Double function;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
index 315f03279d..a2e1f23a25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
@@ -36,8 +36,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -48,7 +46,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.rng.RRNG;
 
 public class RNGFunctions {
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     @RBuiltin(name = "set.seed", visibility = OFF, kind = INTERNAL, parameterNames = {"seed", "kind", "normal.kind"}, behavior = MODIFIES_STATE)
     public abstract static class SetSeed extends RBuiltinNode {
 
@@ -79,7 +76,6 @@ public class RNGFunctions {
         }
     }
 
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     @RBuiltin(name = "RNGkind", kind = INTERNAL, parameterNames = {"kind", "normkind"}, behavior = MODIFIES_STATE)
     public abstract static class RNGkind extends RBuiltinNode {
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
index 8b1ad3e4b6..57c65861aa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
@@ -25,9 +25,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetInt;
@@ -42,7 +40,6 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  * Sample2 is more efficient special case implementation of {@link Sample}.
  */
 @RBuiltin(name = "sample2", kind = INTERNAL, parameterNames = {"x", "size"}, behavior = MODIFIES_STATE)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class Sample2 extends RBuiltinNode {
     private static final double U = 33554432.0;
     static final double MAX_INT = Integer.MAX_VALUE;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index a9d87f4e49..f9c56347d3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -33,10 +33,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
@@ -79,7 +77,6 @@ public abstract class UpdateAttr extends RBuiltinNode {
 
     @Child private InternStringNode intern = InternStringNodeGen.create();
 
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     public abstract static class InternStringNode extends Node {
 
         public abstract String execute(String value);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
index e41593722b..d89fdf7ecc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
@@ -31,11 +31,9 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -52,7 +50,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 @NodeChild(value = "arguments", type = RNode[].class)
 abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
 
@@ -86,7 +83,6 @@ abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
 }
 
 @RBuiltin(name = "$", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class AccessField extends RBuiltinNode {
 
     @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 501753254b..301672faa1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -26,12 +26,10 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen;
@@ -64,7 +62,6 @@ class SpecialsUtils {
     /**
      * Common code shared between specials doing subset/subscript related operation.
      */
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     abstract static class SubscriptSpecialCommon extends RNode {
 
         protected final boolean inReplacement;
@@ -90,7 +87,6 @@ class SpecialsUtils {
         }
     }
 
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     abstract static class SubscriptSpecial2Common extends SubscriptSpecialCommon {
 
         protected SubscriptSpecial2Common(boolean inReplacement) {
@@ -115,7 +111,6 @@ class SpecialsUtils {
     /**
      * Common code shared between specials accessing/updating fields.
      */
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     abstract static class ListFieldSpecialBase extends RNode {
 
         @Child private ClassHierarchyNode hierarchyNode = ClassHierarchyNode.create();
@@ -172,7 +167,6 @@ class SpecialsUtils {
 
     @NodeInfo(cost = NodeCost.NONE)
     @NodeChild(value = "delegate", type = RNode.class)
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     public abstract static class ConvertIndex extends RNode {
 
         protected abstract RNode getDelegate();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index 82199ccb54..0042a04609 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
@@ -30,9 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -90,7 +88,6 @@ abstract class SubsetSpecial extends SubscriptSpecialBase {
  * Subset special only handles single element integer/double index. In the case of list, we need to
  * create the actual list otherwise we just return the primitive type.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 abstract class SubsetSpecial2 extends SubscriptSpecial2Base {
 
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
@@ -112,7 +109,6 @@ abstract class SubsetSpecial2 extends SubscriptSpecial2Base {
 }
 
 @RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class Subset extends RBuiltinNode {
 
     @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
index 5376735712..474cd495bb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
@@ -27,9 +27,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -50,7 +48,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * argument is missing, i.e. {@code ~ x} result in {@code `~`(x)}.
  */
 @RBuiltin(name = "~", kind = PRIMITIVE, parameterNames = {"x", "y"}, nonEvalArgs = {0, 1}, behavior = READS_FRAME)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class Tilde extends RBuiltinNode {
 
     private static final RStringVector FORMULA_CLASS = RDataFactory.createStringVectorFromScalar(RRuntime.FORMULA_CLASS);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
index d5ff59a1c9..d2d7c567ba 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
@@ -32,10 +32,8 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
@@ -116,7 +114,6 @@ abstract class UpdateFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
 }
 
 @RBuiltin(name = "$<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class UpdateField extends RBuiltinNode {
 
     @Child private ReplaceVectorNode update = ReplaceVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index cfc2f94db1..a1fc8e1653 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -33,10 +33,8 @@ import java.util.Arrays;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -161,7 +159,6 @@ abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
 }
 
 @RBuiltin(name = "[[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class UpdateSubscript extends RBuiltinNode {
 
     @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 30ad8a85fc..75f6199966 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -31,10 +31,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -48,7 +46,6 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 @RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class UpdateSubset extends RBuiltinNode {
 
     @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSET, false);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java
deleted file mode 100644
index 63903c8fcb..0000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/EmptyTypeSystemFlatLayout.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes;
-
-import static com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator.FLAT;
-
-import com.oracle.truffle.api.dsl.TypeSystem;
-import com.oracle.truffle.api.dsl.internal.DSLOptions;
-
-/**
- * Auxiliary class for nodes that want to use the new DSL layout with no implicit type conversions.
- */
-@TypeSystem
-@DSLOptions(defaultGenerator = FLAT)
-public class EmptyTypeSystemFlatLayout {
-    // empty
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
index 6005517090..e9ec3546f2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.find
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
@@ -38,11 +37,9 @@ import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class FrameSlotNode extends RBaseNode {
 
     public abstract boolean hasValue(Frame frame);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java
index 485ca001bc..d7c432c78e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java
@@ -24,9 +24,7 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode;
 import com.oracle.truffle.r.runtime.data.RListBase;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -47,7 +45,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
  * convenient wrapper that performs the extraction as well as invocation of
  * {@link UpdateShareableChildValueNode}. See also the documentation of {@link RListBase}.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class ExtractListElement extends Node {
 
     public abstract Object execute(RAbstractContainer container, int index);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java
index e2a4149113..f19f5253ee 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java
@@ -23,19 +23,16 @@
 package com.oracle.truffle.r.nodes.attributes;
 
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.object.Location;
 import com.oracle.truffle.api.object.Property;
 import com.oracle.truffle.api.object.Shape;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * The base class for the nodes that get/set/remove attributes. It encapsulates the common methods
  * used in guards and for caching.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class AttributeAccessNode extends RBaseNode {
 
     protected AttributeAccessNode() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java
index 5c3512aab3..da7df67a31 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeIterativeAccessNode.java
@@ -24,13 +24,11 @@ package com.oracle.truffle.r.nodes.attributes;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.object.Property;
 import com.oracle.truffle.api.object.Shape;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout.AttrsLayout;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -43,7 +41,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * properties (i.e. attributes) it is unnecessary to invoke method {@link Shape#getPropertyList()},
  * which would be more expensive.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class AttributeIterativeAccessNode extends RBaseNode {
 
     protected static final int CACHE_LIMIT = RAttributesLayout.LAYOUTS.length;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
index ce80a9a8b3..014a9a8aae 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
@@ -28,9 +28,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.binary.BinaryArithmeticSpecialNodeGen.IntegerBinaryArithmeticSpecialNodeGen;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
@@ -44,7 +42,6 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
  * handling, which is replicated here, others (notably pow and mul) throw
  * {@link RSpecialFactory#throwFullCallNeeded()} on NA.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 @NodeChild(value = "left", type = RNode.class)
 @NodeChild(value = "right", type = RNode.class)
 public abstract class BinaryArithmeticSpecial extends RNode {
@@ -101,7 +98,6 @@ public abstract class BinaryArithmeticSpecial extends RNode {
     /**
      * Adds integers handling.
      */
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     abstract static class IntegerBinaryArithmeticSpecial extends BinaryArithmeticSpecial {
 
         IntegerBinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java
index d2f20e7dc5..96c8af2564 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java
@@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.binary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -38,7 +36,6 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory;
  * empty type system to avoid conversions to vector types. NA values cause
  * {@link RSpecialFactory#throwFullCallNeeded()} exception.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 @NodeChild(value = "arguments", type = RNode[].class)
 public abstract class BinaryBooleanSpecial extends RNode {
     @Child private BooleanOperation operation;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index 5986bdbb7b..54b6e8d4f7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -28,12 +28,10 @@ import java.util.List;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
@@ -53,7 +51,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 abstract class ReplacementNode extends OperatorNode {
 
     protected final RSyntaxElement lhs;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index b8ca65da53..5ab82f5b4e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -25,11 +25,9 @@ package com.oracle.truffle.r.nodes.function;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -43,7 +41,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 /**
  * A {@link ArgumentStatePush} is used to bump up state transition for function arguments.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class ArgumentStatePush extends Node {
 
     public abstract void executeObject(VirtualFrame frame, Object shareable);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index 3e3a70f6a3..55b43d1f3f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -27,12 +27,10 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
@@ -57,7 +55,6 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class ClassHierarchyNode extends UnaryNode {
 
     private static final RStringVector truffleObjectClassHeader = RDataFactory.createStringVectorFromScalar("truffle.object");
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 5c9497e41b..54c5e060a0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
@@ -53,7 +52,6 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
@@ -105,7 +103,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 @NodeInfo(cost = NodeCost.NONE)
 @NodeChild(value = "function", type = RNode.class)
 public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall {
@@ -606,7 +603,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         }
     }
 
-    @TypeSystemReference(EmptyTypeSystemFlatLayout.class)
     public abstract static class FunctionDispatch extends Node {
 
         /**
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java
index d19da1dc99..554d2b2b0e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java
@@ -27,11 +27,9 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.function.ArgumentMatcher;
 import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation;
@@ -53,7 +51,6 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  * rules. It implements two different paths: one for arguments provided as an
  * {@link CallArgumentsNode}, i.e., unevaluated arguments, and another path for evaluated arguments.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class PrepareArguments extends Node {
 
     protected static final int CACHE_SIZE = 8;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java
index 523d27ac3d..b28a5f0d5e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java
@@ -26,11 +26,9 @@ import static com.oracle.truffle.api.nodes.NodeCost.NONE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 
@@ -42,9 +40,9 @@ import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
  * This class relies (and asserts) that all RShareable objects are subclasses of
  * RSharingAttributeStorage.
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 @NodeInfo(cost = NONE)
 public abstract class ShareObjectNode extends Node {
+
     public abstract Object execute(Object obj);
 
     public static ShareObjectNode create() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java
index 35e5972874..89f8b2a4e8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java
@@ -27,9 +27,7 @@ import java.util.Arrays;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -45,7 +43,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  *
  * @see com.oracle.truffle.r.nodes.function.ArgumentMatcher
  */
-@TypeSystemReference(EmptyTypeSystemFlatLayout.class)
 public abstract class CombineSignaturesNode extends RBaseNode {
 
     protected static final int CACHE_LIMIT = 3;
-- 
GitLab


From bc686ba1e4544b8ac101ffdfafac295a102cd27b Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 27 Jan 2017 15:42:08 +0100
Subject: [PATCH 026/402] fix match builtin

---
 .../truffle/r/nodes/builtin/base/Match.java   | 1248 +++++++++--------
 .../r/nodes/helpers/InheritsCheckNode.java    |    7 +-
 .../truffle/r/runtime/nodes/RBaseNode.java    |    8 +-
 3 files changed, 638 insertions(+), 625 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index 291aad6c29..dfa5e0c300 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalFalse;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.runtime.RError.Message.MATCH_VECTOR_ARGS;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -30,20 +32,23 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.MatchNodeGen.MatchInternalNodeGen;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.helpers.RFactorNodes;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.closures.RClosures;
@@ -58,6 +63,9 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
+/*
+ * TODO: handle "incomparables" parameter.
+ */
 @RBuiltin(name = "match", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "incomparables"}, behavior = PURE)
 public abstract class Match extends RBuiltinNode {
 
@@ -81,27 +89,14 @@ public abstract class Match extends RBuiltinNode {
         // MATCH_VECTOR_ARGS).asVectorPreserveAttrs(true);
         // casts.arg("table").allowNull().mustBe(abstractVectorValue()).asVectorPreserveAttrs(true);
         casts.arg("nomatch").asIntegerVector().findFirst();
-        // casts.arg("incomparables").allowNull().mustBe(abstractVectorValue()).asVectorPreserveAttrs(true);
-    }
-
-    private RAbstractStringVector castString(RAbstractVector operand) {
-        if (castString == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            castString = insert(CastStringNodeGen.create(false, false, false));
-        }
-        return (RAbstractStringVector) castString.execute(operand);
+        casts.arg("incomparables").defaultError(Message.GENERIC, "usage of 'incomparables' in match not implemented").allowNull().mustBe(logicalValue()).asLogicalVector().findFirst().mustBe(
+                        logicalFalse());
     }
 
-    private Object matchRecursive(Object x, Object table, Object noMatch, Object incomparables) {
-        if (matchRecursive == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            matchRecursive = insert(MatchNodeGen.create());
-        }
-        return matchRecursive.executeRIntVector(x, table, noMatch, incomparables);
+    protected static MatchInternalNode createInternal() {
+        return MatchInternalNodeGen.create();
     }
 
-    // FIXME deal incomparables parameter
-
     @Specialization
     @SuppressWarnings("unused")
     protected RIntVector match(RNull x, RNull table, int nomatch, Object incomparables) {
@@ -116,752 +111,765 @@ public abstract class Match extends RBuiltinNode {
 
     @Specialization
     @SuppressWarnings("unused")
-    protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object incomparables) {
+    protected RIntVector match(RAbstractVector x, RNull table, int nomatch, Object incomparables,
+                    @Cached("createBinaryProfile()") ConditionProfile na) {
         int[] data = new int[x.getLength()];
         Arrays.fill(data, nomatch);
-        naCheck.enable(nomatch);
-        naCheck.check(nomatch);
-        return RDataFactory.createIntVector(data, naCheck.neverSeenNA());
+        return RDataFactory.createIntVector(data, na.profile(!RRuntime.isNA(nomatch)));
+    }
+
+    @Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
+
+    protected boolean isFactor(Object o) {
+        return factorInheritsCheck.execute(o);
     }
 
     @Specialization(guards = {"isFactor(x)", "isFactor(table)"})
-    protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, int nomatch, Object incomparables,
-                    @Cached("create()") RFactorNodes.GetLevels getLevelsNode) {
-        naCheck.enable(x);
-        naCheck.enable(table);
-        return matchRecursive(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)),
-                        RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch, incomparables);
+    protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
+                    @Cached("create()") RFactorNodes.GetLevels getLevelsNode,
+                    @Cached("createInternal()") MatchInternalNode match) {
+        return match.execute(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)),
+                        RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch);
     }
 
     @Specialization(guards = {"isFactor(x)", "!isFactor(table)"})
-    protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, int nomatch, Object incomparables,
-                    @Cached("create()") RFactorNodes.GetLevels getLevelsNode) {
-        naCheck.enable(x);
-        return matchRecursive(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), table, nomatch, incomparables);
+    protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
+                    @Cached("create()") RFactorNodes.GetLevels getLevelsNode,
+                    @Cached("createInternal()") MatchInternalNode match) {
+        return match.execute(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), table, nomatch);
     }
 
     @Specialization(guards = {"!isFactor(x)", "isFactor(table)"})
-    protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, int nomatch, Object incomparables,
-                    @Cached("create()") RFactorNodes.GetLevels getLevelsNode) {
-        naCheck.enable(table);
-        return matchRecursive(x, RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch, incomparables);
+    protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
+                    @Cached("create()") RFactorNodes.GetLevels getLevelsNode,
+                    @Cached("createInternal()") MatchInternalNode match) {
+        return match.execute(x, RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch);
     }
 
-    @Specialization
-    protected Object matchList(RAbstractListVector x, Object table, Object nomatchObj, Object incomparables,
-                    @Cached("create()") CastStringNode cast) {
-        return matchRecursive(cast.execute(x), table, nomatchObj, incomparables);
+    @Specialization(guards = {"!isRAbstractIntVector(table) || !isFactor(table)"})
+    protected Object matchList(RAbstractListVector x, RAbstractVector table, int nomatchObj, @SuppressWarnings("unused") Object incomparables,
+                    @Cached("create()") CastStringNode cast,
+                    @Cached("createInternal()") MatchInternalNode match) {
+        return match.execute((RAbstractVector) cast.execute(x), table, nomatchObj);
     }
 
-    @Specialization
-    protected RIntVector match(RAbstractIntVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) {
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        NonRecursiveHashMapInt hashTable;
-        if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
-            hashTable = new NonRecursiveHashMapInt(x.getLength());
-            NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength());
-            for (int i = 0; i < result.length; i++) {
-                hashSet.add(x.getDataAt(i));
-            }
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                int val = table.getDataAt(i);
-                if (hashSet.contains(val)) {
-                    hashTable.put(val, i);
-                }
-            }
-        } else {
-            hashTable = new NonRecursiveHashMapInt(table.getLength());
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                hashTable.put(table.getDataAt(i), i);
+    @Specialization(guards = {"!isRAbstractListVector(x)", "!isRAbstractIntVector(x) || !isFactor(x)", "!isRAbstractIntVector(table) || !isFactor(table)"})
+    protected Object match(RAbstractVector x, RAbstractVector table, int noMatch, @SuppressWarnings("unused") Object incomparables,
+                    @Cached("createInternal()") MatchInternalNode match) {
+        return match.execute(x, table, noMatch);
+    }
+
+    @Fallback
+    @SuppressWarnings("unused")
+    protected RIntVector match(Object x, Object table, Object nomatch, Object incomparables) {
+        throw RError.error(this, MATCH_VECTOR_ARGS);
+    }
+
+    protected abstract static class MatchInternalNode extends Node {
+
+        private static final int TABLE_SIZE_FACTOR = 10;
+
+        protected abstract Object execute(RAbstractVector x, RAbstractVector table, int noMatch);
+
+        @Child private CastStringNode castString;
+
+        @Child private MatchInternalNode matchRecursive;
+
+        private final ConditionProfile bigTableProfile = ConditionProfile.createBinaryProfile();
+
+        private RAbstractStringVector castString(RAbstractVector operand) {
+            if (castString == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                castString = insert(CastStringNodeGen.create(false, false, false));
             }
+            return (RAbstractStringVector) castString.execute(operand);
         }
-        for (int i = 0; i < result.length; i++) {
-            int xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
+
+        @Specialization
+        protected RIntVector match(RAbstractIntVector x, RAbstractIntVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            NonRecursiveHashMapInt hashTable;
+            if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
+                hashTable = new NonRecursiveHashMapInt(x.getLength());
+                NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength());
+                for (int i = 0; i < result.length; i++) {
+                    hashSet.add(x.getDataAt(i));
+                }
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    int val = table.getDataAt(i);
+                    if (hashSet.contains(val)) {
+                        hashTable.put(val, i);
+                    }
+                }
             } else {
-                matchAll = false;
+                hashTable = new NonRecursiveHashMapInt(table.getLength());
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    hashTable.put(table.getDataAt(i), i);
+                }
             }
-        }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
-
-    @Specialization
-    protected RIntVector match(RAbstractDoubleVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) {
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        NonRecursiveHashMapDouble hashTable;
-        if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
-            hashTable = new NonRecursiveHashMapDouble(x.getLength());
-            NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength());
             for (int i = 0; i < result.length; i++) {
-                hashSet.add(x.getDataAt(i));
-            }
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                int val = table.getDataAt(i);
-                if (hashSet.contains(RRuntime.int2double(val))) {
-                    hashTable.put(RRuntime.int2double(val), i);
+                int xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
                 }
             }
-        } else {
-            hashTable = new NonRecursiveHashMapDouble(table.getLength());
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                hashTable.put(RRuntime.int2double(table.getDataAt(i)), i);
-            }
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        for (int i = 0; i < result.length; i++) {
-            double xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
-            } else {
-                matchAll = false;
-            }
-        }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
 
-    @Specialization
-    protected RIntVector match(RAbstractIntVector x, RAbstractDoubleVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) {
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        NonRecursiveHashMapInt hashTable;
-        if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
-            hashTable = new NonRecursiveHashMapInt(x.getLength());
-            NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength());
-            for (int i = 0; i < result.length; i++) {
-                hashSet.add(x.getDataAt(i));
-            }
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                double val = table.getDataAt(i);
-                if (RRuntime.isNA(val) && hashSet.contains(RRuntime.INT_NA)) {
-                    hashTable.put(RRuntime.INT_NA, i);
-                } else if (val == (int) val && hashSet.contains((int) val)) {
-                    hashTable.put((int) val, i);
+        @Specialization
+        protected RIntVector match(RAbstractDoubleVector x, RAbstractIntVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            NonRecursiveHashMapDouble hashTable;
+            if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
+                hashTable = new NonRecursiveHashMapDouble(x.getLength());
+                NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength());
+                for (int i = 0; i < result.length; i++) {
+                    hashSet.add(x.getDataAt(i));
                 }
-            }
-        } else {
-            hashTable = new NonRecursiveHashMapInt(table.getLength());
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                double xx = table.getDataAt(i);
-                if (RRuntime.isNA(xx)) {
-                    hashTable.put(RRuntime.INT_NA, i);
-                } else if (xx == (int) xx) {
-                    hashTable.put((int) xx, i);
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    int val = table.getDataAt(i);
+                    if (hashSet.contains(RRuntime.int2double(val))) {
+                        hashTable.put(RRuntime.int2double(val), i);
+                    }
                 }
-            }
-        }
-        for (int i = 0; i < result.length; i++) {
-            int xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
             } else {
-                matchAll = false;
+                hashTable = new NonRecursiveHashMapDouble(table.getLength());
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    hashTable.put(RRuntime.int2double(table.getDataAt(i)), i);
+                }
             }
-        }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
-
-    @Specialization
-    protected RIntVector match(RAbstractDoubleVector x, RAbstractDoubleVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) {
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        NonRecursiveHashMapDouble hashTable;
-        if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
-            hashTable = new NonRecursiveHashMapDouble(x.getLength());
-            NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength());
             for (int i = 0; i < result.length; i++) {
-                hashSet.add(x.getDataAt(i));
-            }
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                double val = table.getDataAt(i);
-                if (hashSet.contains(val)) {
-                    hashTable.put(val, i);
+                double xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
                 }
             }
-        } else {
-            hashTable = new NonRecursiveHashMapDouble(table.getLength());
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                hashTable.put(table.getDataAt(i), i);
-            }
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        for (int i = 0; i < result.length; i++) {
-            double xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
+
+        @Specialization
+        protected RIntVector match(RAbstractIntVector x, RAbstractDoubleVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            NonRecursiveHashMapInt hashTable;
+            if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
+                hashTable = new NonRecursiveHashMapInt(x.getLength());
+                NonRecursiveHashSetInt hashSet = new NonRecursiveHashSetInt(x.getLength());
+                for (int i = 0; i < result.length; i++) {
+                    hashSet.add(x.getDataAt(i));
+                }
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    double val = table.getDataAt(i);
+                    if (RRuntime.isNA(val) && hashSet.contains(RRuntime.INT_NA)) {
+                        hashTable.put(RRuntime.INT_NA, i);
+                    } else if (val == (int) val && hashSet.contains((int) val)) {
+                        hashTable.put((int) val, i);
+                    }
+                }
             } else {
-                matchAll = false;
+                hashTable = new NonRecursiveHashMapInt(table.getLength());
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    double xx = table.getDataAt(i);
+                    if (RRuntime.isNA(xx)) {
+                        hashTable.put(RRuntime.INT_NA, i);
+                    } else if (xx == (int) xx) {
+                        hashTable.put((int) xx, i);
+                    }
+                }
             }
-        }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
-
-    @Specialization
-    protected RIntVector match(RAbstractIntVector x, RAbstractLogicalVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) {
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        int[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA};
-        int[] indexes = new int[values.length];
-        for (int i = 0; i < values.length; i++) {
-            byte value = (byte) values[i];
-            for (int j = 0; j < table.getLength(); j++) {
-                if (table.getDataAt(j) == value) {
-                    indexes[i] = j + 1;
-                    break;
-                }
-            }
-            values[i] = RRuntime.logical2int(value);
-        }
-        for (int i = 0; i < result.length; i++) {
-            int xx = x.getDataAt(i);
-            boolean match = false;
-            for (int j = 0; j < values.length; j++) {
-                if (xx == values[j] && indexes[j] != 0) {
-                    result[i] = indexes[j];
-                    match = true;
-                    break;
+            for (int i = 0; i < result.length; i++) {
+                int xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
                 }
             }
-            matchAll &= match;
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
 
-    @Specialization(guards = "x.getLength() == 1")
-    protected int matchSizeOne(RAbstractStringVector x, RAbstractStringVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
-                    @Cached("create()") NAProfile naProfile,
-                    @Cached("create()") BranchProfile foundProfile,
-                    @Cached("create()") BranchProfile notFoundProfile) {
-        String element = x.getDataAt(0);
-        int length = table.getLength();
-        if (naProfile.isNA(element)) {
-            for (int i = 0; i < length; i++) {
-                if (RRuntime.isNA(table.getDataAt(i))) {
-                    foundProfile.enter();
-                    return i + 1;
+        @Specialization
+        protected RIntVector match(RAbstractDoubleVector x, RAbstractDoubleVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            NonRecursiveHashMapDouble hashTable;
+            if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
+                hashTable = new NonRecursiveHashMapDouble(x.getLength());
+                NonRecursiveHashSetDouble hashSet = new NonRecursiveHashSetDouble(x.getLength());
+                for (int i = 0; i < result.length; i++) {
+                    hashSet.add(x.getDataAt(i));
                 }
-            }
-        } else {
-            for (int i = 0; i < length; i++) {
-                if (element.equals(table.getDataAt(i))) {
-                    foundProfile.enter();
-                    return i + 1;
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    double val = table.getDataAt(i);
+                    if (hashSet.contains(val)) {
+                        hashTable.put(val, i);
+                    }
+                }
+            } else {
+                hashTable = new NonRecursiveHashMapDouble(table.getLength());
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    hashTable.put(table.getDataAt(i), i);
                 }
             }
-        }
-        notFoundProfile.enter();
-        return nomatch;
-    }
-
-    @Specialization
-    protected RIntVector match(RAbstractStringVector x, RAbstractStringVector table, int nomatch, @SuppressWarnings("unused") Object incomparables) {
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        NonRecursiveHashMapCharacter hashTable;
-        if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
-            hashTable = new NonRecursiveHashMapCharacter(x.getLength());
-            NonRecursiveHashSetCharacter hashSet = new NonRecursiveHashSetCharacter(x.getLength());
             for (int i = 0; i < result.length; i++) {
-                hashSet.add(x.getDataAt(i));
+                double xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
+                }
             }
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                String val = table.getDataAt(i);
-                if (hashSet.contains(val)) {
-                    hashTable.put(val, i);
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
+        }
+
+        @Specialization
+        protected RIntVector match(RAbstractIntVector x, RAbstractLogicalVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            int[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA};
+            int[] indexes = new int[values.length];
+            for (int i = 0; i < values.length; i++) {
+                byte value = (byte) values[i];
+                for (int j = 0; j < table.getLength(); j++) {
+                    if (table.getDataAt(j) == value) {
+                        indexes[i] = j + 1;
+                        break;
+                    }
                 }
+                values[i] = RRuntime.logical2int(value);
             }
-        } else {
-            hashTable = new NonRecursiveHashMapCharacter(table.getLength());
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                hashTable.put(table.getDataAt(i), i);
+            for (int i = 0; i < result.length; i++) {
+                int xx = x.getDataAt(i);
+                boolean match = false;
+                for (int j = 0; j < values.length; j++) {
+                    if (xx == values[j] && indexes[j] != 0) {
+                        result[i] = indexes[j];
+                        match = true;
+                        break;
+                    }
+                }
+                matchAll &= match;
+            }
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
+        }
+
+        @Specialization(guards = "x.getLength() == 1")
+        protected int matchSizeOne(RAbstractStringVector x, RAbstractStringVector table, int nomatch,
+                        @Cached("create()") NAProfile naProfile,
+                        @Cached("create()") BranchProfile foundProfile,
+                        @Cached("create()") BranchProfile notFoundProfile) {
+            String element = x.getDataAt(0);
+            int length = table.getLength();
+            if (naProfile.isNA(element)) {
+                for (int i = 0; i < length; i++) {
+                    if (RRuntime.isNA(table.getDataAt(i))) {
+                        foundProfile.enter();
+                        return i + 1;
+                    }
+                }
+            } else {
+                for (int i = 0; i < length; i++) {
+                    if (element.equals(table.getDataAt(i))) {
+                        foundProfile.enter();
+                        return i + 1;
+                    }
+                }
             }
+            notFoundProfile.enter();
+            return nomatch;
         }
-        for (int i = 0; i < result.length; i++) {
-            String xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
+
+        @Specialization
+        protected RIntVector match(RAbstractStringVector x, RAbstractStringVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            NonRecursiveHashMapCharacter hashTable;
+            if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
+                hashTable = new NonRecursiveHashMapCharacter(x.getLength());
+                NonRecursiveHashSetCharacter hashSet = new NonRecursiveHashSetCharacter(x.getLength());
+                for (int i = 0; i < result.length; i++) {
+                    hashSet.add(x.getDataAt(i));
+                }
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    String val = table.getDataAt(i);
+                    if (hashSet.contains(val)) {
+                        hashTable.put(val, i);
+                    }
+                }
             } else {
-                matchAll = false;
+                hashTable = new NonRecursiveHashMapCharacter(table.getLength());
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    hashTable.put(table.getDataAt(i), i);
+                }
+            }
+            for (int i = 0; i < result.length; i++) {
+                String xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
+                }
             }
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
 
-    @Specialization
-    protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, int nomatch, Object incomparables) {
-        naCheck.enable(x);
-        return match(RClosures.createLogicalToStringVector(x), table, nomatch, incomparables);
-    }
+        @Specialization
+        protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, int nomatch) {
+            return match(RClosures.createLogicalToStringVector(x), table, nomatch);
+        }
 
-    @Specialization
-    protected RIntVector match(RAbstractRawVector x, RAbstractIntVector table, int nomatch, Object incomparables) {
-        naCheck.enable(x);
-        return match(RClosures.createRawToStringVector(x), RClosures.createIntToStringVector(table), nomatch, incomparables);
-    }
+        @Specialization
+        protected RIntVector match(RAbstractRawVector x, RAbstractIntVector table, int nomatch) {
+            return match(RClosures.createRawToStringVector(x), RClosures.createIntToStringVector(table), nomatch);
+        }
 
-    @Specialization
-    protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch, Object incomparables) {
-        naCheck.enable(x);
-        return match(RClosures.createIntToStringVector(x), table, nomatch, incomparables);
-    }
+        @Specialization
+        protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch) {
+            return match(RClosures.createIntToStringVector(x), table, nomatch);
+        }
 
-    @Specialization
-    protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch, Object incomparables) {
-        naCheck.enable(x);
-        return match(RClosures.createDoubleToStringVector(x), table, nomatch, incomparables);
-    }
+        @Specialization
+        protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch) {
+            return match(RClosures.createDoubleToStringVector(x), table, nomatch);
+        }
 
-    @Specialization
-    protected RIntVector match(RAbstractLogicalVector x, RAbstractLogicalVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) {
-        int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0);
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        byte[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA};
-        int[] indexes = new int[values.length];
-        for (int i = 0; i < values.length; i++) {
-            byte value = values[i];
-            for (int j = 0; j < table.getLength(); j++) {
-                if (table.getDataAt(j) == value) {
-                    indexes[i] = j + 1;
-                    break;
+        @Specialization
+        protected RIntVector match(RAbstractLogicalVector x, RAbstractLogicalVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            byte[] values = {RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA};
+            int[] indexes = new int[values.length];
+            for (int i = 0; i < values.length; i++) {
+                byte value = values[i];
+                for (int j = 0; j < table.getLength(); j++) {
+                    if (table.getDataAt(j) == value) {
+                        indexes[i] = j + 1;
+                        break;
+                    }
                 }
             }
-        }
-        for (int i = 0; i < result.length; i++) {
-            byte xx = x.getDataAt(i);
-            boolean match = false;
-            for (int j = 0; j < values.length; j++) {
-                if (xx == values[j] && indexes[j] != 0) {
-                    result[i] = indexes[j];
-                    match = true;
-                    break;
+            for (int i = 0; i < result.length; i++) {
+                byte xx = x.getDataAt(i);
+                boolean match = false;
+                for (int j = 0; j < values.length; j++) {
+                    if (xx == values[j] && indexes[j] != 0) {
+                        result[i] = indexes[j];
+                        match = true;
+                        break;
+                    }
                 }
+                matchAll &= match;
             }
-            matchAll &= match;
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
 
-    @Specialization(guards = "!isStringVectorTable(table)")
-    protected RIntVector match(RAbstractStringVector x, RAbstractVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) {
-        int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0);
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        RAbstractStringVector stringTable = castString(table);
-        NonRecursiveHashMapCharacter hashTable = new NonRecursiveHashMapCharacter(table.getLength());
-        for (int i = table.getLength() - 1; i >= 0; i--) {
-            hashTable.put(stringTable.getDataAt(i), i);
-        }
-        for (int i = 0; i < result.length; i++) {
-            String xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
-            } else {
-                matchAll = false;
+        @Specialization(guards = "!isStringVectorTable(table)")
+        protected RIntVector match(RAbstractStringVector x, RAbstractVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            RAbstractStringVector stringTable = castString(table);
+            NonRecursiveHashMapCharacter hashTable = new NonRecursiveHashMapCharacter(table.getLength());
+            for (int i = table.getLength() - 1; i >= 0; i--) {
+                hashTable.put(stringTable.getDataAt(i), i);
             }
-        }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
-
-    @Specialization
-    protected RIntVector match(RAbstractComplexVector x, RAbstractComplexVector table, RAbstractIntVector nomatchVec, @SuppressWarnings("unused") Object incomparables) {
-        int nomatch = nomatchVec.getLength() == 0 ? RRuntime.INT_NA : nomatchVec.getDataAt(0);
-        int[] result = initResult(x.getLength(), nomatch);
-        boolean matchAll = true;
-        NonRecursiveHashMapComplex hashTable;
-        if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
-            hashTable = new NonRecursiveHashMapComplex(x.getLength());
-            NonRecursiveHashSetComplex hashSet = new NonRecursiveHashSetComplex(x.getLength());
             for (int i = 0; i < result.length; i++) {
-                hashSet.add(x.getDataAt(i));
-            }
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                RComplex val = table.getDataAt(i);
-                if (hashSet.contains(val)) {
-                    hashTable.put(val, i);
+                String xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
                 }
             }
-        } else {
-            hashTable = new NonRecursiveHashMapComplex(table.getLength());
-            for (int i = table.getLength() - 1; i >= 0; i--) {
-                hashTable.put(table.getDataAt(i), i);
-            }
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        for (int i = 0; i < result.length; i++) {
-            RComplex xx = x.getDataAt(i);
-            int index = hashTable.get(xx);
-            if (index != -1) {
-                result[i] = index + 1;
+
+        @Specialization
+        protected RIntVector match(RAbstractComplexVector x, RAbstractComplexVector table, int nomatch) {
+            int[] result = initResult(x.getLength(), nomatch);
+            boolean matchAll = true;
+            NonRecursiveHashMapComplex hashTable;
+            if (bigTableProfile.profile(table.getLength() > (x.getLength() * TABLE_SIZE_FACTOR))) {
+                hashTable = new NonRecursiveHashMapComplex(x.getLength());
+                NonRecursiveHashSetComplex hashSet = new NonRecursiveHashSetComplex(x.getLength());
+                for (int i = 0; i < result.length; i++) {
+                    hashSet.add(x.getDataAt(i));
+                }
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    RComplex val = table.getDataAt(i);
+                    if (hashSet.contains(val)) {
+                        hashTable.put(val, i);
+                    }
+                }
             } else {
-                matchAll = false;
+                hashTable = new NonRecursiveHashMapComplex(table.getLength());
+                for (int i = table.getLength() - 1; i >= 0; i--) {
+                    hashTable.put(table.getDataAt(i), i);
+                }
+            }
+            for (int i = 0; i < result.length; i++) {
+                RComplex xx = x.getDataAt(i);
+                int index = hashTable.get(xx);
+                if (index != -1) {
+                    result[i] = index + 1;
+                } else {
+                    matchAll = false;
+                }
             }
+            return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
-        return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
-    }
-
-    @Specialization
-    @SuppressWarnings("unused")
-    protected RIntVector match(RFunction x, Object table, int nomatch, Object incomparables) {
-        throw RError.error(this, MATCH_VECTOR_ARGS);
-    }
-
-    @Specialization
-    @SuppressWarnings("unused")
-    protected RIntVector match(Object x, RFunction table, int nomatch, Object incomparables) {
-        throw RError.error(this, MATCH_VECTOR_ARGS);
-    }
-
-    protected boolean isStringVectorTable(RAbstractVector table) {
-        return table.getElementClass() == String.class;
-    }
 
-    @Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR);
-
-    protected boolean isFactor(Object o) {
-        return factorInheritsCheck.execute(o);
-    }
+        protected boolean isStringVectorTable(RAbstractVector table) {
+            return table.getElementClass() == String.class;
+        }
 
-    private static int[] initResult(int length, int nomatch) {
-        int[] result = new int[length];
-        Arrays.fill(result, nomatch);
-        return result;
-    }
+        private static int[] initResult(int length, int nomatch) {
+            int[] result = new int[length];
+            Arrays.fill(result, nomatch);
+            return result;
+        }
 
-    /**
-     * Set the "complete" status. If {@code nomatch} is not NA (uncommon), then the result vector is
-     * always COMPLETE, otherwise it is INCOMPLETE unless everything matched.
-     */
-    private static boolean setCompleteState(boolean matchAll, int nomatch) {
-        return nomatch != RRuntime.INT_NA || matchAll ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR;
-    }
+        /**
+         * Set the "complete" status. If {@code nomatch} is not NA (uncommon), then the result
+         * vector is always COMPLETE, otherwise it is INCOMPLETE unless everything matched.
+         */
+        private static boolean setCompleteState(boolean matchAll, int nomatch) {
+            return nomatch != RRuntime.INT_NA || matchAll ? RDataFactory.COMPLETE_VECTOR : RDataFactory.INCOMPLETE_VECTOR;
+        }
 
-    // simple implementations of non-recursive hash-maps to enable compilation
-    // TODO: consider replacing with a more efficient library implementation
+        // simple implementations of non-recursive hash-maps to enable compilation
+        // TODO: consider replacing with a more efficient library implementation
 
-    private abstract static class NonRecursiveHashMap {
+        private abstract static class NonRecursiveHashMap {
 
-        protected final int[] values;
-        protected int naValue;
+            protected final int[] values;
+            protected int naValue;
 
-        protected NonRecursiveHashMap(int entryCount) {
-            int capacity = Math.max(entryCount * 3 / 2, 1);
-            values = new int[Integer.highestOneBit(capacity) << 1];
-        }
+            protected NonRecursiveHashMap(int entryCount) {
+                int capacity = Math.max(entryCount * 3 / 2, 1);
+                values = new int[Integer.highestOneBit(capacity) << 1];
+            }
 
-        protected int index(int hash) {
-            // Multiply by -127
-            return ((hash << 1) - (hash << 8)) & (values.length - 1);
+            protected int index(int hash) {
+                // Multiply by -127
+                return ((hash << 1) - (hash << 8)) & (values.length - 1);
+            }
         }
-    }
 
-    private static final class NonRecursiveHashMapCharacter extends NonRecursiveHashMap {
+        private static final class NonRecursiveHashMapCharacter extends NonRecursiveHashMap {
 
-        private final String[] keys;
+            private final String[] keys;
 
-        NonRecursiveHashMapCharacter(int approxCapacity) {
-            super(approxCapacity);
-            keys = new String[values.length];
-        }
+            NonRecursiveHashMapCharacter(int approxCapacity) {
+                super(approxCapacity);
+                keys = new String[values.length];
+            }
 
-        public boolean put(String key, int value) {
-            assert value >= 0;
-            if (RRuntime.isNA(key)) {
-                boolean ret = naValue == 0;
-                naValue = value + 1;
-                return ret;
-            } else {
-                int ind = index(key.hashCode());
-                while (true) {
-                    if (values[ind] == 0) {
-                        keys[ind] = key;
-                        values[ind] = value + 1;
-                        return false;
-                    } else if (key.equals(keys[ind])) {
-                        values[ind] = value + 1;
-                        return true;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
+            public boolean put(String key, int value) {
+                assert value >= 0;
+                if (RRuntime.isNA(key)) {
+                    boolean ret = naValue == 0;
+                    naValue = value + 1;
+                    return ret;
+                } else {
+                    int ind = index(key.hashCode());
+                    while (true) {
+                        if (values[ind] == 0) {
+                            keys[ind] = key;
+                            values[ind] = value + 1;
+                            return false;
+                        } else if (key.equals(keys[ind])) {
+                            values[ind] = value + 1;
+                            return true;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
                         }
                     }
                 }
             }
-        }
 
-        public int get(String key) {
-            if (RRuntime.isNA(key)) {
-                return naValue - 1;
-            } else {
-                int ind = index(key.hashCode());
-                int firstInd = ind;
-                while (true) {
-                    if (key.equals(keys[ind])) {
-                        return values[ind] - 1;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
-                        }
-                        if (ind == firstInd || values[ind] == 0) {
-                            return -1;
+            public int get(String key) {
+                if (RRuntime.isNA(key)) {
+                    return naValue - 1;
+                } else {
+                    int ind = index(key.hashCode());
+                    int firstInd = ind;
+                    while (true) {
+                        if (key.equals(keys[ind])) {
+                            return values[ind] - 1;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
+                            if (ind == firstInd || values[ind] == 0) {
+                                return -1;
+                            }
                         }
                     }
                 }
             }
         }
-    }
-
-    private static final class NonRecursiveHashMapComplex extends NonRecursiveHashMap {
 
-        private final RComplex[] keys;
-
-        NonRecursiveHashMapComplex(int approxCapacity) {
-            super(approxCapacity);
-            keys = new RComplex[values.length];
-        }
-
-        public boolean put(RComplex key, int value) {
-            assert value >= 0;
-            if (RRuntime.isNA(key)) {
-                boolean ret = naValue == 0;
-                naValue = value + 1;
-                return ret;
-            } else {
-                int ind = index(key.hashCode());
-                while (true) {
-                    if (values[ind] == 0) {
-                        keys[ind] = key;
-                        values[ind] = value + 1;
-                        return false;
-                    } else if (key.equals(keys[ind])) {
-                        values[ind] = value + 1;
-                        return true;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
+        private static final class NonRecursiveHashMapComplex extends NonRecursiveHashMap {
+
+            private final RComplex[] keys;
+
+            NonRecursiveHashMapComplex(int approxCapacity) {
+                super(approxCapacity);
+                keys = new RComplex[values.length];
+            }
+
+            public boolean put(RComplex key, int value) {
+                assert value >= 0;
+                if (RRuntime.isNA(key)) {
+                    boolean ret = naValue == 0;
+                    naValue = value + 1;
+                    return ret;
+                } else {
+                    int ind = index(key.hashCode());
+                    while (true) {
+                        if (values[ind] == 0) {
+                            keys[ind] = key;
+                            values[ind] = value + 1;
+                            return false;
+                        } else if (key.equals(keys[ind])) {
+                            values[ind] = value + 1;
+                            return true;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
                         }
                     }
                 }
             }
-        }
 
-        public int get(RComplex key) {
-            if (RRuntime.isNA(key)) {
-                return naValue - 1;
-            } else {
-                int ind = index(key.hashCode());
-                int firstInd = ind;
-                while (true) {
-                    if (key.equals(keys[ind])) {
-                        return values[ind] - 1;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
-                        }
-                        if (ind == firstInd || values[ind] == 0) {
-                            return -1;
+            public int get(RComplex key) {
+                if (RRuntime.isNA(key)) {
+                    return naValue - 1;
+                } else {
+                    int ind = index(key.hashCode());
+                    int firstInd = ind;
+                    while (true) {
+                        if (key.equals(keys[ind])) {
+                            return values[ind] - 1;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
+                            if (ind == firstInd || values[ind] == 0) {
+                                return -1;
+                            }
                         }
                     }
                 }
             }
         }
-    }
-
-    private static final class NonRecursiveHashMapDouble extends NonRecursiveHashMap {
 
-        private final double[] keys;
-        private int nanValue;
-
-        NonRecursiveHashMapDouble(int approxCapacity) {
-            super(approxCapacity);
-            keys = new double[values.length];
-            Arrays.fill(keys, RRuntime.DOUBLE_NA);
-        }
-
-        public boolean put(double key, int value) {
-            assert value >= 0;
-            if (RRuntime.isNA(key)) {
-                boolean ret = naValue == 0;
-                naValue = value + 1;
-                return ret;
-            } else if (Double.isNaN(key)) {
-                boolean ret = nanValue == 0;
-                nanValue = value + 1;
-                return ret;
-            } else {
-                int ind = index(Double.hashCode(key));
-                while (true) {
-                    if (values[ind] == 0) {
-                        keys[ind] = key;
-                        values[ind] = value + 1;
-                        return false;
-                    } else if (key == keys[ind]) {
-                        values[ind] = value + 1;
-                        return true;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
+        private static final class NonRecursiveHashMapDouble extends NonRecursiveHashMap {
+
+            private final double[] keys;
+            private int nanValue;
+
+            NonRecursiveHashMapDouble(int approxCapacity) {
+                super(approxCapacity);
+                keys = new double[values.length];
+                Arrays.fill(keys, RRuntime.DOUBLE_NA);
+            }
+
+            public boolean put(double key, int value) {
+                assert value >= 0;
+                if (RRuntime.isNA(key)) {
+                    boolean ret = naValue == 0;
+                    naValue = value + 1;
+                    return ret;
+                } else if (Double.isNaN(key)) {
+                    boolean ret = nanValue == 0;
+                    nanValue = value + 1;
+                    return ret;
+                } else {
+                    int ind = index(Double.hashCode(key));
+                    while (true) {
+                        if (values[ind] == 0) {
+                            keys[ind] = key;
+                            values[ind] = value + 1;
+                            return false;
+                        } else if (key == keys[ind]) {
+                            values[ind] = value + 1;
+                            return true;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
                         }
                     }
                 }
             }
-        }
 
-        public int get(double key) {
-            if (RRuntime.isNA(key)) {
-                return naValue - 1;
-            } else if (Double.isNaN(key)) {
-                return nanValue - 1;
-            } else {
-                int ind = index(Double.hashCode(key));
-                int firstInd = ind;
-                while (true) {
-                    if (key == keys[ind]) {
-                        return values[ind] - 1;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
-                        }
-                        if (ind == firstInd || values[ind] == 0) {
-                            return -1;
+            public int get(double key) {
+                if (RRuntime.isNA(key)) {
+                    return naValue - 1;
+                } else if (Double.isNaN(key)) {
+                    return nanValue - 1;
+                } else {
+                    int ind = index(Double.hashCode(key));
+                    int firstInd = ind;
+                    while (true) {
+                        if (key == keys[ind]) {
+                            return values[ind] - 1;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
+                            if (ind == firstInd || values[ind] == 0) {
+                                return -1;
+                            }
                         }
                     }
                 }
             }
         }
-    }
-
-    private static final class NonRecursiveHashMapInt extends NonRecursiveHashMap {
-
-        private final int[] keys;
-
-        NonRecursiveHashMapInt(int approxCapacity) {
-            super(approxCapacity);
-            keys = new int[values.length];
-            Arrays.fill(keys, RRuntime.INT_NA);
-        }
 
-        public boolean put(int key, int value) {
-            assert value >= 0;
-            if (RRuntime.isNA(key)) {
-                boolean ret = naValue == 0;
-                naValue = value + 1;
-                return ret;
-            } else {
-                int ind = index(Integer.hashCode(key));
-                while (true) {
-                    if (values[ind] == 0) {
-                        keys[ind] = key;
-                        values[ind] = value + 1;
-                        return false;
-                    } else if (key == keys[ind]) {
-                        values[ind] = value + 1;
-                        return true;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
+        private static final class NonRecursiveHashMapInt extends NonRecursiveHashMap {
+
+            private final int[] keys;
+
+            NonRecursiveHashMapInt(int approxCapacity) {
+                super(approxCapacity);
+                keys = new int[values.length];
+                Arrays.fill(keys, RRuntime.INT_NA);
+            }
+
+            public boolean put(int key, int value) {
+                assert value >= 0;
+                if (RRuntime.isNA(key)) {
+                    boolean ret = naValue == 0;
+                    naValue = value + 1;
+                    return ret;
+                } else {
+                    int ind = index(Integer.hashCode(key));
+                    while (true) {
+                        if (values[ind] == 0) {
+                            keys[ind] = key;
+                            values[ind] = value + 1;
+                            return false;
+                        } else if (key == keys[ind]) {
+                            values[ind] = value + 1;
+                            return true;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
                         }
                     }
                 }
             }
-        }
 
-        public int get(int key) {
-            if (RRuntime.isNA(key)) {
-                return naValue - 1;
-            } else {
-                int ind = index(Integer.hashCode(key));
-                int firstInd = ind;
-                while (true) {
-                    if (key == keys[ind]) {
-                        return values[ind] - 1;
-                    } else {
-                        ind++;
-                        if (ind == values.length) {
-                            ind = 0;
-                        }
-                        if (ind == firstInd || values[ind] == 0) {
-                            return -1;
+            public int get(int key) {
+                if (RRuntime.isNA(key)) {
+                    return naValue - 1;
+                } else {
+                    int ind = index(Integer.hashCode(key));
+                    int firstInd = ind;
+                    while (true) {
+                        if (key == keys[ind]) {
+                            return values[ind] - 1;
+                        } else {
+                            ind++;
+                            if (ind == values.length) {
+                                ind = 0;
+                            }
+                            if (ind == firstInd || values[ind] == 0) {
+                                return -1;
+                            }
                         }
                     }
                 }
             }
         }
-    }
 
-    private static class NonRecursiveHashSetInt {
-        private final NonRecursiveHashMapInt map;
+        private static class NonRecursiveHashSetInt {
+            private final NonRecursiveHashMapInt map;
 
-        NonRecursiveHashSetInt(int approxCapacity) {
-            map = new NonRecursiveHashMapInt(approxCapacity);
-        }
+            NonRecursiveHashSetInt(int approxCapacity) {
+                map = new NonRecursiveHashMapInt(approxCapacity);
+            }
 
-        public boolean add(int value) {
-            return map.put(value, 1);
-        }
+            public boolean add(int value) {
+                return map.put(value, 1);
+            }
 
-        public boolean contains(int value) {
-            return map.get(value) == 1 ? true : false;
+            public boolean contains(int value) {
+                return map.get(value) == 1 ? true : false;
+            }
         }
-    }
 
-    private static class NonRecursiveHashSetDouble {
-        private final NonRecursiveHashMapDouble map;
+        private static class NonRecursiveHashSetDouble {
+            private final NonRecursiveHashMapDouble map;
 
-        NonRecursiveHashSetDouble(int approxCapacity) {
-            map = new NonRecursiveHashMapDouble(approxCapacity);
-        }
+            NonRecursiveHashSetDouble(int approxCapacity) {
+                map = new NonRecursiveHashMapDouble(approxCapacity);
+            }
 
-        public boolean add(double value) {
-            return map.put(value, 1);
-        }
+            public boolean add(double value) {
+                return map.put(value, 1);
+            }
 
-        public boolean contains(double value) {
-            return map.get(value) == 1 ? true : false;
+            public boolean contains(double value) {
+                return map.get(value) == 1 ? true : false;
+            }
         }
-    }
 
-    private static class NonRecursiveHashSetCharacter {
-        private final NonRecursiveHashMapCharacter map;
+        private static class NonRecursiveHashSetCharacter {
+            private final NonRecursiveHashMapCharacter map;
 
-        NonRecursiveHashSetCharacter(int approxCapacity) {
-            map = new NonRecursiveHashMapCharacter(approxCapacity);
-        }
+            NonRecursiveHashSetCharacter(int approxCapacity) {
+                map = new NonRecursiveHashMapCharacter(approxCapacity);
+            }
 
-        public boolean add(String value) {
-            return map.put(value, 1);
-        }
+            public boolean add(String value) {
+                return map.put(value, 1);
+            }
 
-        public boolean contains(String value) {
-            return map.get(value) == 1 ? true : false;
+            public boolean contains(String value) {
+                return map.get(value) == 1 ? true : false;
+            }
         }
-    }
 
-    private static class NonRecursiveHashSetComplex {
-        private final NonRecursiveHashMapComplex map;
+        private static class NonRecursiveHashSetComplex {
+            private final NonRecursiveHashMapComplex map;
 
-        NonRecursiveHashSetComplex(int approxCapacity) {
-            map = new NonRecursiveHashMapComplex(approxCapacity);
-        }
+            NonRecursiveHashSetComplex(int approxCapacity) {
+                map = new NonRecursiveHashMapComplex(approxCapacity);
+            }
 
-        public boolean add(RComplex value) {
-            return map.put(value, 1);
-        }
+            public boolean add(RComplex value) {
+                return map.put(value, 1);
+            }
 
-        public boolean contains(RComplex value) {
-            return map.get(value) == 1 ? true : false;
+            public boolean contains(RComplex value) {
+                return map.get(value) == 1 ? true : false;
+            }
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java
index 16524b3fee..9ef1c9bcc6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -49,6 +50,10 @@ public final class InheritsCheckNode extends Node {
         assert RType.fromMode(checkedClazz) == null : "Class '" + checkedClazz + "' cannot be checked by InheritsCheckNode";
     }
 
+    public static InheritsCheckNode createFactor() {
+        return new InheritsCheckNode(RRuntime.CLASS_FACTOR);
+    }
+
     public boolean execute(Object value) {
         if (value instanceof RMissing) {
             return false;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index 730c1b5a77..d19ba63e09 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -49,6 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -237,10 +238,9 @@ public abstract class RBaseNode extends Node {
         return value instanceof RAbstractStringVector;
     }
 
-    /*
-     * No isXyz functions for abstract vector classes (RAbstractIntVector, etc.), because they do
-     * not honor implicit casts and can thus lead to unexpected behavior.
-     */
+    protected static boolean isRAbstractListVector(Object value) {
+        return value instanceof RAbstractListVector;
+    }
 
     protected static boolean isRList(Object value) {
         return value instanceof RList;
-- 
GitLab


From 5e83924dfea972bf90bcb0fcc58637471b7dccb8 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 31 Jan 2017 11:54:05 +0100
Subject: [PATCH 027/402] type-specialize AsVector, MatMult and Crossprod

---
 .../r/nodes/builtin/base/AsVector.java        |  88 +++++-----
 .../r/nodes/builtin/base/Crossprod.java       |  16 +-
 .../truffle/r/nodes/builtin/base/MatMult.java | 160 ++++++++----------
 3 files changed, 125 insertions(+), 139 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index facf4b7d25..b0ce114681 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -35,11 +35,11 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen.CastPairListNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen.DropAttributesNodeGen;
 import com.oracle.truffle.r.nodes.function.CallMatcherNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
@@ -61,13 +61,12 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -96,7 +95,7 @@ public abstract class AsVector extends RBuiltinNode {
     @Specialization
     protected Object asVector(VirtualFrame frame, Object x, String mode) {
         // TODO given dispatch = INTERNAL_GENERIC, this should not be necessary
-        // However, removing it causes unit test failures
+        // However, INTERNAL_GENERIC is not handled for INTERNAL builtins
         RStringVector clazz = classHierarchy.execute(x);
         if (hasClassProfile.profile(clazz != null)) {
             // Note: this dispatch takes care of factor, because there is as.vector.factor
@@ -121,43 +120,7 @@ public abstract class AsVector extends RBuiltinNode {
 
         public abstract Object execute(Object x, String mode);
 
-        private final ConditionProfile hasAttributes = ConditionProfile.createBinaryProfile();
         private final ConditionProfile indirectMatchProfile = ConditionProfile.createBinaryProfile();
-        private final BranchProfile vectorProfile = BranchProfile.create();
-        private final ConditionProfile listProfile = ConditionProfile.createBinaryProfile();
-        private final BranchProfile languageProfile = BranchProfile.create();
-        private final BranchProfile symbolProfile = BranchProfile.create();
-        private final BranchProfile expressionProfile = BranchProfile.create();
-
-        private Object dropAttributesIfNeeded(Object o) {
-            Object res = o;
-            if (res instanceof RAttributable && hasAttributes.profile(((RAttributable) res).getAttributes() != null)) {
-                // the assertion should hold because of how cast works and it's only used for
-                // vectors (as per as.vector docs)
-                if (res instanceof RExpression) {
-                    expressionProfile.enter();
-                    return res;
-                } else if (res instanceof RAbstractVector) {
-                    vectorProfile.enter();
-                    if (listProfile.profile(res instanceof RAbstractListVector)) {
-                        // attributes are not dropped for list results
-                        return res;
-                    } else {
-                        return ((RAbstractVector) res).copyDropAttributes();
-                    }
-                } else if (res instanceof RLanguage) {
-                    languageProfile.enter();
-                    return RDataFactory.createLanguage(((RLanguage) res).getRep());
-                } else if (res instanceof RSymbol) {
-                    symbolProfile.enter();
-                    return RDataFactory.createSymbol(((RSymbol) res).getName());
-                } else {
-                    CompilerDirectives.transferToInterpreter();
-                    throw RInternalError.unimplemented("drop attributes for " + res.getClass().getSimpleName());
-                }
-            }
-            return res;
-        }
 
         protected static CastNode createCast(RType type) {
             if (type != null) {
@@ -201,8 +164,49 @@ public abstract class AsVector extends RBuiltinNode {
         protected Object asVector(Object x, String mode,
                         @Cached("mode") String cachedMode,
                         @Cached("fromMode(cachedMode)") RType type,
-                        @Cached("createCast(type)") CastNode cast) {
-            return dropAttributesIfNeeded(cast == null ? x : cast.execute(x));
+                        @Cached("createCast(type)") CastNode cast,
+                        @Cached("create()") DropAttributesNode drop) {
+            return drop.execute(cast == null ? x : cast.execute(x));
+        }
+
+        public abstract static class DropAttributesNode extends Node {
+
+            public abstract Object execute(Object o);
+
+            public static DropAttributesNode create() {
+                return DropAttributesNodeGen.create();
+            }
+
+            protected static boolean hasAttributes(Class<? extends RAbstractAtomicVector> clazz, RAbstractAtomicVector o) {
+                return clazz.cast(o).getAttributes() != null;
+            }
+
+            @Specialization(guards = {"o.getClass() == oClass", "hasAttributes(oClass, o)"})
+            protected RAbstractVector dropCached(RAbstractAtomicVector o,
+                            @Cached("o.getClass()") Class<? extends RAbstractAtomicVector> oClass) {
+                return oClass.cast(o).copyDropAttributes();
+            }
+
+            @Specialization(replaces = "dropCached", guards = "o.getAttributes() != null")
+            protected RAbstractVector drop(RAbstractAtomicVector o) {
+                return o.copyDropAttributes();
+            }
+
+            @Specialization(guards = "o.getAttributes() != null")
+            protected static RLanguage drop(RLanguage o) {
+                return RDataFactory.createLanguage(o.getRep());
+            }
+
+            @Specialization(guards = "o.getAttributes() != null")
+            protected static RSymbol drop(RSymbol o) {
+                return RDataFactory.createSymbol(o.getName());
+            }
+
+            @Fallback
+            protected Object drop(Object o) {
+                // includes RAbstractListVector, RExpression, RPairList
+                return o;
+            }
         }
 
         protected abstract static class CastPairListNode extends CastNode {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
index 842176d655..8917f9ffe0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
@@ -31,8 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -68,17 +66,14 @@ public abstract class Crossprod extends RBuiltinNode {
     @Specialization(guards = {"x.isMatrix()", "y.isMatrix()"})
     protected RDoubleVector crossprod(RAbstractDoubleVector x, RAbstractDoubleVector y,
                     @Cached("create()") GetDimAttributeNode getXDimsNode,
-                    @Cached("create()") GetDimAttributeNode getYDimsNode,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
+                    @Cached("create()") GetDimAttributeNode getYDimsNode) {
         int[] xDims = getXDimsNode.getDimensions(x);
         int[] yDims = getYDimsNode.getDimensions(y);
         int xRows = xDims[0];
         int xCols = xDims[1];
         int yRows = yDims[0];
         int yCols = yDims[1];
-        return matMult.doubleMatrixMultiply(x, y, xCols, xRows, yRows, yCols, xRows, 1, 1, yRows, false, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+        return matMult.doubleMatrixMultiply(x, y, xCols, xRows, yRows, yCols, xRows, 1, 1, yRows, false);
     }
 
     private static RDoubleVector mirror(RDoubleVector result, GetDimAttributeNode getResultDimsNode) {
@@ -110,14 +105,11 @@ public abstract class Crossprod extends RBuiltinNode {
     @Specialization(guards = "x.isMatrix()")
     protected RDoubleVector crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y,
                     @Cached("create()") GetDimAttributeNode getDimsNode,
-                    @Cached("create()") GetDimAttributeNode getResultDimsNode,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
+                    @Cached("create()") GetDimAttributeNode getResultDimsNode) {
         int[] xDims = getDimsNode.getDimensions(x);
         int xRows = xDims[0];
         int xCols = xDims[1];
-        return mirror(matMult.doubleMatrixMultiply(x, x, xCols, xRows, xRows, xCols, xRows, 1, 1, xRows, true, setDimNamesNode, getADimNamesNode, getBDimNamesNode), getResultDimsNode);
+        return mirror(matMult.doubleMatrixMultiply(x, x, xCols, xRows, xRows, xCols, xRows, 1, 1, xRows, true), getResultDimsNode);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index f75a6b739a..6dc66e4dbf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -42,6 +42,7 @@ import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -50,6 +51,7 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.closures.RClosures;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -80,6 +82,10 @@ public abstract class MatMult extends RBuiltinNode {
     @Child protected GetDimAttributeNode getBDimsNode = GetDimAttributeNode.create();
     @Child protected SetDimAttributeNode setDimsNode = SetDimAttributeNode.create();
 
+    @Child private SetDimNamesAttributeNode setDimNamesNode = SetDimNamesAttributeNode.create();
+    @Child private GetDimNamesAttributeNode getADimNamesNode = GetDimNamesAttributeNode.create();
+    @Child private GetDimNamesAttributeNode getBDimNamesNode = GetDimNamesAttributeNode.create();
+
     protected abstract Object executeObject(Object a, Object b);
 
     private final NACheck na;
@@ -144,9 +150,8 @@ public abstract class MatMult extends RBuiltinNode {
     private final BranchProfile incompleteProfile = BranchProfile.create();
     @CompilationFinal private boolean seenLargeMatrix;
 
-    private RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols, SetDimNamesAttributeNode setDimNamesNode,
-                    GetDimNamesAttributeNode getADimNamesNode, GetDimNamesAttributeNode getBDimNamesNode) {
-        return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, 1, aRows, 1, bRows, false, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+    private RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols) {
+        return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, 1, aRows, 1, bRows, false);
     }
 
     /**
@@ -167,7 +172,7 @@ public abstract class MatMult extends RBuiltinNode {
      * @return the result vector
      */
     public RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols, int aRowStride, int aColStride, int bRowStride,
-                    int bColStride, boolean mirrored, SetDimNamesAttributeNode setDimNamesNode, GetDimNamesAttributeNode getADimNamesNode, GetDimNamesAttributeNode getBDimNamesNode) {
+                    int bColStride, boolean mirrored) {
         if (aCols != bRows) {
             errorProfile.enter();
             throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
@@ -273,19 +278,30 @@ public abstract class MatMult extends RBuiltinNode {
         }
     }
 
-    @Specialization
+    @Specialization(guards = {"a.getClass() == aClass", "b.getClass() == bClass"})
+    protected RDoubleVector multiplyDouble(RAbstractDoubleVector a, RAbstractDoubleVector b,
+                    @Cached("a.getClass()") Class<? extends RAbstractDoubleVector> aClass,
+                    @Cached("b.getClass()") Class<? extends RAbstractDoubleVector> bClass,
+                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
+                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix,
+                    @Cached("createBinaryProfile()") ConditionProfile lengthEquals) {
+        return doubleMultiply(aClass.cast(a), bClass.cast(b), aIsMatrix, bIsMatrix, lengthEquals);
+    }
+
+    @Specialization(replaces = "multiplyDouble")
     protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractDoubleVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile lengthEquals,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
+                    @Cached("createBinaryProfile()") ConditionProfile lengthEquals) {
+        return doubleMultiply(a, b, aIsMatrix, bIsMatrix, lengthEquals);
+    }
+
+    private RDoubleVector doubleMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix, ConditionProfile lengthEquals) {
         if (aIsMatrix.profile(a.isMatrix())) {
             if (bIsMatrix.profile(b.isMatrix())) {
                 int[] aDimensions = getADimsNode.getDimensions(a);
                 int[] bDimensions = getBDimsNode.getDimensions(b);
-                return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1], setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1]);
             } else {
                 int[] aDim = getADimsNode.getDimensions(a);
                 int aRows = aDim[0];
@@ -299,7 +315,7 @@ public abstract class MatMult extends RBuiltinNode {
                     bRows = 1;
                     bCols = b.getLength();
                 }
-                return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols);
             }
         } else {
             if (bIsMatrix.profile(b.isMatrix())) {
@@ -315,7 +331,7 @@ public abstract class MatMult extends RBuiltinNode {
                     aRows = a.getLength();
                     aCols = 1;
                 }
-                return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols);
             } else {
                 if (a.getLength() != b.getLength()) {
                     errorProfile.enter();
@@ -339,10 +355,23 @@ public abstract class MatMult extends RBuiltinNode {
 
     // complex-complex
 
-    @Specialization
+    @Specialization(guards = {"a.getClass() == aClass", "b.getClass() == bClass"})
+    protected RComplexVector multiplyComplex(RAbstractComplexVector a, RAbstractComplexVector b,
+                    @Cached("a.getClass()") Class<? extends RAbstractComplexVector> aClass,
+                    @Cached("b.getClass()") Class<? extends RAbstractComplexVector> bClass,
+                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
+                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
+        return complexMultiply(aClass.cast(a), bClass.cast(b), aIsMatrix, bIsMatrix);
+    }
+
+    @Specialization(replaces = "multiplyComplex")
     protected RComplexVector multiply(RAbstractComplexVector a, RAbstractComplexVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
+        return complexMultiply(a, b, aIsMatrix, bIsMatrix);
+    }
+
+    private RComplexVector complexMultiply(RAbstractComplexVector a, RAbstractComplexVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix) {
         if (aIsMatrix.profile(a.isMatrix())) {
             if (bIsMatrix.profile(b.isMatrix())) {
                 int[] aDim = getADimsNode.getDimensions(a);
@@ -460,10 +489,23 @@ public abstract class MatMult extends RBuiltinNode {
 
     // int-int
 
-    @Specialization
+    @Specialization(guards = {"a.getClass() == aClass", "b.getClass() == bClass"})
+    protected RIntVector multiplyInt(RAbstractIntVector a, RAbstractIntVector b,
+                    @Cached("a.getClass()") Class<? extends RAbstractIntVector> aClass,
+                    @Cached("b.getClass()") Class<? extends RAbstractIntVector> bClass,
+                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
+                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
+        return intMultiply(aClass.cast(a), bClass.cast(b), aIsMatrix, bIsMatrix);
+    }
+
+    @Specialization(replaces = "multiplyInt")
     protected RIntVector multiply(RAbstractIntVector a, RAbstractIntVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
+        return intMultiply(a, b, aIsMatrix, bIsMatrix);
+    }
+
+    private RIntVector intMultiply(RAbstractIntVector a, RAbstractIntVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix) {
         if (aIsMatrix.profile(a.isMatrix())) {
             if (bIsMatrix.profile(b.isMatrix())) {
                 int[] aDim = getADimsNode.getDimensions(a);
@@ -578,7 +620,7 @@ public abstract class MatMult extends RBuiltinNode {
     protected RIntVector multiply(RAbstractLogicalVector aOriginal, RAbstractLogicalVector bOriginal,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(RClosures.createLogicalToIntVector(aOriginal), RClosures.createLogicalToIntVector(bOriginal), aIsMatrix, bIsMatrix);
+        return intMultiply(RClosures.createLogicalToIntVector(aOriginal), RClosures.createLogicalToIntVector(bOriginal), aIsMatrix, bIsMatrix);
     }
 
     // to int
@@ -587,104 +629,52 @@ public abstract class MatMult extends RBuiltinNode {
     protected RIntVector multiply(RAbstractLogicalVector a, RAbstractIntVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(RClosures.createLogicalToIntVector(a), b, aIsMatrix, bIsMatrix);
+        return intMultiply(RClosures.createLogicalToIntVector(a), b, aIsMatrix, bIsMatrix);
     }
 
     @Specialization
     protected RIntVector multiply(RAbstractIntVector a, RAbstractLogicalVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(a, RClosures.createLogicalToIntVector(b), aIsMatrix, bIsMatrix);
-    }
-
-    // to complex
-
-    @Specialization
-    protected RComplexVector multiply(RAbstractIntVector a, RAbstractComplexVector b,
-                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(RClosures.createIntToComplexVector(a), b, aIsMatrix, bIsMatrix);
-    }
-
-    @Specialization
-    protected RComplexVector multiply(RAbstractComplexVector a, RAbstractIntVector b,
-                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(a, RClosures.createIntToComplexVector(b), aIsMatrix, bIsMatrix);
-    }
-
-    @Specialization
-    protected RComplexVector multiply(RAbstractLogicalVector a, RAbstractComplexVector b,
-                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(RClosures.createLogicalToComplexVector(a), b, aIsMatrix, bIsMatrix);
-    }
-
-    @Specialization
-    protected RComplexVector multiply(RAbstractComplexVector a, RAbstractLogicalVector b,
-                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(a, RClosures.createLogicalToComplexVector(b), aIsMatrix, bIsMatrix);
-    }
-
-    @Specialization
-    protected RComplexVector multiply(RAbstractDoubleVector a, RAbstractComplexVector b,
-                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(RClosures.createDoubleToComplexVector(a), b, aIsMatrix, bIsMatrix);
-    }
-
-    @Specialization
-    protected RComplexVector multiply(RAbstractComplexVector a, RAbstractDoubleVector b,
-                    @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return multiply(a, RClosures.createDoubleToComplexVector(b), aIsMatrix, bIsMatrix);
+        return intMultiply(a, RClosures.createLogicalToIntVector(b), aIsMatrix, bIsMatrix);
     }
 
     // to double
 
-    @Specialization
-    protected RDoubleVector multiply(RAbstractIntVector a, RAbstractDoubleVector b,
+    @Specialization(guards = {"!isRAbstractComplexVector(a)"})
+    protected RDoubleVector multiply(RAbstractAtomicVector a, RAbstractDoubleVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile lengthEquals,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
-        return multiply(RClosures.createIntToDoubleVector(a), b, aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+        return doubleMultiply((RAbstractDoubleVector) a.castSafe(RType.Double, isNAProfile), b, aIsMatrix, bIsMatrix, lengthEquals);
     }
 
-    @Specialization
-    protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractIntVector b,
+    @Specialization(guards = {"!isRAbstractComplexVector(b)"})
+    protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractAtomicVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile lengthEquals,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
-        return multiply(a, RClosures.createIntToDoubleVector(b), aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+        return doubleMultiply(a, (RAbstractDoubleVector) b.castSafe(RType.Double, isNAProfile), aIsMatrix, bIsMatrix, lengthEquals);
     }
 
+    // to complex
+
     @Specialization
-    protected RDoubleVector multiply(RAbstractLogicalVector a, RAbstractDoubleVector b,
+    protected RComplexVector multiply(RAbstractAtomicVector a, RAbstractComplexVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile lengthEquals,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
-        return multiply(RClosures.createLogicalToDoubleVector(a), b, aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+        return complexMultiply((RAbstractComplexVector) a.castSafe(RType.Complex, isNAProfile), b, aIsMatrix, bIsMatrix);
     }
 
     @Specialization
-    protected RDoubleVector multiply(RAbstractDoubleVector a, RAbstractLogicalVector b,
+    protected RComplexVector multiply(RAbstractComplexVector a, RAbstractAtomicVector b,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix,
-                    @Cached("createBinaryProfile()") ConditionProfile lengthEquals,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getBDimNamesNode) {
-        return multiply(a, RClosures.createLogicalToDoubleVector(b), aIsMatrix, bIsMatrix, lengthEquals, setDimNamesNode, getADimNamesNode, getBDimNamesNode);
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+        return complexMultiply(a, (RAbstractComplexVector) b.castSafe(RType.Complex, isNAProfile), aIsMatrix, bIsMatrix);
     }
 
     // errors
-- 
GitLab


From b2be94c1abc05a589a7aff8befc4b0a6883eb13e Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 1 Feb 2017 11:53:54 +0100
Subject: [PATCH 028/402] =?UTF-8?q?refactor=20GetNonSharedNode=20and=20use?=
 =?UTF-8?q?=20in=20more=20places,=20remove=20unnecessary=20materializeToSh?=
 =?UTF-8?q?areable=20function=20and=20use=20materialize=20in=20Update?=
 =?UTF-8?q?=E2=80=A6=20builtins?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../r/nodes/builtin/base/UpdateAttr.java      | 19 ++---
 .../nodes/builtin/base/UpdateAttributes.java  | 12 ++-
 .../r/nodes/builtin/base/UpdateDimNames.java  | 16 ++--
 .../r/nodes/builtin/base/UpdateNames.java     |  9 ++-
 .../builtin/base/infix/SpecialsUtils.java     | 44 +++++++++++
 .../builtin/base/infix/UpdateSubscript.java   | 10 ++-
 .../builtin/base/infix/UpdateSubset.java      |  5 +-
 .../base/printer/ValuePrinterNode.java        |  6 --
 .../r/nodes/control/ReplacementNode.java      |  4 +-
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  2 +-
 .../r/nodes/function/ArgumentStatePush.java   |  9 +--
 .../nodes/function/WrapArgumentBaseNode.java  |  3 +-
 .../function/opt/ReuseNonSharedNode.java      | 33 +++-----
 .../r/nodes/function/opt/ShareObjectNode.java | 19 ++---
 .../opt/UpdateShareableChildValueNode.java    | 37 ++-------
 .../r/nodes/unary/GetNonSharedNode.java       | 79 +++++++++++--------
 .../truffle/r/runtime/data/RLanguage.java     |  2 +-
 .../truffle/r/runtime/data/RPairList.java     |  7 +-
 .../truffle/r/runtime/data/RScalarVector.java |  5 --
 .../truffle/r/runtime/data/RSequence.java     |  5 --
 .../data/RSharingAttributeStorage.java        | 11 +++
 .../truffle/r/runtime/data/RVector.java       |  5 --
 .../data/closures/RToVectorClosure.java       |  6 --
 .../data/model/RAbstractContainer.java        |  3 +-
 .../r/runtime/data/model/RAbstractVector.java |  1 +
 25 files changed, 178 insertions(+), 174 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index f9c56347d3..aa74c71def 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastListNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
+import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
@@ -136,9 +137,10 @@ public abstract class UpdateAttr extends RBuiltinNode {
 
     @Specialization
     protected RAbstractContainer updateAttr(RAbstractContainer container, String name, RNull value,
-                    @Cached("create()") RemoveAttributeNode removeAttrNode) {
+                    @Cached("create()") RemoveAttributeNode removeAttrNode,
+                    @Cached("create()") GetNonSharedNode nonShared) {
         String internedName = intern.execute(name);
-        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
+        RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
         // the name is interned, so identity comparison is sufficient
         if (internedName == RRuntime.DIM_ATTR_KEY) {
             if (setDimNode == null) {
@@ -180,10 +182,11 @@ public abstract class UpdateAttr extends RBuiltinNode {
         }
     }
 
-    @Specialization(guards = "!nullValue(value)")
-    protected RAbstractContainer updateAttr(RAbstractContainer container, String name, Object value) {
+    @Specialization(guards = "!isRNull(value)")
+    protected RAbstractContainer updateAttr(RAbstractContainer container, String name, Object value,
+                    @Cached("create()") GetNonSharedNode nonShared) {
         String internedName = intern.execute(name);
-        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
+        RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
         // the name is interned, so identity comparison is sufficient
         if (internedName == RRuntime.DIM_ATTR_KEY) {
             RAbstractIntVector dimsVector = castInteger(castVector(value));
@@ -225,12 +228,6 @@ public abstract class UpdateAttr extends RBuiltinNode {
         return result;
     }
 
-    // the guard is necessary as RNull and Object cannot be distinguished in case of multiple
-    // specializations, such as in: x<-1; attr(x, "dim")<-1; attr(x, "dim")<-NULL
-    protected boolean nullValue(Object value) {
-        return value == RNull.instance;
-    }
-
     /**
      * All other, non-performance centric, {@link RAttributable} types.
      */
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 541be369d7..8ec7de0523 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -30,6 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -44,6 +45,7 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
+import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -115,20 +117,22 @@ public abstract class UpdateAttributes extends RBuiltinNode {
     }
 
     @Specialization
-    protected RAbstractContainer updateAttributes(RAbstractContainer abstractContainer, @SuppressWarnings("unused") RNull list) {
-        RAbstractContainer resultVector = (RAbstractContainer) abstractContainer.getNonShared();
+    protected RAbstractContainer updateAttributes(RAbstractContainer abstractContainer, @SuppressWarnings("unused") RNull list,
+                    @Cached("create()") GetNonSharedNode nonShared) {
+        RAbstractContainer resultVector = ((RAbstractContainer) nonShared.execute(abstractContainer)).materialize();
         resultVector.resetAllAttributes(true);
         return resultVector;
     }
 
     @Specialization
-    protected RAbstractContainer updateAttributes(RAbstractContainer container, RList list) {
+    protected RAbstractContainer updateAttributes(RAbstractContainer container, RList list,
+                    @Cached("create()") GetNonSharedNode nonShared) {
         Object listNamesObject = getNamesNode.getNames(list);
         if (listNamesObject == null || listNamesObject == RNull.instance) {
             throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
         }
         RStringVector listNames = (RStringVector) listNamesObject;
-        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
+        RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
         if (numAttributesProfile.profile(list.getLength() == 0)) {
             result.resetAllAttributes(true);
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index 439c1b4a24..6b63fbccde 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
+import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -94,22 +95,25 @@ public abstract class UpdateDimNames extends RBuiltinNode {
 
     @Specialization
     protected RAbstractContainer updateDimnamesNull(RAbstractContainer container, @SuppressWarnings("unused") RNull list,
-                    @Cached("createDimNames()") RemoveFixedAttributeNode remove) {
-        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
+                    @Cached("createDimNames()") RemoveFixedAttributeNode remove,
+                    @Cached("create()") GetNonSharedNode nonShared) {
+        RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
         remove.execute(result);
         return result;
     }
 
     @Specialization(guards = "list.getLength() == 0")
     protected RAbstractContainer updateDimnamesEmpty(RAbstractContainer container, @SuppressWarnings("unused") RList list,
-                    @Cached("createDimNames()") RemoveFixedAttributeNode remove) {
-        return updateDimnamesNull(container, RNull.instance, remove);
+                    @Cached("createDimNames()") RemoveFixedAttributeNode remove,
+                    @Cached("create()") GetNonSharedNode nonShared) {
+        return updateDimnamesNull(container, RNull.instance, remove, nonShared);
     }
 
     @Specialization(guards = "list.getLength() > 0")
     protected RAbstractContainer updateDimnames(RAbstractContainer container, RList list,
-                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode) {
-        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
+                    @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
+                    @Cached("create()") GetNonSharedNode nonShared) {
+        RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
         setDimNamesNode.setDimNames(result, convertToListOfStrings(list));
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
index afefd3a53d..0a619c54c7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
@@ -28,10 +28,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
+import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -62,10 +64,11 @@ public abstract class UpdateNames extends RBuiltinNode {
 
     @Specialization
     @TruffleBoundary
-    protected RAbstractContainer updateNames(RAbstractContainer container, Object names) {
+    protected RAbstractContainer updateNames(RAbstractContainer container, Object names,
+                    @Cached("create()") GetNonSharedNode nonShared) {
         Object newNames = castString(names);
+        RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
         if (newNames == RNull.instance) {
-            RAbstractContainer result = (RAbstractContainer) container.getNonShared();
             result.setNames(null);
             return result;
         }
@@ -76,7 +79,6 @@ public abstract class UpdateNames extends RBuiltinNode {
         } else {
             stringVector = (RStringVector) ((RAbstractVector) newNames).materialize().copyDropAttributes();
         }
-        RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         if (stringVector.getLength() < result.getLength()) {
             stringVector = (RStringVector) stringVector.copyResized(result.getLength(), true);
         } else if (stringVector.getLength() > result.getLength()) {
@@ -86,7 +88,6 @@ public abstract class UpdateNames extends RBuiltinNode {
         }
         if (stringVector.isTemporary()) {
             stringVector.incRefCount();
-
         }
         result.setNames(stringVector);
         return result;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 301672faa1..6822ea1686 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -33,8 +33,11 @@ import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertValueNodeGen;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -204,6 +207,43 @@ class SpecialsUtils {
         }
     }
 
+    @NodeInfo(cost = NodeCost.NONE)
+    @NodeChild(value = "delegate", type = RNode.class)
+    public abstract static class ConvertValue extends RNode {
+
+        protected abstract RNode getDelegate();
+
+        @Specialization
+        protected static int convert(int value) {
+            return value;
+        }
+
+        @Specialization
+        protected static double convert(double value) {
+            return value;
+        }
+
+        @Specialization(guards = "value.getLength() == 1")
+        protected static int convertIntVector(RIntVector value) {
+            return value.getDataAt(0);
+        }
+
+        @Specialization(guards = "value.getLength() == 1")
+        protected static double convertDoubleVector(RDoubleVector value) {
+            return value.getDataAt(0);
+        }
+
+        @Specialization(replaces = {"convertIntVector", "convertDoubleVector"})
+        protected Object convert(Object value) {
+            return value;
+        }
+
+        @Override
+        protected RSyntaxNode getRSyntaxNode() {
+            return getDelegate().asRSyntaxNode();
+        }
+    }
+
     public static ProfiledValue profile(RNode value) {
         return new ProfiledValue(value);
     }
@@ -211,4 +251,8 @@ class SpecialsUtils {
     public static ConvertIndex convertIndex(RNode value) {
         return ConvertIndexNodeGen.create(value);
     }
+
+    public static ConvertValue convertValue(RNode value) {
+        return ConvertValueNodeGen.create(value);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index a1fc8e1653..80d27c0f38 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
+import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue;
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
@@ -39,6 +40,7 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertValue;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon;
@@ -59,7 +61,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @NodeChild(value = "vector", type = ProfiledValue.class)
 @NodeChild(value = "index", type = ConvertIndex.class)
-@NodeChild(value = "value", type = RNode.class)
+@NodeChild(value = "value", type = ConvertValue.class)
 abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
 
     protected UpdateSubscriptSpecial(boolean inReplacement) {
@@ -110,7 +112,7 @@ abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
 @NodeChild(value = "vector", type = ProfiledValue.class)
 @NodeChild(value = "index1", type = ConvertIndex.class)
 @NodeChild(value = "index2", type = ConvertIndex.class)
-@NodeChild(value = "value", type = RNode.class)
+@NodeChild(value = "value", type = ConvertValue.class)
 abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
 
     protected UpdateSubscriptSpecial2(boolean inReplacement) {
@@ -174,9 +176,9 @@ public abstract class UpdateSubscript extends RBuiltinNode {
             ProfiledValue vector = profile(args[0]);
             ConvertIndex index = convertIndex(args[1]);
             if (args.length == 3) {
-                return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, args[2]);
+                return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, convertValue(args[2]));
             } else {
-                return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), args[3]);
+                return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), convertValue(args[3]));
             }
         }
         return null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 75f6199966..98021bea82 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
+import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue;
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
@@ -60,9 +61,9 @@ public abstract class UpdateSubset extends RBuiltinNode {
             ProfiledValue vector = profile(args[0]);
             ConvertIndex index = convertIndex(args[1]);
             if (args.length == 3) {
-                return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, args[2]);
+                return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, convertValue(args[2]));
             } else {
-                return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), args[3]);
+                return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), convertValue(args[3]));
             }
         }
         return null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index 458380020c..0282196c31 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -63,7 +63,6 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
-import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RVector;
@@ -525,11 +524,6 @@ public final class ValuePrinterNode extends RBaseNode {
             throw RInternalError.shouldNotReachHere();
         }
 
-        @Override
-        public RShareable materializeToShareable() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
         @Override
         public RStringVector getNames() {
             return null;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index 54b6e8d4f7..a6bb499839 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.RCallSpecialNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
-import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen;
+import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory.FullCallNeededException;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -136,7 +136,7 @@ abstract class ReplacementNode extends OperatorNode {
             if ("slot".equals(symbol) || "@".equals(symbol)) {
                 // this is pretty gross, but at this point seems like the only way to get setClass
                 // to work properly
-                argNodes[0] = GetNonSharedNodeGen.create(argNodes[0].asRNode());
+                argNodes[0] = new GetNonSharedNode.GetNonSharedSyntaxNode(argNodes[0].asRNode());
             }
             newSyntaxLHS = builder.lookup(lookupLHS.getLazySourceSection(), symbol + "<-", true);
         } else {
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 87aa0607ff..a338ac2d2e 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
@@ -580,7 +580,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         if (x instanceof RShareable) {
             return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy();
         } else if (x instanceof RSequence) {
-            return ((RSequence) x).materializeToShareable();
+            return ((RSequence) x).materialize();
         } else {
             return ((RExternalPtr) x).copy();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index 5ab82f5b4e..f070ed30d4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RShareable;
@@ -104,17 +103,13 @@ public abstract class ArgumentStatePush extends Node {
         }
     }
 
-    @Specialization
-    public void transitionState(RShareable shareable) {
-        throw RInternalError.shouldNotReachHere("unexpected RShareable that is not RSharingAttributeStorage: " + shareable.getClass());
-    }
-
     @Specialization(guards = "!isShareable(o)")
     public void transitionStateNonShareable(@SuppressWarnings("unused") Object o) {
         // do nothing
     }
 
     protected boolean isShareable(Object o) {
-        return o instanceof RShareable;
+        RSharingAttributeStorage.verify(o);
+        return o instanceof RSharingAttributeStorage;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java
index ebc6853f82..a86dd95a42 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.function;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -65,10 +64,10 @@ public abstract class WrapArgumentBaseNode extends RNode {
     }
 
     public Object execute(VirtualFrame frame, Object result) {
+        RSharingAttributeStorage.verify(result);
         if (isShareable.profile(result instanceof RSharingAttributeStorage)) {
             return handleShareable(frame, (RSharingAttributeStorage) result);
         } else {
-            assert !(result instanceof RShareable) : "unexpected RShareable that is not a subclass of RSharingAttributeStorage";
             return result;
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
index b5d6226606..d1166630d4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
@@ -23,10 +23,9 @@
 package com.oracle.truffle.r.nodes.function.opt;
 
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 
@@ -44,34 +43,26 @@ public abstract class ReuseNonSharedNode extends Node {
 
     public abstract Object execute(Object value);
 
-    @Specialization
-    protected RShareable getStorage(RSharingAttributeStorage value,
-                    @Cached("createBinaryProfile()") ConditionProfile isSharedProfile,
-                    @Cached("createClassProfile()") ValueProfile copyProfile) {
-        if (isSharedProfile.profile(value.isShared())) {
-            RShareable res = copyProfile.profile(value).copy();
-            assert res.isTemporary();
-            return res;
-        }
+    @Specialization(guards = "!value.isShared()")
+    protected RShareable reuseNonShared(RSharingAttributeStorage value) {
         return value;
     }
 
-    @Specialization(replaces = "getStorage")
-    protected static RShareable getRShareable(RShareable value,
-                    @Cached("createBinaryProfile()") ConditionProfile isSharedProfile) {
-        if (isSharedProfile.profile(value.isShared())) {
-            RShareable res = value.copy();
-            return res;
-        }
-        return value;
+    @Specialization(guards = {"value.isShared()", "value.getClass() == valueClass"})
+    protected RSharingAttributeStorage reuseShared(RSharingAttributeStorage value,
+                    @Cached("value.getClass()") Class<? extends RSharingAttributeStorage> valueClass) {
+        RSharingAttributeStorage res = valueClass.cast(value).copy();
+        assert res.isTemporary();
+        return res;
     }
 
     protected static boolean isRShareable(Object value) {
-        return value instanceof RShareable;
+        return value instanceof RSharingAttributeStorage;
     }
 
-    @Specialization(guards = "!isRShareable(value)")
+    @Fallback
     protected static Object getNonShareable(Object value) {
+        RSharingAttributeStorage.verify(value);
         return value;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java
index b28a5f0d5e..2d99d45117 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ShareObjectNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.function.opt;
 import static com.oracle.truffle.api.nodes.NodeCost.NONE;
 
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeInfo;
@@ -58,18 +59,14 @@ public abstract class ShareObjectNode extends Node {
         return obj;
     }
 
-    @Specialization(guards = "!isRShareable(obj)")
+    @Fallback
     protected Object doNonShareable(Object obj) {
+        RSharingAttributeStorage.verify(obj);
         return obj;
     }
 
-    protected static boolean isRShareable(Object value) {
-        verify(value);
-        return value instanceof RSharingAttributeStorage;
-    }
-
     public static <T> T share(T value) {
-        verify(value);
+        RSharingAttributeStorage.verify(value);
         if (value instanceof RSharingAttributeStorage) {
             RSharingAttributeStorage shareable = (RSharingAttributeStorage) value;
             if (!shareable.isSharedPermanent()) {
@@ -80,7 +77,7 @@ public abstract class ShareObjectNode extends Node {
     }
 
     public static <T> T sharePermanent(T value) {
-        verify(value);
+        RSharingAttributeStorage.verify(value);
         if (value instanceof RSharingAttributeStorage) {
             ((RSharingAttributeStorage) value).makeSharedPermanent();
         }
@@ -88,7 +85,7 @@ public abstract class ShareObjectNode extends Node {
     }
 
     public static void unshare(Object value) {
-        verify(value);
+        RSharingAttributeStorage.verify(value);
         if (value instanceof RSharingAttributeStorage) {
             RSharingAttributeStorage shareable = (RSharingAttributeStorage) value;
             if (!shareable.isSharedPermanent()) {
@@ -96,8 +93,4 @@ public abstract class ShareObjectNode extends Node {
             }
         }
     }
-
-    private static void verify(Object value) {
-        assert (value instanceof RShareable) == (value instanceof RSharingAttributeStorage) : "unexpected RShareable that is not RSharingAttributeStorage: " + value;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java
index 7787564d54..fb71c60e5e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java
@@ -23,18 +23,14 @@
 package com.oracle.truffle.r.nodes.function.opt;
 
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class UpdateShareableChildValueNode extends RBaseNode {
 
-    protected UpdateShareableChildValueNode() {
-    }
-
     public abstract void execute(Object owner, Object attrValue);
 
     public final <T> T updateState(Object owner, T item) {
@@ -47,30 +43,13 @@ public abstract class UpdateShareableChildValueNode extends RBaseNode {
     }
 
     @Specialization
-    protected void doShareableValues(RShareable owner, RShareable value,
-                    @Cached("createClassProfile()") ValueProfile valueProfile,
-                    @Cached("createBinaryProfile()") ConditionProfile sharingAttrsStorageOwner,
-                    @Cached("createClassProfile()") ValueProfile ownerProfile,
+    protected void doShareableValues(RSharingAttributeStorage owner, RSharingAttributeStorage value,
                     @Cached("createBinaryProfile()") ConditionProfile sharedValue,
                     @Cached("createBinaryProfile()") ConditionProfile temporaryOwner) {
-        RShareable profiledValue = valueProfile.profile(value);
-        if (sharedValue.profile(profiledValue.isShared())) {
+        if (sharedValue.profile(value.isShared())) {
             // it is already shared, not need to do anything
             return;
         }
-
-        if (sharingAttrsStorageOwner.profile(owner instanceof RSharingAttributeStorage)) {
-            // monomorphic invocations of the owner
-            RSharingAttributeStorage shOwner = (RSharingAttributeStorage) owner;
-            incRef(shOwner, profiledValue, temporaryOwner);
-        } else {
-            // invoking a type-profiled owner
-            RShareable ownerProfiled = ownerProfile.profile(owner);
-            incRef(ownerProfiled, profiledValue, temporaryOwner);
-        }
-    }
-
-    private static void incRef(RShareable owner, RShareable value, ConditionProfile temporaryOwner) {
         if (temporaryOwner.profile(owner.isTemporary())) {
             // This can happen, for example, when we immediately extract out of a temporary
             // list that was returned by a built-in, like: strsplit(...)[[1L]]. We do not need
@@ -79,7 +58,6 @@ public abstract class UpdateShareableChildValueNode extends RBaseNode {
         }
 
         // the owner is at least non-shared
-
         if (value.isTemporary()) {
             // make it at least non-shared (the owner must be also at least non-shared)
             value.incRefCount();
@@ -90,12 +68,9 @@ public abstract class UpdateShareableChildValueNode extends RBaseNode {
         }
     }
 
-    @Specialization(guards = "isFallback(owner, value)")
-    @SuppressWarnings("unused")
+    @Fallback
     protected void doFallback(Object owner, Object value) {
-    }
-
-    protected static boolean isFallback(Object owner, Object value) {
-        return !(value instanceof RShareable) || !(owner instanceof RShareable);
+        RSharingAttributeStorage.verify(owner);
+        RSharingAttributeStorage.verify(value);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
index 9505d3897b..deef4720e1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,55 +22,70 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
-import com.oracle.truffle.api.dsl.NodeChild;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-@NodeChild(value = "n", type = RNode.class)
-public abstract class GetNonSharedNode extends RNode implements RSyntaxNode {
-    // TODO This should not be an RSyntaxNode
+public abstract class GetNonSharedNode extends Node {
 
-    private final ValueProfile shareableTypeProfile = ValueProfile.createClassProfile();
+    public static final class GetNonSharedSyntaxNode extends RNode implements RSyntaxNode {
 
-    protected abstract RNode getN();
+        @Child private RNode delegate;
+        @Child private GetNonSharedNode nonShared = GetNonSharedNodeGen.create();
 
-    @Override
-    protected RSyntaxNode getRSyntaxNode() {
-        return getN().asRSyntaxNode();
-    }
+        public GetNonSharedSyntaxNode(RNode delegate) {
+            this.delegate = delegate;
+        }
 
-    @Specialization
-    protected RTypedValue getNonShared(RShareable shareable) {
-        return shareableTypeProfile.profile(shareable).getNonShared();
-    }
+        @Override
+        public Object execute(VirtualFrame frame) {
+            return nonShared.execute(delegate.execute(frame));
+        }
 
-    protected static boolean isRShareable(Object o) {
-        return o instanceof RShareable;
-    }
+        @Override
+        protected RSyntaxNode getRSyntaxNode() {
+            return delegate.asRSyntaxNode();
+        }
 
-    @Specialization(guards = "!isRShareable(o)")
-    protected Object getNonShared(Object o) {
-        return o;
+        @Override
+        public void setSourceSection(SourceSection sourceSection) {
+            throw RInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        public SourceSection getLazySourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
     }
 
-    @Override
-    public void setSourceSection(SourceSection sourceSection) {
-        throw RInternalError.shouldNotReachHere();
+    public abstract Object execute(Object value);
+
+    public static GetNonSharedNode create() {
+        return GetNonSharedNodeGen.create();
     }
 
-    @Override
-    public SourceSection getLazySourceSection() {
-        return RSyntaxNode.INTERNAL;
+    @Specialization(guards = "shareable.getClass() == shareableClass")
+    protected RTypedValue getNonShared(RSharingAttributeStorage shareable,
+                    @Cached("shareable.getClass()") Class<? extends RSharingAttributeStorage> shareableClass) {
+        return shareableClass.cast(shareable).getNonShared();
     }
 
-    @Override
-    public SourceSection getSourceSection() {
-        return RSyntaxNode.INTERNAL;
+    @Fallback
+    protected Object getNonShared(Object o) {
+        RSharingAttributeStorage.verify(o);
+        return o;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index 9166d94a99..a4eb4d6a40 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -165,7 +165,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
     }
 
     @Override
-    public RShareable materializeToShareable() {
+    public RLanguage materialize() {
         // TODO is copy necessary?
         return copy();
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index 145bda60e2..c999db5a78 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -256,7 +256,7 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
     }
 
     @Override
-    public RShareable copy() {
+    public RSharingAttributeStorage copy() {
         RPairList result = new RPairList();
         Object original = this;
         while (!isNull(original)) {
@@ -280,9 +280,8 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
     }
 
     @Override
-    public RShareable materializeToShareable() {
-        RInternalError.shouldNotReachHere();
-        return null;
+    public RPairList materialize() {
+        return this;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
index 94892c2553..f7e89244ce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
@@ -87,11 +87,6 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector {
         return materialize().getNonShared();
     }
 
-    @Override
-    public RShareable materializeToShareable() {
-        return materialize().materializeToShareable();
-    }
-
     @Override
     public RStringVector getNames() {
         return null;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
index 2167dd74eb..c8a79d94e8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
@@ -182,11 +182,6 @@ public abstract class RSequence implements RAbstractVector {
         return materialize().getNonShared();
     }
 
-    @Override
-    public final RShareable materializeToShareable() {
-        return this.materialize();
-    }
-
     @Override
     public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
         // TODO support for higher dimensions
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
index a685b13e48..33b3162721 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
@@ -76,4 +76,15 @@ public abstract class RSharingAttributeStorage extends RAttributeStorage impleme
         }
         return this;
     }
+
+    @Override
+    public abstract RSharingAttributeStorage copy();
+
+    /**
+     * Verifies that the given object either is and instance of RShareable and
+     * RSharingAttributeStorage or an instance of neither of them.
+     */
+    public static void verify(Object value) {
+        assert (value instanceof RShareable) == (value instanceof RSharingAttributeStorage) : "unexpected RShareable that is not RSharingAttributeStorage: " + value;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index e5e7d62026..4a95c318bd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -779,11 +779,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return implicitClassHeader;
     }
 
-    @Override
-    public final RShareable materializeToShareable() {
-        return materialize();
-    }
-
     public static void verifyDimensions(int vectorLength, int[] newDimensions, RBaseNode invokingNode) {
         int length = 1;
         for (int i = 0; i < newDimensions.length; i++) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
index 1f17428efc..9b78aed76e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.data.closures;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.runtime.data.MemoryCopyTracer;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RVector;
@@ -180,11 +179,6 @@ abstract class RToVectorClosure implements RAbstractVector {
         return vector.getNonShared();
     }
 
-    @Override
-    public final RShareable materializeToShareable() {
-        return vector.materialize();
-    }
-
     @Override
     public int getTypedValueInfo() {
         return vector.getTypedValueInfo();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
index a3001eaf5d..f03140b082 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
@@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 
@@ -48,7 +47,7 @@ public interface RAbstractContainer extends RAttributable, RTypedValue {
 
     RTypedValue getNonShared();
 
-    RShareable materializeToShareable();
+    RAbstractContainer materialize();
 
     Object getDataAtAsObject(int index);
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java
index bf9862638a..2d16b9fbea 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java
@@ -53,6 +53,7 @@ public interface RAbstractVector extends RAbstractContainer {
 
     RVector<?> createEmptySameType(int newLength, boolean newIsComplete);
 
+    @Override
     RVector<?> materialize();
 
     boolean isMatrix();
-- 
GitLab


From e10897bbd4f002d9ceb7a2425fce6b0c2198a4f6 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 2 Feb 2017 15:25:30 +0100
Subject: [PATCH 029/402] ColonNode, MatMult, Quit

---
 .../r/nodes/builtin/base/BasePackage.java     |  2 +-
 .../truffle/r/nodes/builtin/base/Colon.java   | 31 +++++++-
 .../truffle/r/nodes/builtin/base/MatMult.java | 77 +++++++++----------
 .../truffle/r/nodes/builtin/base/Quit.java    |  8 +-
 .../truffle/r/nodes/control/BlockNode.java    | 10 +--
 5 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index de8e99dfb3..c09506f646 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -226,7 +226,7 @@ public class BasePackage extends RBuiltinPackage {
         add(Ceiling.class, CeilingNodeGen::create);
         add(CharMatch.class, CharMatchNodeGen::create);
         add(Col.class, ColNodeGen::create);
-        add(Colon.class, ColonNodeGen::create);
+        add(Colon.class, ColonNodeGen::create, Colon::special);
         add(ColMeans.class, ColMeansNodeGen::create);
         add(ColSums.class, ColSumsNodeGen::create);
         add(Combine.class, CombineNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index 9fa28b86e3..601a63c728 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -28,6 +28,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
@@ -35,13 +36,15 @@ import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.Colon.ColonCastNode;
+import com.oracle.truffle.r.nodes.builtin.base.Colon.ColonInternal;
 import com.oracle.truffle.r.nodes.builtin.base.ColonNodeGen.ColonCastNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.ColonNodeGen.ColonInternalNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleSequence;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
@@ -49,11 +52,34 @@ import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-@RBuiltin(name = ":", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE)
+@NodeChild(value = "left", type = RNode.class)
+@NodeChild(value = "right", type = RNode.class)
+abstract class ColonSpecial extends RNode {
+
+    @Child private ColonCastNode leftCast = ColonCastNodeGen.create();
+    @Child private ColonCastNode rightCast = ColonCastNodeGen.create();
+    @Child private ColonInternal internal = ColonInternalNodeGen.create();
+
+    @Specialization
+    protected Object colon(Object left, Object right) {
+        return internal.execute(leftCast.execute(left), rightCast.execute(right));
+    }
+}
+
+// javac fails without fully qualified name
+@com.oracle.truffle.r.runtime.builtins.RBuiltin(name = ":", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE)
 public abstract class Colon extends RBuiltinNode {
 
+    public static RNode special(ArgumentsSignature signature, RNode[] arguments, boolean inReplacement) {
+        if (signature.getNonNullCount() == 0 && arguments.length == 2 && !inReplacement) {
+            return ColonSpecialNodeGen.create(arguments[0], arguments[1]);
+        }
+        return null;
+    }
+
     @Child private ColonCastNode leftCast = ColonCastNodeGen.create();
     @Child private ColonCastNode rightCast = ColonCastNodeGen.create();
     @Child private ColonInternal internal = ColonInternalNodeGen.create();
@@ -155,6 +181,7 @@ public abstract class Colon extends RBuiltinNode {
         }
     }
 
+    @NodeInfo(cost = NodeCost.NONE)
     abstract static class ColonCastNode extends CastNode {
 
         private final ConditionProfile lengthGreaterOne = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index 6dc66e4dbf..f5fa51dfa9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode.isMatrix;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -297,15 +298,14 @@ public abstract class MatMult extends RBuiltinNode {
     }
 
     private RDoubleVector doubleMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix, ConditionProfile lengthEquals) {
-        if (aIsMatrix.profile(a.isMatrix())) {
-            if (bIsMatrix.profile(b.isMatrix())) {
-                int[] aDimensions = getADimsNode.getDimensions(a);
-                int[] bDimensions = getBDimsNode.getDimensions(b);
+        int[] aDimensions = getADimsNode.getDimensions(a);
+        int[] bDimensions = getBDimsNode.getDimensions(b);
+        if (aIsMatrix.profile(isMatrix(aDimensions))) {
+            if (bIsMatrix.profile(isMatrix(bDimensions))) {
                 return doubleMatrixMultiply(a, b, aDimensions[0], aDimensions[1], bDimensions[0], bDimensions[1]);
             } else {
-                int[] aDim = getADimsNode.getDimensions(a);
-                int aRows = aDim[0];
-                int aCols = aDim[1];
+                int aRows = aDimensions[0];
+                int aCols = aDimensions[1];
                 int bRows;
                 int bCols;
                 if (lengthEquals.profile(aCols == b.getLength())) {
@@ -318,10 +318,9 @@ public abstract class MatMult extends RBuiltinNode {
                 return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols);
             }
         } else {
-            if (bIsMatrix.profile(b.isMatrix())) {
-                int[] bDim = getBDimsNode.getDimensions(b);
-                int bRows = bDim[0];
-                int bCols = bDim[1];
+            if (bIsMatrix.profile(isMatrix(bDimensions))) {
+                int bRows = bDimensions[0];
+                int bCols = bDimensions[1];
                 int aRows;
                 int aCols;
                 if (lengthEquals.profile(bRows == a.getLength())) {
@@ -372,18 +371,18 @@ public abstract class MatMult extends RBuiltinNode {
     }
 
     private RComplexVector complexMultiply(RAbstractComplexVector a, RAbstractComplexVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix) {
-        if (aIsMatrix.profile(a.isMatrix())) {
-            if (bIsMatrix.profile(b.isMatrix())) {
-                int[] aDim = getADimsNode.getDimensions(a);
-                int[] bDim = getBDimsNode.getDimensions(b);
-                final int aCols = aDim[1];
-                final int bRows = bDim[0];
+        int[] aDimensions = getADimsNode.getDimensions(a);
+        int[] bDimensions = getBDimsNode.getDimensions(b);
+        if (aIsMatrix.profile(isMatrix(aDimensions))) {
+            if (bIsMatrix.profile(isMatrix(bDimensions))) {
+                final int aCols = aDimensions[1];
+                final int bRows = bDimensions[0];
                 if (aCols != bRows) {
                     errorProfile.enter();
                     throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
                 }
-                final int aRows = aDim[0];
-                final int bCols = bDim[1];
+                final int aRows = aDimensions[0];
+                final int bCols = bDimensions[1];
                 double[] result = new double[(aRows * bCols) << 1];
                 na.enable(a);
                 na.enable(b);
@@ -401,9 +400,8 @@ public abstract class MatMult extends RBuiltinNode {
                 }
                 return RDataFactory.createComplexVector(result, na.neverSeenNA(), new int[]{aRows, bCols});
             } else {
-                int[] aDim = getADimsNode.getDimensions(a);
-                final int aCols = aDim[1];
-                final int aRows = aDim[0];
+                final int aCols = aDimensions[1];
+                final int aRows = aDimensions[0];
                 if (aCols != 1 && aCols != b.getLength()) {
                     errorProfile.enter();
                     throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
@@ -436,10 +434,9 @@ public abstract class MatMult extends RBuiltinNode {
                 }
             }
         } else {
-            if (bIsMatrix.profile(b.isMatrix())) {
-                int[] bDim = getBDimsNode.getDimensions(b);
-                final int bRows = bDim[0];
-                final int bCols = bDim[1];
+            if (bIsMatrix.profile(isMatrix(bDimensions))) {
+                final int bRows = bDimensions[0];
+                final int bCols = bDimensions[1];
                 if (bRows != 1 && bRows != a.getLength()) {
                     errorProfile.enter();
                     throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
@@ -506,18 +503,18 @@ public abstract class MatMult extends RBuiltinNode {
     }
 
     private RIntVector intMultiply(RAbstractIntVector a, RAbstractIntVector b, ConditionProfile aIsMatrix, ConditionProfile bIsMatrix) {
-        if (aIsMatrix.profile(a.isMatrix())) {
-            if (bIsMatrix.profile(b.isMatrix())) {
-                int[] aDim = getADimsNode.getDimensions(a);
-                int[] bDim = getBDimsNode.getDimensions(b);
-                final int aCols = aDim[1];
-                final int bRows = bDim[0];
+        int[] aDimensions = getADimsNode.getDimensions(a);
+        int[] bDimensions = getBDimsNode.getDimensions(b);
+        if (aIsMatrix.profile(isMatrix(aDimensions))) {
+            if (bIsMatrix.profile(isMatrix(bDimensions))) {
+                int aCols = aDimensions[1];
+                int bRows = bDimensions[0];
                 if (aCols != bRows) {
                     errorProfile.enter();
                     throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
                 }
-                final int aRows = aDim[0];
-                final int bCols = bDim[1];
+                int aRows = aDimensions[0];
+                int bCols = bDimensions[1];
                 int[] result = new int[aRows * bCols];
                 na.enable(a);
                 na.enable(b);
@@ -533,9 +530,8 @@ public abstract class MatMult extends RBuiltinNode {
                 }
                 return RDataFactory.createIntVector(result, na.neverSeenNA(), new int[]{aRows, bCols});
             } else {
-                int[] aDim = getADimsNode.getDimensions(a);
-                final int aCols = aDim[1];
-                final int aRows = aDim[0];
+                final int aCols = aDimensions[1];
+                final int aRows = aDimensions[0];
                 if (aCols != 1 && aCols != b.getLength()) {
                     errorProfile.enter();
                     throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
@@ -566,10 +562,9 @@ public abstract class MatMult extends RBuiltinNode {
                 }
             }
         } else {
-            int[] bDim = getBDimsNode.getDimensions(b);
-            if (bIsMatrix.profile(b.isMatrix())) {
-                final int bCols = bDim[1];
-                final int bRows = bDim[0];
+            if (bIsMatrix.profile(isMatrix(bDimensions))) {
+                final int bCols = bDimensions[1];
+                final int bRows = bDimensions[0];
                 if (bRows != 1 && bRows != a.getLength()) {
                     errorProfile.enter();
                     throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index 4a3d93122c..05eafee4ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -54,19 +54,19 @@ public abstract class Quit extends RBuiltinNode {
     protected Object doQuit(String save, final int status, final byte runLastIn) {
         byte runLast = runLastIn;
         if (RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser()) {
-            RError.warning(this, RError.Message.BROWSER_QUIT);
+            RError.warning(RError.SHOW_CALLER, RError.Message.BROWSER_QUIT);
             return RNull.instance;
         }
         RStartParams.SA_TYPE ask = checkSaveValue(save);
         if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().getConsoleHandler().isInteractive()) {
-            RError.warning(this, RError.Message.QUIT_ASK_INTERACTIVE);
+            RError.warning(RError.SHOW_CALLER, RError.Message.QUIT_ASK_INTERACTIVE);
         }
         if (status == RRuntime.INT_NA) {
-            RError.warning(this, RError.Message.QUIT_INVALID_STATUS);
+            RError.warning(RError.SHOW_CALLER, RError.Message.QUIT_INVALID_STATUS);
             runLast = RRuntime.LOGICAL_FALSE;
         }
         if (runLast == RRuntime.LOGICAL_NA) {
-            RError.warning(this, RError.Message.QUIT_INVALID_RUNLAST);
+            RError.warning(RError.SHOW_CALLER, RError.Message.QUIT_INVALID_RUNLAST);
             runLast = RRuntime.LOGICAL_FALSE;
         }
         RCleanUp.cleanUp(ask, status, RRuntime.fromLogical(runLast));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java
index e660d18e3c..3feff83c7a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/BlockNode.java
@@ -76,12 +76,12 @@ public final class BlockNode extends OperatorNode {
     @Override
     @ExplodeLoop
     public Object visibleExecute(VirtualFrame frame) {
-        if (visibility == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            visibility = insert(SetVisibilityNode.create());
-        }
-        visibility.execute(frame, true);
         if (sequence.length == 0) {
+            if (visibility == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                visibility = insert(SetVisibilityNode.create());
+            }
+            visibility.execute(frame, true);
             return RNull.instance;
         }
         for (int i = 0; i < sequence.length - 1; i++) {
-- 
GitLab


From ddafe7f0bc09af14dfea1455f984fe0d165ceaaf Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 7 Feb 2017 11:03:57 +0100
Subject: [PATCH 030/402] special calls are only wrappers (NodeCost.NONE)

---
 .../oracle/truffle/r/nodes/function/RCallSpecialNode.java   | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
index ce167a93b4..86b549616a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.nodes.function;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.SourceSection;
@@ -96,6 +98,7 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup {
     }
 }
 
+@NodeInfo(cost = NodeCost.NONE)
 public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode, RSyntaxCall {
 
     private static final boolean useSpecials = FastROptions.UseSpecials.getBooleanValue();
@@ -216,6 +219,9 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
                         return null;
                     }
                     if (i < evaluatedArgs) {
+                        // not quite correct:
+                        // || (dispatch == RDispatch.DEFAULT
+                        // && builtinDescriptor.evaluatesArg(i))
                         localArguments[i] = arg.asRNode();
                     } else {
                         localArguments[i] = new PeekLocalVariableNode(lookup);
-- 
GitLab


From 00854a3f4f0a882aa17525f2a4147d6b095fe347 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 15 Feb 2017 18:47:17 +0100
Subject: [PATCH 031/402] fix copyrights

---
 .../truffle/r/nodes/access/vector/ExtractListElement.java       | 2 +-
 .../oracle/truffle/r/nodes/attributes/AttributeAccessNode.java  | 2 +-
 .../com/oracle/truffle/r/nodes/function/ArgumentStatePush.java  | 2 +-
 .../oracle/truffle/r/runtime/data/RSharingAttributeStorage.java | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java
index d7c432c78e..4890e66223 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractListElement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java
index f19f5253ee..a69ac1f254 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccessNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index f070ed30d4..fe657055d9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
index 33b3162721..7a0797ee36 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSharingAttributeStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From 7fbc914762dd4229a3c726392013a3770547d792 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 20 Feb 2017 13:59:33 +0100
Subject: [PATCH 032/402] fix various warnings, unused imports, etc.

---
 .../truffle/r/engine/TruffleRLanguage.java      | 17 +++++++++--------
 .../r/library/methods/SubstituteDirect.java     |  2 +-
 .../r/library/stats/SplineFunctions.java        |  6 +++---
 .../nodes/builtin/base/ConnectionFunctions.java |  2 +-
 .../truffle/r/nodes/builtin/base/Match.java     |  6 ------
 .../r/nodes/builtin/base/Substitute.java        |  2 +-
 .../r/nodes/binary/BinaryArithmeticSpecial.java |  2 +-
 .../r/nodes/binary/BinaryBooleanSpecial.java    |  2 +-
 .../truffle/r/nodes/ffi/CoerceVectorNode.java   | 14 +++++++-------
 .../r/nodes/unary/CastExpressionNode.java       |  6 ++++--
 .../truffle/r/runtime/conn/FileConnections.java |  2 --
 .../truffle/r/runtime/conn/RawConnections.java  |  2 +-
 12 files changed, 29 insertions(+), 34 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index aee4e3ae22..9f04a1454b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -130,17 +130,18 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
 
     @Override
     protected String toString(RContext context, Object value) {
-        // Btw debugger passes result of TruffleRLanguage.findMetaObject() to this method too
-        if (value instanceof String) {
-            return (String) value;
-        }
-        if (value instanceof RPromise) {
-            RPromise promise = (RPromise) value;
+        // the debugger also passes result of TruffleRLanguage.findMetaObject() to this method
+        Object unwrapped = value;
+        if (unwrapped instanceof RPromise) {
+            RPromise promise = (RPromise) unwrapped;
             if (promise.isEvaluated()) {
-                value = promise.getValue();
+                unwrapped = promise.getValue();
             }
         }
-        return RRuntime.toString(value);
+        if (unwrapped instanceof String) {
+            return (String) unwrapped;
+        }
+        return RRuntime.toString(unwrapped);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
index e1a2b1bac6..bcc83ed895 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
@@ -60,7 +60,7 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
     @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"})
     @TruffleBoundary
-    protected static Object substituteDirect(Object object, RList list) {
+    protected static Object substituteDirect(Object object, @SuppressWarnings("unused") RList list) {
         return substituteDirect(object, createNewEnvironment());
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
index 03b79a3c25..ac97fefd9b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
@@ -62,19 +62,19 @@ public class SplineFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object splineCoef(int method, RAbstractDoubleVector x, RNull y) {
+        protected Object splineCoef(int method, RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y) {
             return SplineFunctions.splineCoef(method, x.materialize(), RDataFactory.createDoubleVector(0));
         }
 
         @Specialization
         @TruffleBoundary
-        protected Object splineCoef(int method, RNull x, RAbstractDoubleVector y) {
+        protected Object splineCoef(int method, @SuppressWarnings("unused") RNull x, RAbstractDoubleVector y) {
             return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), y.materialize());
         }
 
         @Specialization
         @TruffleBoundary
-        protected Object splineCoef(int method, RNull x, RNull y) {
+        protected Object splineCoef(int method, @SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") RNull y) {
             return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), RDataFactory.createDoubleVector(0));
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 46ffa0411b..5357665035 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -740,7 +740,7 @@ public abstract class ConnectionFunctions {
         }
 
         @TruffleBoundary
-        private RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
+        private static RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wb")) {
                 int length = object.getLength();
                 for (int i = 0; i < length; i++) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index dfa5e0c300..77bdce22b0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -60,7 +60,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
 /*
@@ -69,17 +68,12 @@ import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 @RBuiltin(name = "match", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "incomparables"}, behavior = PURE)
 public abstract class Match extends RBuiltinNode {
 
-    private static final int TABLE_SIZE_FACTOR = 10;
-
     protected abstract Object executeRIntVector(Object x, Object table, Object noMatch, Object incomparables);
 
     @Child private CastStringNode castString;
 
     @Child private Match matchRecursive;
 
-    private final NACheck naCheck = NACheck.create();
-    private final ConditionProfile bigTableProfile = ConditionProfile.createBinaryProfile();
-
     static {
         Casts casts = new Casts(Match.class);
         // TODO initially commented out because of use of scalars, the commented out version
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
index 8f75d38052..af511fd6c2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
@@ -73,7 +73,7 @@ public abstract class Substitute extends RBuiltinNode {
     }
 
     @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"})
-    protected Object doSubstitute(RPromise expr, RList list) {
+    protected Object doSubstitute(RPromise expr, @SuppressWarnings("unused") RList list) {
         return doSubstituteWithEnv(expr, SubstituteDirect.createNewEnvironment());
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
index 014a9a8aae..ee507eba25 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
@@ -76,7 +76,7 @@ public abstract class BinaryArithmeticSpecial extends RNode {
 
     @Fallback
     @SuppressWarnings("unused")
-    protected void doFallback(Object left, Object right) {
+    protected double doFallback(Object left, Object right) {
         throw RSpecialFactory.throwFullCallNeeded();
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java
index 96c8af2564..00075ef448 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanSpecial.java
@@ -82,7 +82,7 @@ public abstract class BinaryBooleanSpecial extends RNode {
 
     @Fallback
     @SuppressWarnings("unused")
-    public void doFallback(Object left, Object right) {
+    public byte doFallback(Object left, Object right) {
         throw RSpecialFactory.throwFullCallNeeded();
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
index b7eb9d97d3..d7a8d9d574 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
@@ -55,22 +55,22 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
     }
 
     @Specialization(guards = "value.isS4()")
-    Object doS4Object(RTypedValue value, int mode) {
+    Object doS4Object(@SuppressWarnings("unused") RTypedValue value, @SuppressWarnings("unused") int mode) {
         throw RError.nyi(RError.NO_CALLER, "Rf_coerceVector for S4 objects.");
     }
 
     // Note: caches should cover all valid possibilities
     @Specialization(guards = {"!isS4Object(value)", "isNotList(value)", "isValidMode(mode)", "cachedMode == mode"}, limit = "99")
-    Object doCached(Object value, int mode,
-                    @Cached("mode") int cachedMode,
+    Object doCached(Object value, @SuppressWarnings("unused") int mode,
+                    @Cached("mode") @SuppressWarnings("unused") int cachedMode,
                     @Cached("createCastNode(cachedMode)") CastNode castNode) {
         return castNode.execute(value);
     }
 
     // Lists are coerced with only preserved names unlike other types
     @Specialization(guards = {"!isS4Object(value)", "isValidMode(mode)", "cachedMode == mode"}, limit = "99")
-    Object doCached(RList value, int mode,
-                    @Cached("mode") int cachedMode,
+    Object doCached(RList value, @SuppressWarnings("unused") int mode,
+                    @Cached("mode") @SuppressWarnings("unused") int cachedMode,
                     @Cached("createCastNodeForList(cachedMode)") CastNode castNode) {
         return castNode.execute(value);
     }
@@ -120,7 +120,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
             case VECSXP:
                 return CastListNode.createForRFFI(true, forList, forList);
             case EXPRSXP:
-                return CastExpressionNode.createForRFFI(false, false, false);
+                return CastExpressionNode.createForRFFI();
             case INTSXP:
                 return CastIntegerNode.createForRFFI(true, preserveDims, preserveAttrs);
             case REALSXP:
@@ -141,7 +141,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
     private static final class CastNullNode extends CastNode {
         @Override
         @TruffleBoundary
-        public Object execute(@SuppressWarnings("unused") Object value) {
+        public Object execute(Object value) {
             if (value instanceof RList) {
                 throw RError.error(RError.NO_CALLER, Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, "list", "coerceVectorList");
             } else {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java
index a5a4c01397..3c48230dc7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java
@@ -108,8 +108,10 @@ public abstract class CastExpressionNode extends CastBaseNode {
         return RDataFactory.createExpression(new Object[]{obj});
     }
 
-    public static CastExpressionNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        // RFFI coercion to list unlike others does not preserve names it seems
+    /**
+     * RFFI coercion to list unlike others does not preserve names it seems.
+     */
+    public static CastExpressionNode createForRFFI() {
         return CastExpressionNodeGen.create(false, false, false, true);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index d12a2ac515..77c0e2875e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -32,7 +32,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
-import java.util.Objects;
 import java.util.zip.GZIPInputStream;
 
 import org.tukaani.xz.XZInputStream;
@@ -43,7 +42,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.TempPathName;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index f30f83e5b8..02d6e0dd6c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -99,7 +99,7 @@ public class RawConnections {
             return channel.getBuffer();
         }
 
-        public static long seek(SeekableMemoryByteChannel channel, long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public static long seek(SeekableMemoryByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
             final long origPos = channel.position();
             final long newPos;
             switch (seekMode) {
-- 
GitLab


From daefc00f97c0f0d4ad9e5ac917e52b0f7c727c4a Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 20 Feb 2017 15:19:17 +0100
Subject: [PATCH 033/402] remove some more obsolete code

---
 .../r/nodes/builtin/RBuiltinFactory.java      |   7 --
 .../function/FunctionExpressionNode.java      |   7 +-
 .../truffle/r/nodes/function/PromiseNode.java |  15 ++-
 .../truffle/r/nodes/function/RCallNode.java   |  12 +-
 .../r/nodes/function/WrapArgumentNode.java    |  22 +---
 .../runtime/builtins/RBuiltinDescriptor.java  |  10 +-
 .../oracle/truffle/r/runtime/nodes/RNode.java | 103 +-----------------
 7 files changed, 24 insertions(+), 152 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
index 5ef1dd975e..90e34ba0ec 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
-import java.util.Arrays;
 import java.util.function.Supplier;
 
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -46,10 +45,4 @@ public final class RBuiltinFactory extends RBuiltinDescriptor {
     public Supplier<RBuiltinNode> getConstructor() {
         return constructor;
     }
-
-    @Override
-    public String toString() {
-        return "RBuiltinFactory [name=" + getName() + ", aliases=" + Arrays.toString(getAliases()) + ", kind=" + getKind() + ", siagnature=" + getSignature() + ", nonEvaledArgs=" +
-                        Arrays.toString(getNonEvalArgs()) + ", splitCaller=" + isSplitCaller() + ", dispatch=" + getDispatch() + ", behavior=" + getBehavior() + "]";
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java
index cc6676d89f..89977152e7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,11 +66,6 @@ public final class FunctionExpressionNode extends RSourceSectionNode implements
 
     @Override
     public RFunction execute(VirtualFrame frame) {
-        return executeFunction(frame);
-    }
-
-    @Override
-    public RFunction executeFunction(VirtualFrame frame) {
         visibility.execute(frame, true);
         MaterializedFrame matFrame = frame.materialize();
         if (deoptFrameNode != null) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
index 5bea3d0032..7887b85553 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.SourceSection;
@@ -44,6 +43,7 @@ import com.oracle.truffle.r.nodes.function.opt.OptConstantPromiseNode;
 import com.oracle.truffle.r.nodes.function.opt.OptForcedEagerPromiseNode;
 import com.oracle.truffle.r.nodes.function.opt.OptVariablePromiseBaseNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -294,13 +294,12 @@ public abstract class PromiseNode extends RNode {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 lookupVarArgs = insert(ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any));
             }
-            RArgsValuesAndNames varArgsAndNames;
-            try {
-                varArgsAndNames = lookupVarArgs.executeRArgsValuesAndNames(frame);
-            } catch (UnexpectedResultException e) {
-                throw RInternalError.shouldNotReachHere(e, "'...' should always be represented by RArgsValuesAndNames");
+            Object varArgs = lookupVarArgs.execute(frame);
+            if (!(varArgs instanceof RArgsValuesAndNames)) {
+                CompilerDirectives.transferToInterpreter();
+                throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT);
             }
-            return varArgsAndNames;
+            return (RArgsValuesAndNames) varArgs;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 54c5e060a0..9aaff96744 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -47,7 +47,6 @@ import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
@@ -215,17 +214,16 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         if (explicitArgs != null) {
             return (RArgsValuesAndNames) explicitArgs.execute(frame);
         }
-        RArgsValuesAndNames varArgs;
         if (lookupVarArgs == null) {
-            varArgs = null;
+            return null;
         } else {
-            try {
-                varArgs = lookupVarArgs.executeRArgsValuesAndNames(frame);
-            } catch (UnexpectedResultException e) {
+            Object varArgs = lookupVarArgs.execute(frame);
+            if (!(varArgs instanceof RArgsValuesAndNames)) {
+                CompilerDirectives.transferToInterpreter();
                 throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT);
             }
+            return (RArgsValuesAndNames) varArgs;
         }
-        return varArgs;
     }
 
     protected FunctionDispatch createUninitializedCall() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
index 64f43e7ee5..5d1a666e1b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
@@ -88,24 +86,6 @@ public final class WrapArgumentNode extends WrapArgumentBaseNode {
         }
     }
 
-    @Override
-    public RMissing executeMissing(VirtualFrame frame) throws UnexpectedResultException {
-        try {
-            return operand.executeMissing(frame);
-        } catch (UnexpectedResultException e) {
-            throw new UnexpectedResultException(execute(frame, e.getResult()));
-        }
-    }
-
-    @Override
-    public RNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
-        try {
-            return operand.executeNull(frame);
-        } catch (UnexpectedResultException e) {
-            throw new UnexpectedResultException(execute(frame, e.getResult()));
-        }
-    }
-
     static WrapArgumentNode create(int index) {
         return new WrapArgumentNode(null, index);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
index ff436f3fb0..5ca12b5a04 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
@@ -108,10 +108,6 @@ public abstract class RBuiltinDescriptor {
         return signature;
     }
 
-    public int[] getNonEvalArgs() {
-        return nonEvalArgs;
-    }
-
     public boolean isAlwaysSplit() {
         return alwaysSplit;
     }
@@ -147,4 +143,10 @@ public abstract class RBuiltinDescriptor {
     public RSpecialFactory getSpecialCall() {
         return specialCall;
     }
+
+    @Override
+    public String toString() {
+        return "RBuiltinFactory [name=" + getName() + ", aliases=" + Arrays.toString(getAliases()) + ", kind=" + getKind() + ", siagnature=" + getSignature() + ", nonEvaledArgs=" +
+                        Arrays.toString(nonEvalArgs) + ", splitCaller=" + isSplitCaller() + ", dispatch=" + getDispatch() + ", behavior=" + getBehavior() + "]";
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
index ef19d63069..43eda05cbd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
@@ -26,27 +26,8 @@ import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrumentation.Instrumentable;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
-import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.RTypesGen;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory;
 
 @TypeSystemReference(RTypes.class)
@@ -75,42 +56,14 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode {
         return execute(frame);
     }
 
+    /*
+     * Execute functions with primitive return types:
+     */
+
     public int executeInteger(VirtualFrame frame) throws UnexpectedResultException {
         return RTypesGen.expectInteger(execute(frame));
     }
 
-    public RRaw executeRRaw(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRRaw(execute(frame));
-    }
-
-    public RComplex executeRComplex(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRComplex(execute(frame));
-    }
-
-    public RAbstractDoubleVector executeRAbstractDoubleVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractDoubleVector(execute(frame));
-    }
-
-    public RAbstractIntVector executeRAbstractIntVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractIntVector(execute(frame));
-    }
-
-    public RAbstractComplexVector executeRAbstractComplexVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractComplexVector(execute(frame));
-    }
-
-    public RAbstractLogicalVector executeRAbstractLogicalVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractLogicalVector(execute(frame));
-    }
-
-    public RAbstractRawVector executeRAbstractRawVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractRawVector(execute(frame));
-    }
-
-    public RAbstractStringVector executeRAbstractStringVector(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractStringVector(execute(frame));
-    }
-
     public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
         return RTypesGen.expectDouble(execute(frame));
     }
@@ -118,52 +71,4 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode {
     public byte executeByte(VirtualFrame frame) throws UnexpectedResultException {
         return RTypesGen.expectByte(execute(frame));
     }
-
-    public RFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRFunction(execute(frame));
-    }
-
-    public RNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRNull(execute(frame));
-    }
-
-    public RMissing executeMissing(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRMissing(execute(frame));
-    }
-
-    public String executeString(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectString(execute(frame));
-    }
-
-    public REnvironment executeREnvironment(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectREnvironment(execute(frame));
-    }
-
-    public RExpression executeRExpression(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRExpression(execute(frame));
-    }
-
-    public RSymbol executeRSymbol(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRSymbol(execute(frame));
-    }
-
-    public RLanguage executeRLanguage(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRLanguage(execute(frame));
-    }
-
-    public RPromise executeRPromise(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRPromise(execute(frame));
-    }
-
-    public RAbstractContainer executeRAbstractContainer(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRAbstractContainer(execute(frame));
-    }
-
-    public RPairList executeRPairList(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRPairList(execute(frame));
-    }
-
-    public RArgsValuesAndNames executeRArgsValuesAndNames(VirtualFrame frame) throws UnexpectedResultException {
-        return RTypesGen.expectRArgsValuesAndNames(execute(frame));
-    }
 }
-- 
GitLab


From 7c77e309940e59c0f11f997fe6ccb66164601043 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 21 Feb 2017 13:03:47 +0100
Subject: [PATCH 034/402] JNI array handling fixes

* NULL the entry in nativeArrayTable instead of its copy
* updateNativeArrays cannot retain the buffers, because the underlying vector may be modified by the up-call
---
 .../fficall/src/jni/rffiutils.c               | 57 ++++++++++++++-----
 .../fficall/src/jni/rffiutils.h               |  2 +
 2 files changed, 44 insertions(+), 15 deletions(-)

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 03118d01c2..0a58952ae4 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <assert.h>
 
 /*
  * All calls pass through one of the call(N) methods in rfficall.c, which carry the JNIEnv value,
@@ -69,13 +70,38 @@ static NativeArrayElem *nativeArrayTable;
 // hwm of nativeArrayTable
 static int nativeArrayTableHwm;
 static int nativeArrayTableLength;
-static void releaseNativeArray(JNIEnv *env, int index, int freedata);
+static void releaseNativeArray(JNIEnv *env, int index);
 
 static int isEmbedded = 0;
 void setEmbedded() {
 	isEmbedded = 1;
 }
 
+#ifdef TRACE_ENABLED
+// Helper for debugging purposes: prints out (into the trace file) the java
+// class name for given SEXP
+static const char* fastRInspect(JNIEnv *env, SEXP v) {
+    // this invokes getClass().getName()
+    jclass cls = (*env)->GetObjectClass(env, v);
+    jmethodID getClassMethodID = checkGetMethodID(env, cls, "getClass", "()Ljava/lang/Class;", 0);
+    jobject classObj = (*env)->CallObjectMethod(env, v, getClassMethodID);
+    jclass javaClassClass = (*env)->GetObjectClass(env, classObj);
+    jmethodID getNameMethodID = checkGetMethodID(env, javaClassClass, "getName", "()Ljava/lang/String;", 0);
+    jstring nameJString = (jstring)(*env)->CallObjectMethod(env, javaClassClass, getNameMethodID);
+
+    // This gets us the C string
+    const char* result = (*env)->GetStringUTFChars(env, nameJString, NULL);
+    fprintf(traceFile, "fastRInspect(%p): %s\n",  v, result);
+
+    // Release the memory
+    (*env)->ReleaseStringUTFChars(env, nameJString, result);
+}
+#endif
+
+static int isValidJNIRef(JNIEnv *env, SEXP ref) {
+    return (*env)->GetObjectRefType(env, ref) != JNIInvalidRefType;
+}
+
 // native down call depth, indexes nativeArrayTableHwmStack
 int callDepth = 0;
 
@@ -149,7 +175,7 @@ jmp_buf *getErrorJmpBuf() {
 void callExit(JNIEnv *env) {
 	int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
 	for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
-               releaseNativeArray(env, i, 1);
+               releaseNativeArray(env, i);
 	}
 	nativeArrayTableHwm = oldHwm;
 	callDepth--;
@@ -162,7 +188,7 @@ void invalidateNativeArray(JNIEnv *env, SEXP oldObj) {
 #if TRACE_NATIVE_ARRAYS
 			fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj);
 #endif
-			releaseNativeArray(env, i, 1);
+			releaseNativeArray(env, i);
 			nativeArrayTable[i].obj = NULL;
 		}
 	}
@@ -172,18 +198,22 @@ void invalidateNativeArray(JNIEnv *env, SEXP oldObj) {
 }
 
 void updateNativeArrays(JNIEnv *env) {
+    // We just release the arrays, the up call may change their contents in the R world,
+    // so we cannot re-use the native buffers which may be out of sync
 	int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
 	for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
-        releaseNativeArray(env, i, 0);
+        releaseNativeArray(env, i);
 	}
 }
 
 
 static void *findNativeArray(JNIEnv *env, SEXP x) {
 	int i;
+        assert(isValidJNIRef(env, x));
 	for (i = 0; i < nativeArrayTableHwm; i++) {
 		NativeArrayElem cv = nativeArrayTable[i];
 		if (cv.obj != NULL) {
+                        assert(isValidJNIRef(env, cv.obj));
 			if ((*env)->IsSameObject(env, cv.obj, x)) {
 				void *data = cv.data;
 #if TRACE_NATIVE_ARRAYS
@@ -277,17 +307,18 @@ void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
 	return data;
 }
 
-static void releaseNativeArray(JNIEnv *env, int i, int freedata) {
+static void releaseNativeArray(JNIEnv *env, int i) {
 	NativeArrayElem cv = nativeArrayTable[i];
 #if TRACE_NATIVE_ARRAYS
                fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d, freedata=%d)\n", cv.obj, i, freedata);
 #endif
 	if (cv.obj != NULL) {
+            assert(isValidJNIRef(env, cv.obj));
 		jboolean complete = JNI_FALSE; // pessimal
 		switch (cv.type) {
 		case INTSXP: {
 			jintArray intArray = (jintArray) cv.jArray;
-			(*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, freedata ? 0 : JNI_COMMIT);
+			(*env)->ReleaseIntArrayElements(env, intArray, (jint *)cv.data, 0);
 			break;
 		}
 
@@ -309,22 +340,20 @@ static void releaseNativeArray(JNIEnv *env, int i, int freedata) {
 
 			}
 			(*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0);
-            if (freedata){
-                free(data); // was malloc'ed in addNativeArray
-            }
+                    free(data); // was malloc'ed in addNativeArray
 			break;
 		}
 
 		case REALSXP: {
 			jdoubleArray doubleArray = (jdoubleArray) cv.jArray;
-			(*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, freedata ? 0 : JNI_COMMIT);
+			(*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, 0);
 			break;
 
 		}
 
 		case RAWSXP: {
 			jbyteArray byteArray = (jbyteArray) cv.jArray;
-			(*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, freedata ? 0 : JNI_COMMIT);
+			(*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, 0);
 			break;
 
 		}
@@ -334,10 +363,8 @@ static void releaseNativeArray(JNIEnv *env, int i, int freedata) {
 		// update complete status
 		(*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete);
 
-        if (freedata) {
             // free up the slot
-		    cv.obj = NULL;
-        }
+            nativeArrayTable[i].obj = NULL;
 	}
 }
 
@@ -377,7 +404,7 @@ SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent) {
 	cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref;
 	cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent;
 #if TRACE_REF_CACHE
-			fprintf(traceFile, "gref: add: index %d, ref %p\n", cachedGlobalRefsHwm), gref;
+			fprintf(traceFile, "gref: add: index %d, ref %p\n", cachedGlobalRefsHwm, gref);
 #endif
 	cachedGlobalRefsHwm++;
 	return gref;
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index c86fc4bc15..cca2f64363 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -72,6 +72,8 @@ void *getNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type);
 // Rare case where an operation changes the internal
 // data and thus the old C array should be invalidated
 void invalidateNativeArray(JNIEnv *env, SEXP oldObj);
+// Should be called before up calling to arbitrary code, e.g. Rf_eval,
+// to copy back the arrays into their Java counterparts
 void updateNativeArrays(JNIEnv *env);
 
 SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent);
-- 
GitLab


From bd02ee25ca0922fb75db34bea0ec17ac6d1d1827 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 21 Feb 2017 13:18:59 +0100
Subject: [PATCH 035/402] JNI: replace tabs for spaces + add few more
 assertions

---
 .../fficall/src/jni/rffiutils.c               | 633 +++++++++---------
 1 file changed, 318 insertions(+), 315 deletions(-)

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 0a58952ae4..07f347eec3 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -43,8 +43,8 @@ static JNIEnv *curenv = NULL;
 FILE *traceFile = NULL;
 
 typedef struct globalRefTable_struct {
-	int permanent;
-	SEXP gref;         // The jobject (SEXP) global ref
+    int permanent;
+    SEXP gref;         // The jobject (SEXP) global ref
 } GlobalRefElem;
 
 #define CACHED_GLOBALREFS_INITIAL_SIZE 64
@@ -57,10 +57,10 @@ static int cachedGlobalRefsLength;
 // N.B. There are actually two levels to this as FastR
 // wraps, e.g.,  int[] in an RIntVector.
 typedef struct nativeArrayTable_struct {
-	SEXPTYPE type;
-	SEXP obj;         // The jobject (SEXP) that data is derived from (e.g, RIntVector)
-	void *jArray;     // the jarray corresponding to obj
-	void *data;       // the (possibly) copied (or pinned) data from JNI GetXXXArrayElements
+    SEXPTYPE type;
+    SEXP obj;         // The jobject (SEXP) that data is derived from (e.g, RIntVector)
+    void *jArray;     // the jarray corresponding to obj
+    void *data;       // the (possibly) copied (or pinned) data from JNI GetXXXArrayElements
 } NativeArrayElem;
 
 #define NATIVE_ARRAY_TABLE_INITIAL_SIZE 64
@@ -74,7 +74,7 @@ static void releaseNativeArray(JNIEnv *env, int index);
 
 static int isEmbedded = 0;
 void setEmbedded() {
-	isEmbedded = 1;
+    isEmbedded = 1;
 }
 
 #ifdef TRACE_ENABLED
@@ -113,411 +113,414 @@ static jmp_buf* callErrorJmpBufTable[CALLDEPTH_STACK_SIZE];
 
 
 void init_utils(JNIEnv *env, jobject upCallsInstance) {
-	curenv = env;
-	UpCallsRFFIClass = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, upCallsInstance));
-	UpCallsRFFIObject = (*env)->NewGlobalRef(env, upCallsInstance);
-	if (TRACE_ENABLED && traceFile == NULL) {
-		if (!isEmbedded) {
-			traceFile = stdout;
-		} else {
-			jclass RFFIUtilsClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/RFFIUtils");
-			jclass FileDescriptorClass = checkFindClass(env, "java/io/FileDescriptor");
-			jmethodID getTraceFileDescriptorMethodID = checkGetMethodID(env, RFFIUtilsClass, "getTraceFileDescriptor", "()Ljava/io/FileDescriptor;", 1);
-			// ASSUMPTION: FileDescriptor has an "fd" field
-			jobject tfd = (*env)->CallStaticObjectMethod(env, RFFIUtilsClass, getTraceFileDescriptorMethodID);
-			jfieldID fdField = checkGetFieldID(env, FileDescriptorClass, "fd", "I", 0);
-			int fd = (*env)->GetIntField(env, tfd, fdField);
-		    traceFile = fdopen(fd, "w");
-		    if (traceFile == NULL) {
-				fprintf(stderr, "%s, %d", "failed to fdopen trace file on JNI side\n", errno);
-				exit(1);
-			}
-		    // no buffering
-		    setvbuf(traceFile, (char*) NULL, _IONBF, 0);
-		}
-	}
+    curenv = env;
+    UpCallsRFFIClass = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, upCallsInstance));
+    UpCallsRFFIObject = (*env)->NewGlobalRef(env, upCallsInstance);
+    if (TRACE_ENABLED && traceFile == NULL) {
+        if (!isEmbedded) {
+            traceFile = stdout;
+        } else {
+            jclass RFFIUtilsClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/RFFIUtils");
+            jclass FileDescriptorClass = checkFindClass(env, "java/io/FileDescriptor");
+            jmethodID getTraceFileDescriptorMethodID = checkGetMethodID(env, RFFIUtilsClass, "getTraceFileDescriptor", "()Ljava/io/FileDescriptor;", 1);
+            // ASSUMPTION: FileDescriptor has an "fd" field
+            jobject tfd = (*env)->CallStaticObjectMethod(env, RFFIUtilsClass, getTraceFileDescriptorMethodID);
+            jfieldID fdField = checkGetFieldID(env, FileDescriptorClass, "fd", "I", 0);
+            int fd = (*env)->GetIntField(env, tfd, fdField);
+            traceFile = fdopen(fd, "w");
+            if (traceFile == NULL) {
+                fprintf(stderr, "%s, %d", "failed to fdopen trace file on JNI side\n", errno);
+                exit(1);
+            }
+            // no buffering
+            setvbuf(traceFile, (char*) NULL, _IONBF, 0);
+        }
+    }
     cachedGlobalRefs = calloc(CACHED_GLOBALREFS_INITIAL_SIZE, sizeof(GlobalRefElem));
     cachedGlobalRefsLength = CACHED_GLOBALREFS_INITIAL_SIZE;
     cachedGlobalRefsHwm = 0;
-	nativeArrayTable = calloc(NATIVE_ARRAY_TABLE_INITIAL_SIZE, sizeof(NativeArrayElem));
-	nativeArrayTableLength = NATIVE_ARRAY_TABLE_INITIAL_SIZE;
-	nativeArrayTableHwm = 0;
+    nativeArrayTable = calloc(NATIVE_ARRAY_TABLE_INITIAL_SIZE, sizeof(NativeArrayElem));
+    nativeArrayTableLength = NATIVE_ARRAY_TABLE_INITIAL_SIZE;
+    nativeArrayTableHwm = 0;
 }
 
 const char *stringToChars(JNIEnv *jniEnv, jstring string) {
-	// This is nasty:
-	// 1. the resulting character array has to be copied and zero-terminated.
-	// 2. It causes an (inevitable?) memory leak
-	jsize len = (*jniEnv)->GetStringUTFLength(jniEnv, string);
-	const char *stringChars = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL);
-	char *copyChars = malloc(len + 1);
-	memcpy(copyChars, stringChars, len);
-	copyChars[len] = 0;
-	return copyChars;
+    // This is nasty:
+    // 1. the resulting character array has to be copied and zero-terminated.
+    // 2. It causes an (inevitable?) memory leak
+    jsize len = (*jniEnv)->GetStringUTFLength(jniEnv, string);
+    const char *stringChars = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL);
+    char *copyChars = malloc(len + 1);
+    memcpy(copyChars, stringChars, len);
+    copyChars[len] = 0;
+    return copyChars;
 }
 
 void callEnter(JNIEnv *env, jmp_buf *jmpbuf) {
-	setEnv(env);
-	//printf("callEnter: callDepth %d, jmpbufptr %p\n", callDepth, jmpbuf);
-	callErrorJmpBufTable[callDepth] = jmpbuf;
-	if (callDepth >= CALLDEPTH_STACK_SIZE) {
-		fatalError("call stack overflow\n");
-	}
-	nativeArrayTableHwmStack[callDepth] = nativeArrayTableHwm;
-	callDepth++;
+    setEnv(env);
+    //printf("callEnter: callDepth %d, jmpbufptr %p\n", callDepth, jmpbuf);
+    callErrorJmpBufTable[callDepth] = jmpbuf;
+    if (callDepth >= CALLDEPTH_STACK_SIZE) {
+        fatalError("call stack overflow\n");
+    }
+    nativeArrayTableHwmStack[callDepth] = nativeArrayTableHwm;
+    callDepth++;
 }
 
 jmp_buf *getErrorJmpBuf() {
-	// printf("getErrorJmpBuf: callDepth %d, jmpbufptr %p\n", callDepth, callErrorJmpBufTable[callDepth - 1]);
-	return callErrorJmpBufTable[callDepth - 1];
+    // printf("getErrorJmpBuf: callDepth %d, jmpbufptr %p\n", callDepth, callErrorJmpBufTable[callDepth - 1]);
+    return callErrorJmpBufTable[callDepth - 1];
 }
 
 void callExit(JNIEnv *env) {
-	int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
-	for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
-               releaseNativeArray(env, i);
-	}
-	nativeArrayTableHwm = oldHwm;
-	callDepth--;
+    int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
+    for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
+        releaseNativeArray(env, i);
+    }
+    nativeArrayTableHwm = oldHwm;
+    callDepth--;
 }
 
 void invalidateNativeArray(JNIEnv *env, SEXP oldObj) {
-	for (int i = 0; i < nativeArrayTableHwm; i++) {
-		NativeArrayElem cv = nativeArrayTable[i];
-		if ((*env)->IsSameObject(env, cv.obj, oldObj)) {
+    assert(isValidJNIRef(env, oldObj));
+    for (int i = 0; i < nativeArrayTableHwm; i++) {
+        NativeArrayElem cv = nativeArrayTable[i];
+        if ((*env)->IsSameObject(env, cv.obj, oldObj)) {
 #if TRACE_NATIVE_ARRAYS
-			fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj);
+            fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj);
 #endif
-			releaseNativeArray(env, i);
-			nativeArrayTable[i].obj = NULL;
-		}
-	}
+            releaseNativeArray(env, i);
+            nativeArrayTable[i].obj = NULL;
+        }
+    }
 #if TRACE_NATIVE_ARRAYS
-	fprintf(traceFile, "invalidateNativeArray(%p): not found\n", oldObj);
+    fprintf(traceFile, "invalidateNativeArray(%p): not found\n", oldObj);
 #endif
 }
 
 void updateNativeArrays(JNIEnv *env) {
     // We just release the arrays, the up call may change their contents in the R world,
     // so we cannot re-use the native buffers which may be out of sync
-	int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
-	for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
+    int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
+    for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
         releaseNativeArray(env, i);
-	}
+    }
 }
 
 
 static void *findNativeArray(JNIEnv *env, SEXP x) {
-	int i;
-        assert(isValidJNIRef(env, x));
-	for (i = 0; i < nativeArrayTableHwm; i++) {
-		NativeArrayElem cv = nativeArrayTable[i];
-		if (cv.obj != NULL) {
-                        assert(isValidJNIRef(env, cv.obj));
-			if ((*env)->IsSameObject(env, cv.obj, x)) {
-				void *data = cv.data;
+    int i;
+    assert(isValidJNIRef(env, x));
+    for (i = 0; i < nativeArrayTableHwm; i++) {
+        NativeArrayElem cv = nativeArrayTable[i];
+        if (cv.obj != NULL) {
+            assert(isValidJNIRef(env, cv.obj));
+            if ((*env)->IsSameObject(env, cv.obj, x)) {
+                void *data = cv.data;
 #if TRACE_NATIVE_ARRAYS
-				fprintf(traceFile, "findNativeArray(%p): found %p\n", x, data);
+                fprintf(traceFile, "findNativeArray(%p): found %p\n", x, data);
 #endif
-				return data;
-			}
-		}
-	}
+                return data;
+            }
+        }
+    }
 #if TRACE_NATIVE_ARRAYS
-	fprintf(traceFile, "findNativeArray(%p): not found\n", x);
+    fprintf(traceFile, "findNativeArray(%p): not found\n", x);
 #endif
-	return NULL;
+    return NULL;
 }
 
 static void addNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type, void *jArray, void *data) {
 #if TRACE_NATIVE_ARRAYS
-	fprintf(traceFile, "addNativeArray(x=%p, t=%p, ix=%d)\n", x, data, nativeArrayTableHwm);
+    fprintf(traceFile, "addNativeArray(x=%p, t=%p, ix=%d)\n", x, data, nativeArrayTableHwm);
 #endif
-	// check for overflow
-	if (nativeArrayTableHwm >= nativeArrayTableLength) {
-		int newLength = 2 * nativeArrayTableLength;
-		NativeArrayElem *newnativeArrayTable = calloc(newLength, sizeof(NativeArrayElem));
-		if (newnativeArrayTable == NULL) {
-			fatalError("FFI copied vectors table expansion failure");
-		}
-		memcpy(newnativeArrayTable, nativeArrayTable, nativeArrayTableLength * sizeof(NativeArrayElem));
-		free(nativeArrayTable);
-		nativeArrayTable = newnativeArrayTable;
-		nativeArrayTableLength = newLength;
-	}
-	nativeArrayTable[nativeArrayTableHwm].obj = x;
-	nativeArrayTable[nativeArrayTableHwm].data = data;
-	nativeArrayTable[nativeArrayTableHwm].type = type;
-	nativeArrayTable[nativeArrayTableHwm].jArray = jArray;
-	nativeArrayTableHwm++;
+    // check for overflow
+    if (nativeArrayTableHwm >= nativeArrayTableLength) {
+        int newLength = 2 * nativeArrayTableLength;
+        NativeArrayElem *newnativeArrayTable = calloc(newLength, sizeof(NativeArrayElem));
+        if (newnativeArrayTable == NULL) {
+            fatalError("FFI copied vectors table expansion failure");
+        }
+        memcpy(newnativeArrayTable, nativeArrayTable, nativeArrayTableLength * sizeof(NativeArrayElem));
+        free(nativeArrayTable);
+        nativeArrayTable = newnativeArrayTable;
+        nativeArrayTableLength = newLength;
+    }
+    nativeArrayTable[nativeArrayTableHwm].obj = x;
+    nativeArrayTable[nativeArrayTableHwm].data = data;
+    nativeArrayTable[nativeArrayTableHwm].type = type;
+    nativeArrayTable[nativeArrayTableHwm].jArray = jArray;
+    nativeArrayTableHwm++;
 }
 
 void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
-	void *data = findNativeArray(thisenv, x);
-	jboolean isCopy;
-	if (data == NULL) {
-		jarray jArray;
-		switch (type) {
-		case INTSXP: {
-			jintArray intArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, INTEGER_MethodID, x);
-			int len = (*thisenv)->GetArrayLength(thisenv, intArray);
-			data = (*thisenv)->GetIntArrayElements(thisenv, intArray, &isCopy);
-			jArray = intArray;
-			break;
-		}
-
-		case REALSXP: {
-			jdoubleArray doubleArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, REAL_MethodID, x);
-			int len = (*thisenv)->GetArrayLength(thisenv, doubleArray);
-			data = (*thisenv)->GetDoubleArrayElements(thisenv, doubleArray, &isCopy);
-			jArray = doubleArray;
-			break;
-		}
-
-		case RAWSXP: {
-		    jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, RAW_MethodID, x);
-		    int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
-		    data = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
-	        jArray = byteArray;
-	        break;
-		}
-
-		case LGLSXP: {
-			// Special treatment becuase R FFI wants int* and FastR represents using byte[]
-		    jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x);
-		    int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
-		    jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
-		    int* idata = malloc(len * sizeof(int));
-		    for (int i = 0; i < len; i++) {
-		    	char value = internalData[i];
-		    	idata[i] = value == 0 ? FALSE : value == 1 ? TRUE : NA_INTEGER;
-		    }
-		    (*thisenv)->ReleaseByteArrayElements(thisenv, byteArray, internalData, JNI_ABORT);
-		    jArray = byteArray;
-		    data = idata;
-		    break;
-		}
-
-		default:
-			fatalError("getNativeArray: unexpected type");
-
-		}
-		addNativeArray(thisenv, x, type, jArray, data);
-	}
-	return data;
+    void *data = findNativeArray(thisenv, x);
+    jboolean isCopy;
+    if (data == NULL) {
+        jarray jArray;
+        switch (type) {
+        case INTSXP: {
+            jintArray intArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, INTEGER_MethodID, x);
+            int len = (*thisenv)->GetArrayLength(thisenv, intArray);
+            data = (*thisenv)->GetIntArrayElements(thisenv, intArray, &isCopy);
+            jArray = intArray;
+            break;
+        }
+
+        case REALSXP: {
+            jdoubleArray doubleArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, REAL_MethodID, x);
+            int len = (*thisenv)->GetArrayLength(thisenv, doubleArray);
+            data = (*thisenv)->GetDoubleArrayElements(thisenv, doubleArray, &isCopy);
+            jArray = doubleArray;
+            break;
+        }
+
+        case RAWSXP: {
+            jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, RAW_MethodID, x);
+            int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
+            data = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
+            jArray = byteArray;
+            break;
+        }
+
+        case LGLSXP: {
+            // Special treatment becuase R FFI wants int* and FastR represents using byte[]
+            jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x);
+            int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
+            jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
+            int* idata = malloc(len * sizeof(int));
+            for (int i = 0; i < len; i++) {
+                char value = internalData[i];
+                idata[i] = value == 0 ? FALSE : value == 1 ? TRUE : NA_INTEGER;
+            }
+            (*thisenv)->ReleaseByteArrayElements(thisenv, byteArray, internalData, JNI_ABORT);
+            jArray = byteArray;
+            data = idata;
+            break;
+        }
+
+        default:
+            fatalError("getNativeArray: unexpected type");
+
+        }
+        addNativeArray(thisenv, x, type, jArray, data);
+    }
+    return data;
 }
 
 static void releaseNativeArray(JNIEnv *env, int i) {
-	NativeArrayElem cv = nativeArrayTable[i];
+    NativeArrayElem cv = nativeArrayTable[i];
 #if TRACE_NATIVE_ARRAYS
                fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d, freedata=%d)\n", cv.obj, i, freedata);
 #endif
-	if (cv.obj != NULL) {
-            assert(isValidJNIRef(env, cv.obj));
-		jboolean complete = JNI_FALSE; // pessimal
-		switch (cv.type) {
-		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;
-			complete = JNI_TRUE; // since we going to look at each element anyway
-			for (int i = 0; i < len; i++) {
-				int isNA = data[i] == NA_INTEGER ? JNI_TRUE : JNI_FALSE;
-				if (isNA) {
-					internalData[i] = 255;
-					complete = JNI_FALSE;
-				} else {
-					internalData[i] = (jbyte) data[i];
-				}
-
-			}
-			(*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0);
+    if (cv.obj != NULL) {
+        assert(isValidJNIRef(env, cv.obj));
+        jboolean complete = JNI_FALSE; // pessimal
+        switch (cv.type) {
+        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;
+            complete = JNI_TRUE; // since we going to look at each element anyway
+            for (int i = 0; i < len; i++) {
+                int isNA = data[i] == NA_INTEGER ? JNI_TRUE : JNI_FALSE;
+                if (isNA) {
+                    internalData[i] = 255;
+                    complete = JNI_FALSE;
+                } else {
+                    internalData[i] = (jbyte) data[i];
+                }
+
+            }
+            (*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0);
                     free(data); // was malloc'ed in addNativeArray
-			break;
-		}
-
-		case REALSXP: {
-			jdoubleArray doubleArray = (jdoubleArray) cv.jArray;
-			(*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, 0);
-			break;
-
-		}
-
-		case RAWSXP: {
-			jbyteArray byteArray = (jbyteArray) cv.jArray;
-			(*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, 0);
-			break;
-
-		}
-		default:
-			fatalError("releaseNativeArray type");
-		}
-		// update complete status
-		(*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete);
-
-            // free up the slot
-            nativeArrayTable[i].obj = NULL;
-	}
+            break;
+        }
+
+        case REALSXP: {
+            jdoubleArray doubleArray = (jdoubleArray) cv.jArray;
+            (*env)->ReleaseDoubleArrayElements(env, doubleArray, (jdouble *)cv.data, 0);
+            break;
+
+        }
+
+        case RAWSXP: {
+            jbyteArray byteArray = (jbyteArray) cv.jArray;
+            (*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, 0);
+            break;
+
+        }
+        default:
+            fatalError("releaseNativeArray type");
+        }
+        // update complete status
+        (*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete);
+
+        // free up the slot
+        nativeArrayTable[i].obj = NULL;
+    }
 }
 
 static SEXP findCachedGlobalRef(JNIEnv *env, SEXP obj) {
-	for (int i = 0; i < cachedGlobalRefsHwm; i++) {
-		GlobalRefElem elem = cachedGlobalRefs[i];
-		if (elem.gref == NULL) {
-			continue;
-		}
-		if ((*env)->IsSameObject(env, elem.gref, obj)) {
+    // TODO: this assert fails in test RFFI: assert(isValidJNIRef(env, obj));
+    for (int i = 0; i < cachedGlobalRefsHwm; i++) {
+        GlobalRefElem elem = cachedGlobalRefs[i];
+        if (elem.gref == NULL) {
+            continue;
+        }
+        if ((*env)->IsSameObject(env, elem.gref, obj)) {
 #if TRACE_REF_CACHE
-			fprintf(traceFile, "gref: cache hit: %d\n", i);
+            fprintf(traceFile, "gref: cache hit: %d\n", i);
 #endif
-			return elem.gref;
-		}
-	}
-	return NULL;
+            return elem.gref;
+        }
+    }
+    return NULL;
 }
 
 SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent) {
-	SEXP gref;
-	if (cachedGlobalRefsHwm >= cachedGlobalRefsLength) {
-		int newLength = cachedGlobalRefsLength * 2;
+    SEXP gref;
+    assert(isValidJNIRef(env, obj));
+    if (cachedGlobalRefsHwm >= cachedGlobalRefsLength) {
+        int newLength = cachedGlobalRefsLength * 2;
 #if TRACE_REF_CACHE
-		fprintf(traceFile, "gref: extending table to %d\n", newLength);
+        fprintf(traceFile, "gref: extending table to %d\n", newLength);
 #endif
-		SEXP newCachedGlobalRefs = calloc(newLength, sizeof(GlobalRefElem));
-		if (newCachedGlobalRefs == NULL) {
-			fatalError("FFI global refs table expansion failure");
-		}
-		memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(GlobalRefElem));
-		free(cachedGlobalRefs);
-		cachedGlobalRefs = newCachedGlobalRefs;
-		cachedGlobalRefsLength = newLength;
-	}
-	gref = (*env)->NewGlobalRef(env, obj);
-	cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref;
-	cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent;
+        SEXP newCachedGlobalRefs = calloc(newLength, sizeof(GlobalRefElem));
+        if (newCachedGlobalRefs == NULL) {
+            fatalError("FFI global refs table expansion failure");
+        }
+        memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(GlobalRefElem));
+        free(cachedGlobalRefs);
+        cachedGlobalRefs = newCachedGlobalRefs;
+        cachedGlobalRefsLength = newLength;
+    }
+    gref = (*env)->NewGlobalRef(env, obj);
+    cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref;
+    cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent;
 #if TRACE_REF_CACHE
-			fprintf(traceFile, "gref: add: index %d, ref %p\n", cachedGlobalRefsHwm, gref);
+            fprintf(traceFile, "gref: add: index %d, ref %p\n", cachedGlobalRefsHwm, gref);
 #endif
-	cachedGlobalRefsHwm++;
-	return gref;
+    cachedGlobalRefsHwm++;
+    return gref;
 }
 
 SEXP checkRef(JNIEnv *env, SEXP obj) {
-	SEXP gref = findCachedGlobalRef(env, obj);
-	TRACE(TARGpp, obj, gref);
-	if (gref == NULL) {
-		return obj;
-	} else {
-	    return gref;
-	}
+    SEXP gref = findCachedGlobalRef(env, obj);
+    TRACE(TARGpp, obj, gref);
+    if (gref == NULL) {
+        return obj;
+    } else {
+        return gref;
+    }
 }
 
 SEXP createGlobalRef(JNIEnv *env, SEXP obj, int permanent) {
-	SEXP gref = findCachedGlobalRef(env, obj);
-	if (gref == NULL) {
-		gref = addGlobalRef(env, obj, permanent);
-	}
-	return gref;
+    SEXP gref = findCachedGlobalRef(env, obj);
+    if (gref == NULL) {
+        gref = addGlobalRef(env, obj, permanent);
+    }
+    return gref;
 }
 
 void releaseGlobalRef(JNIEnv *env, SEXP obj) {
-	for (int i = 0; i < cachedGlobalRefsHwm; i++) {
-		GlobalRefElem elem = cachedGlobalRefs[i];
-		if (elem.gref == NULL || elem.permanent) {
-			continue;
-		}
-		if ((*env)->IsSameObject(env, elem.gref, obj)) {
+    for (int i = 0; i < cachedGlobalRefsHwm; i++) {
+        GlobalRefElem elem = cachedGlobalRefs[i];
+        if (elem.gref == NULL || elem.permanent) {
+            continue;
+        }
+        if ((*env)->IsSameObject(env, elem.gref, obj)) {
 #if TRACE_REF_CACHE
-			fprintf(traceFile, "gref: release: index %d, gref: %p\n", i, elem.gref);
+            fprintf(traceFile, "gref: release: index %d, gref: %p\n", i, elem.gref);
 #endif
-			(*env)->DeleteGlobalRef(env, elem.gref);
-			cachedGlobalRefs[i].gref = NULL;
-		}
-	}
+            (*env)->DeleteGlobalRef(env, elem.gref);
+            cachedGlobalRefs[i].gref = NULL;
+        }
+    }
 }
 
 void validateRef(JNIEnv *env, SEXP x, const char *msg) {
-	jobjectRefType t = (*env)->GetObjectRefType(env, x);
-	if (t == JNIInvalidRefType) {
-		char buf[1000];
-		sprintf(buf, "%s %p", msg,x);
-		fatalError(buf);
-	}
+    jobjectRefType t = (*env)->GetObjectRefType(env, x);
+    if (t == JNIInvalidRefType) {
+        char buf[1000];
+        sprintf(buf, "%s %p", msg,x);
+        fatalError(buf);
+    }
 }
 
 JNIEnv *getEnv() {
-//	fprintf(traceFile, "getEnv()=%p\n", curenv);
-	return curenv;
+//    fprintf(traceFile, "getEnv()=%p\n", curenv);
+    return curenv;
 }
 
 void setEnv(JNIEnv *env) {
-//	printf("setEnv(%p)\n", env);
-	curenv = env;
+//    printf("setEnv(%p)\n", env);
+    curenv = env;
 }
 
 void *unimplemented(char *msg) {
-	JNIEnv *thisenv = getEnv();
-	char buf[1024];
-	strcpy(buf, "unimplemented ");
-	strcat(buf, msg);
-	(*thisenv)->FatalError(thisenv, buf);
-	// to keep compiler happy
-	return NULL;
+    JNIEnv *thisenv = getEnv();
+    char buf[1024];
+    strcpy(buf, "unimplemented ");
+    strcat(buf, msg);
+    (*thisenv)->FatalError(thisenv, buf);
+    // to keep compiler happy
+    return NULL;
 }
 
 void fatalError(char *msg) {
-	JNIEnv *thisenv = getEnv();
-	(*thisenv)->FatalError(thisenv, msg);
+    JNIEnv *thisenv = getEnv();
+    (*thisenv)->FatalError(thisenv, msg);
 }
 
 // Class/method search
 jclass checkFindClass(JNIEnv *env, const char *name) {
-	jclass klass = (*env)->FindClass(env, name);
-	if (klass == NULL) {
-		char buf[1024];
-		strcpy(buf, "failed to find class ");
-		strcat(buf, name);
-		(*env)->FatalError(env, buf);
-	}
-	return (*env)->NewGlobalRef(env, klass);
+    jclass klass = (*env)->FindClass(env, name);
+    if (klass == NULL) {
+        char buf[1024];
+        strcpy(buf, "failed to find class ");
+        strcat(buf, name);
+        (*env)->FatalError(env, buf);
+    }
+    return (*env)->NewGlobalRef(env, klass);
 }
 
 jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic) {
-	jmethodID methodID = isStatic ? (*env)->GetStaticMethodID(env, klass, name, sig) : (*env)->GetMethodID(env, klass, name, sig);
-	if (methodID == NULL) {
-		char buf[1024];
-		strcpy(buf, "failed to find ");
-		strcat(buf, isStatic ? "static" : "instance");
-		strcat(buf, " method ");
-		strcat(buf, name);
-		strcat(buf, "(");
-		strcat(buf, sig);
-		strcat(buf, ")");
-		(*env)->FatalError(env, buf);
-	}
-	return methodID;
+    jmethodID methodID = isStatic ? (*env)->GetStaticMethodID(env, klass, name, sig) : (*env)->GetMethodID(env, klass, name, sig);
+    if (methodID == NULL) {
+        char buf[1024];
+        strcpy(buf, "failed to find ");
+        strcat(buf, isStatic ? "static" : "instance");
+        strcat(buf, " method ");
+        strcat(buf, name);
+        strcat(buf, "(");
+        strcat(buf, sig);
+        strcat(buf, ")");
+        (*env)->FatalError(env, buf);
+    }
+    return methodID;
 }
 
 jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic) {
-	jfieldID fieldID = isStatic ? (*env)->GetStaticFieldID(env, klass, name, sig) : (*env)->GetFieldID(env, klass, name, sig);
-	if (fieldID == NULL) {
-		char buf[1024];
-		strcpy(buf, "failed to find ");
-		strcat(buf, isStatic ? "static" : "instance");
-		strcat(buf, " field ");
-		strcat(buf, name);
-		strcat(buf, "(");
-		strcat(buf, sig);
-		strcat(buf, ")");
-		(*env)->FatalError(env, buf);
-	}
-	return fieldID;
+    jfieldID fieldID = isStatic ? (*env)->GetStaticFieldID(env, klass, name, sig) : (*env)->GetFieldID(env, klass, name, sig);
+    if (fieldID == NULL) {
+        char buf[1024];
+        strcpy(buf, "failed to find ");
+        strcat(buf, isStatic ? "static" : "instance");
+        strcat(buf, " field ");
+        strcat(buf, name);
+        strcat(buf, "(");
+        strcat(buf, sig);
+        strcat(buf, ")");
+        (*env)->FatalError(env, buf);
+    }
+    return fieldID;
 }
-- 
GitLab


From a73e15e7b8f69d0a036226a4ddc1b7b7d2074a32 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Feb 2017 19:27:27 +0100
Subject: [PATCH 036/402] fix isfinite/isinfinite/isnan functions

---
 .../nodes/builtin/base/IsFiniteFunctions.java | 29 ++++++------
 .../truffle/r/nodes/unary/TypeofNode.java     |  6 +++
 .../truffle/r/test/ExpectedTestOutput.test    | 46 +++++++++----------
 .../r/test/builtins/TestBuiltin_isfinite.java | 18 ++++----
 .../test/builtins/TestBuiltin_isinfinite.java | 26 ++++-------
 .../r/test/builtins/TestBuiltin_isnan.java    | 10 ++--
 6 files changed, 66 insertions(+), 69 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
index f1ce895c28..f98ece1fa5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
@@ -29,12 +29,13 @@ import java.util.Arrays;
 import java.util.function.DoublePredicate;
 import java.util.function.IntPredicate;
 
-import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
-import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -53,6 +54,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 public class IsFiniteFunctions {
 
     public abstract static class Adapter extends RBuiltinNode {
+
+        @Child private GetDimAttributeNode getDims = GetDimAttributeNode.create();
+        @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
+
         @FunctionalInterface
         protected interface ComplexPredicate {
             boolean test(RComplex x);
@@ -78,22 +83,16 @@ public class IsFiniteFunctions {
             return doFunConstant(x, RRuntime.LOGICAL_FALSE);
         }
 
-        @Child private TypeofNode typeofNode;
-
         @Fallback
+        @TruffleBoundary
         protected Object doIsFiniteOther(Object x) {
-            if (typeofNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                typeofNode = insert(TypeofNodeGen.create());
-            }
-            String type = typeofNode.execute(x).getName();
-            throw RError.error(this, RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, type);
+            throw RError.error(this, RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, TypeofNode.getTypeof(x).getName());
         }
 
         protected RLogicalVector doFunConstant(RAbstractVector x, byte value) {
             byte[] b = new byte[x.getLength()];
             Arrays.fill(b, value);
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
         }
 
         protected RLogicalVector doFunDouble(RAbstractDoubleVector x, DoublePredicate fun) {
@@ -101,7 +100,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
         }
 
         protected RLogicalVector doFunLogical(RAbstractLogicalVector x, LogicalPredicate fun) {
@@ -109,7 +108,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
         }
 
         protected RLogicalVector doFunInt(RAbstractIntVector x, IntPredicate fun) {
@@ -117,7 +116,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
         }
 
         protected RLogicalVector doFunComplex(RAbstractComplexVector x, ComplexPredicate fun) {
@@ -125,7 +124,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
index 358b1b3ce4..33fa857d3b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
@@ -80,4 +81,9 @@ public abstract class TypeofNode extends UnaryNode {
     protected static RType doGenericTyped(RTypedValue operand) {
         return operand.getRType();
     }
+
+    public static RType getTypeof(Object operand) {
+        CompilerAsserts.neverPartOfCompilation();
+        return ((RTypedValue) RRuntime.asAbstractVector(operand)).getRType();
+    }
 }
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 3c238793e1..ab007e9ef8 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
@@ -24981,7 +24981,7 @@ Error in class(x) <- "factor" :
 #argv <- list(c(20.1635649375266, 0.00464806897188935, 7.66871331765456, 12.5627629785965, 11.5797681339384, 12.9719582729673, 25.2769526097163, -1.81739378653632, 0.81215865601413, -3.83170645669318, -0.246853801421158, 3.46135095276697, 2.4554639832607, -3.21187324485145, -3.0183971859156));is.finite(argv[[1]]);
  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite10#
 #argv <- list(structure(c(-32.6915744137254, -24.6945405669482, -24.6945405669482, -357.79068676373), .Dim = c(2L, 2L)));is.finite(argv[[1]]);
      [,1] [,2]
 [1,] TRUE TRUE
@@ -24995,7 +24995,7 @@ Error in class(x) <- "factor" :
 #argv <- list(c(0.0599, 0.00599, 0.000599, 5.99e-05, 5.99e-06, 5.99e-07));is.finite(argv[[1]]);
 [1] TRUE TRUE TRUE TRUE TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite13#
 #argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0.205661411508856i, 1.39139505579429-0.26763356813179i, 0.928710764113827-0.221714979045717i, -0.46926798541295+1.18846175213664i, 0.7424437487-0.205661411508856i, 0.460916205989202+0i, -0.452623703774585+0.170604003753717i, -0.094501186832143+0.54302538277632i, -0.331818442379127+0.612232958468282i, 1.39139505579429+0.26763356813179i, -0.452623703774585-0.170604003753717i, 0.400771450594052+0i, -0.927967220342259+0.479716843914174i, -0.790922791530657+0.043092176305418i, 0.928710764113827+0.221714979045717i, -0.094501186832143-0.54302538277632i, -0.927967220342259-0.479716843914174i, 0.701355901563686+0i, -0.600841318509537+0.213998439984336i, -0.46926798541295-1.18846175213664i, -0.331818442379127-0.612232958468282i, -0.790922791530657-0.043092176305418i, -0.600841318509537-0.213998439984336i, -0.625039267849257+0i), .Dim = c(5L, 5L)));is.finite(argv[[1]]);
      [,1] [,2] [,3] [,4] [,5]
 [1,] TRUE TRUE TRUE TRUE TRUE
@@ -25012,7 +25012,7 @@ Error in class(x) <- "factor" :
 #argv <- list(c(0.0099, 0.099, 0.99, 9.9, 99, 990, 9900, 99000, 990000, 9900000, 9.9e+07, 9.9e+08, 9.9e+09, 9.9e+10));is.finite(argv[[1]]);
  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite16#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite16#
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));is.finite(argv[[1]]);
 <0 x 0 matrix>
 
@@ -25024,7 +25024,7 @@ logical(0)
 #argv <- list(structure(1, .Tsp = c(1, 1, 1), class = 'ts'));is.finite(argv[[1]]);
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite19#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite19#
 #argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.finite(argv[[1]]);
    100 -1e-13    Inf   -Inf    NaN   3.14     NA
   TRUE   TRUE  FALSE  FALSE  FALSE   TRUE  FALSE
@@ -25041,7 +25041,7 @@ logical(0)
  [85]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
  [97]  TRUE  TRUE  TRUE  TRUE  TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite20#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite20#
 #argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.finite(argv[[1]]);
    100 -1e-13    Inf   -Inf    NaN   3.14     NA
   TRUE   TRUE  FALSE  FALSE  FALSE   TRUE  FALSE
@@ -25051,7 +25051,7 @@ logical(0)
  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 [16] TRUE TRUE TRUE TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite22#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite22#
 #argv <- list(structure(1:7, .Dim = c(1L, 7L)));is.finite(argv[[1]]);
      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
 [1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
@@ -25075,7 +25075,7 @@ logical(0)
 #argv <- list(structure(c(13991, 13995), class = 'Date'));is.finite(argv[[1]]);
 [1] TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite3#
 #argv <- list(structure(485.051413351662, .Names = 'value'));is.finite(argv[[1]]);
 value
  TRUE
@@ -25249,17 +25249,17 @@ fe
 #argv <- list(structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')));is.function(argv[[1]]);
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite1#
 #argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.infinite(argv[[1]]);
    100 -1e-13    Inf   -Inf    NaN   3.14     NA
  FALSE  FALSE  FALSE  FALSE  FALSE  FALSE  FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite10#
 #argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.infinite(argv[[1]]);
    100 -1e-13    Inf   -Inf    NaN   3.14     NA
  FALSE  FALSE   TRUE   TRUE  FALSE  FALSE  FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite11#
 #argv <- list(structure(c(0.140840156507829, 0.04056135019562, 0.0029302031336855, 0.244192917875952, 0.613916838192149, 0.0888451715064135, 0.0786481028238466, 0.000549230092684491, 0.00048785961836479, 0.235214398525727, 0.000402612842061681, 0.00423992719924668, 0.0355604120039037, 0.00432748168352161, 0.170388213068447, 0.466682597016338), .Names = c('1947', '1948', '1949', '1950', '1951', '1952', '1953', '1954', '1955', '1956', '1957', '1958', '1959', '1960', '1961', '1962')));is.infinite(argv[[1]]);
  1947  1948  1949  1950  1951  1952  1953  1954  1955  1956  1957  1958  1959
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -25270,7 +25270,7 @@ FALSE FALSE FALSE
 #argv <- list(4);is.infinite(argv[[1]]);
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite13#
 #argv <- list(structure(1:24, .Dim = 2:4));is.infinite(argv[[1]]);
 , , 1
 
@@ -25325,11 +25325,11 @@ B FALSE FALSE
 #argv <- list(c(Inf, -Inf));is.infinite(argv[[1]]);
 [1] TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite3#
 #argv <- list(structure(logical(0), .Dim = c(0L, 0L)));is.infinite(argv[[1]]);
 <0 x 0 matrix>
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite4#
 #argv <- list(structure(c(0.00241725013897913, 2.73568372449633e-07, 0.00400531454105884, 0.0305181933571734, 0.022064930648429, 0.000416097494498381, 0.0186357510997526, 0.00896237344987589, 0.00202331168264955, 0.00279067096737535, 0.0447487811957221, 0.000577210896095096, 0.00782925975125774, 0.033211430744327, 0.0093483442273581, 0.00136284952207105, 0.0275004422708864, 0.0135979349769553, 0.000181644594904405, 0.00803803085466393, 0.00350275333198457, 0.014998898960339, 5.39459255498146e-05, 0.00123860219686858, 1.13323906102913e-05, 0.0297916373848854, 0.0312890114433758, 5.85350754663798e-05, 0.0131002435454964, 0.00277072267615578, 0.0222123285012571, 0.00194205331979335, 0.0103231522531299, 0.0261098279661105, 0.0358853728812373, 1.13323906102913e-05, 0.0486308859679786, 0.000674881587747117, 0.0218633172580077, 0.000558592420498928, 0.000802158707806158, 0.0581913205761545, 0.000436809276845313, 0.00631994234432259, 0.000141965876420771, 0.000262833357340149, 0.0055965687842748, 0.000654737007593888, 0.0140931986366498, 0.00241538552182261, 0.00414822230660342, 0.00884150659070285, 0.0647626092888162, 0.0935599413167129, 0.00117891119201738, 0.00742609802768654, 0.0306399064130622, 0.0274290617824389, 0.00217883778937331, 0.0108387379377857, 0.0242348837396833, 0.0168720396936779, 0.022211269097018, 0.0355286679037712, 0.00017126708391638, 0.00443642409999561, 0.0068913158904869, 0.0635882367317516, 0.0566932963429416, 0.00904861729235097, 0.00038919481466495), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71')));is.infinite(argv[[1]]);
     1     2     3     4     5     6     7     8     9    10    11    12    13
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -25369,7 +25369,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE
 [20,]    FALSE      FALSE      FALSE      FALSE
 [21,]    FALSE      FALSE      FALSE      FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite6#
 #argv <- list(structure(c(1.12411954394441, -0.567321126080105, 1.28594901629635, -0.519809468914999, -1.485548782458, -0.435305441405687, -0.281625943801696, -0.527525498975648, 2.60041695299567, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')));is.infinite(argv[[1]]);
     1     2     3     4     5     6     7     8     9    10
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -25378,7 +25378,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 #argv <- list(NULL);is.infinite(argv[[1]]);
 logical(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite8#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite8#
 #argv <- list(structure(c(0.00544194018731062, 0.00542949133552226, 1.20718999105839e-05, 0.00505497198006266, 0.827687885653788, 0.00315385274195005, 0.0023164952286401, 0.00117183915211372, 2.09167441982205, 0.00193959227691399, 0.00358084102808485, 3.39138861812986e-05, 0.00163051710052444, 0.00168735925488057, 0.0167253073891896, 0.237074502262169, 0.0118967636015583, 0.00307437031103621, 0.00114371252369823, 0.000860763872820255, 0.00028432076263802, 0.00329557354736053, 0.000123683950933913, 0.00026114238659798, 0.00471892942651347, 0.00317288091968884, 6.76955217513137e-05, 0.0119061189538054, 0.00233356124758579, 0.00672098496026968, 0.134965372025281, 0.00102115420103838, 0.00114816901125044), .Names = c('Craig Dunain', 'Ben Rha', 'Ben Lomond', 'Goatfell', 'Bens of Jura', 'Cairnpapple', 'Scolty', 'Traprain', 'Lairig Ghru', 'Dollar', 'Lomonds', 'Cairn Table', 'Eildon Two', 'Cairngorm', 'Seven Hills', 'Knock Hill', 'Black Hill', 'Creag Beag', 'Kildcon Hill', 'Meall Ant-Suidhe', 'Half Ben Nevis', 'Cow Hill', 'N Berwick Law', 'Creag Dubh', 'Burnswark', 'Largo Law', 'Criffel', 'Acmony', 'Ben Nevis', 'Knockfarrel', 'Two Breweries', 'Cockleroi', 'Moffat Chase')));is.infinite(argv[[1]]);
     Craig Dunain          Ben Rha       Ben Lomond         Goatfell
            FALSE            FALSE            FALSE            FALSE
@@ -25399,7 +25399,7 @@ logical(0)
     Moffat Chase
            FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite9#
 #argv <- list(structure(c(0.648648743252693, 0.52170345712821, -0.338075767187078, 0.169770656775468, -1.86324282017776, 0.362268009067608, 0.136032794890515, 0.901814933704047, -0.671639624694386, 1.79387977353953, 0.714576709724596, -0.471811539980989, -0.857026690426369, 0.226899513968796, 0.568565310101759, -0.944564385994918, 0.693403222263985, 0.02231307737364, -0.276817414323803, -0.344452836733253, -0.844829717537689, -0.421779195680793, -0.154748062715674, 1.43960300137753, 0.256965508768852, -0.295370227475694, 0.507911869619344, -0.346156318366332, -0.187948961031579, -0.454073164294974, -0.0895014237058297, 1.91227371168715, 0.779246572061347, 0.606406152381391, -0.0628430973426908, 2.1063179091687, -1.32672093069913, -0.754254955100625, -0.59565543740158, -1.95946772292555, -0.495798772099865, -3.58086046245482, -0.721772682345538, -0.254468243441054, 2.41750264738881, -0.0647957309150968, 1.87354174039771, -0.552199273430865, 0.732944502427441, 0.703597322009966, 0.875011400025303, -0.916329805907907, -0.297942295133666, -0.239141969395332, -1.79620422664673, -1.34633804643361, -Inf, 1.84762640960041, -0.344523591926435, 1.12935189480329, -0.902874350916712, -0.187948961031579, 0.444184743731147, -0.595767030989317, -0.878351658910786, 0.131398128073247, -1.16349118303155, -0.612790192876235, -0.231519954928205, -0.944564385994918, 0.136032794890519, -0.250233723215235, -0.972829009134415, 0.576852333601859, 0.226899513968797, -0.316245505808486, 0.101419270213227, 2.16953626752671, -0.383691077846572, 0.547999893193889, 0.00183871707028874, -1.28758691932778, 0.0676445397107313, -0.809987759639438, -1.04896153736838, 0.156556073105978, 0.248659709506608, 1.27246860456928, 0.554771572109539, 1.2326801378144, 2.2926344791142, 1.00034303387372, -0.554771572109538), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93')));is.infinite(argv[[1]]);
     1     2     3     4     5     6     7     8     9    10    11    12    13
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -26314,7 +26314,7 @@ Levels: a b
 #argv <- list(NA);is.nan(argv[[1]]);
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan10#
 #argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]);
 , , 1
 
@@ -26332,7 +26332,7 @@ Levels: a b
 [1,] FALSE FALSE
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan2#
 #argv <- list(structure(1:7, .Names = c('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7')));is.nan(argv[[1]]);
    a1    a2    a3    a4    a5    a6    a7
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -26341,7 +26341,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 #argv <- list(1:3);is.nan(argv[[1]]);
 [1] FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan4#
 #argv <- list(structure(NaN, .Dim = c(1L, 1L)));is.nan(argv[[1]]);
      [,1]
 [1,] TRUE
@@ -26354,7 +26354,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 #argv <- list(NULL);is.nan(argv[[1]]);
 logical(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnan7#
 #argv <- list(structure(1:3, .Dim = c(3L, 1L)));is.nan(argv[[1]]);
       [,1]
 [1,] FALSE
@@ -41014,7 +41014,7 @@ x3  0.81       -0.97
 - x2    1     26.79  74.76 28.742
 - x1    1    820.91 868.88 60.629
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#
 #argv <- list(structure(c('1', '2', '\\b', '4', '5', '\\040', '\\x20', 'c:\\spencer\\tests', '\\t', '\\n', '\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
                  TEST
 1                   1
@@ -41061,7 +41061,7 @@ c  535  595  655  715
 #argv <- list(quote(y ~ A:U + A:V - 1), NULL, TRUE, NULL, NULL, FALSE, NULL, TRUE, TRUE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 y ~ A:U + A:V - 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#
 #argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
      [,1] [,2] [,3] [,4]
 [1,] ----  "a"  "b" "10"
@@ -138678,7 +138678,7 @@ Levels: 2147483648L
 #typeof(type.convert('2147483648L'))
 [1] "integer"
 
-##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#
 #type.convert('NA', 1)
 Error in type.convert("NA", 1) : invalid 'na.strings' argument
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java
index cb708368ec..0816c96c8e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -29,7 +29,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite3() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(485.051413351662, .Names = 'value'));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(485.051413351662, .Names = 'value'));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -65,7 +65,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite10() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(-32.6915744137254, -24.6945405669482, -24.6945405669482, -357.79068676373), .Dim = c(2L, 2L)));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(-32.6915744137254, -24.6945405669482, -24.6945405669482, -357.79068676373), .Dim = c(2L, 2L)));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -80,8 +80,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite13() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0.205661411508856i, 1.39139505579429-0.26763356813179i, 0.928710764113827-0.221714979045717i, -0.46926798541295+1.18846175213664i, 0.7424437487-0.205661411508856i, 0.460916205989202+0i, -0.452623703774585+0.170604003753717i, -0.094501186832143+0.54302538277632i, -0.331818442379127+0.612232958468282i, 1.39139505579429+0.26763356813179i, -0.452623703774585-0.170604003753717i, 0.400771450594052+0i, -0.927967220342259+0.479716843914174i, -0.790922791530657+0.043092176305418i, 0.928710764113827+0.221714979045717i, -0.094501186832143-0.54302538277632i, -0.927967220342259-0.479716843914174i, 0.701355901563686+0i, -0.600841318509537+0.213998439984336i, -0.46926798541295-1.18846175213664i, -0.331818442379127-0.612232958468282i, -0.790922791530657-0.043092176305418i, -0.600841318509537-0.213998439984336i, -0.625039267849257+0i), .Dim = c(5L, 5L)));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(-0.560475646552213+0i, 0.7424437487+0.205661411508856i, 1.39139505579429-0.26763356813179i, 0.928710764113827-0.221714979045717i, -0.46926798541295+1.18846175213664i, 0.7424437487-0.205661411508856i, 0.460916205989202+0i, -0.452623703774585+0.170604003753717i, -0.094501186832143+0.54302538277632i, -0.331818442379127+0.612232958468282i, 1.39139505579429+0.26763356813179i, -0.452623703774585-0.170604003753717i, 0.400771450594052+0i, -0.927967220342259+0.479716843914174i, -0.790922791530657+0.043092176305418i, 0.928710764113827+0.221714979045717i, -0.094501186832143-0.54302538277632i, -0.927967220342259-0.479716843914174i, 0.701355901563686+0i, -0.600841318509537+0.213998439984336i, -0.46926798541295-1.18846175213664i, -0.331818442379127-0.612232958468282i, -0.790922791530657-0.043092176305418i, -0.600841318509537-0.213998439984336i, -0.625039267849257+0i), .Dim = c(5L, 5L)));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -96,7 +95,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite16() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -111,13 +110,12 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite19() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.finite(argv[[1]]);");
     }
 
     @Test
     public void testisfinite20() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -127,7 +125,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite22() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:7, .Dim = c(1L, 7L)));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(1:7, .Dim = c(1L, 7L)));is.finite(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java
index 8697181ac8..59854d0c50 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -19,7 +19,7 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite1() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(100L, 0L, NA, NA, NA, 3L, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.infinite(argv[[1]]);");
     }
 
     @Test
@@ -29,13 +29,12 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite3() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(logical(0), .Dim = c(0L, 0L)));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(logical(0), .Dim = c(0L, 0L)));is.infinite(argv[[1]]);");
     }
 
     @Test
     public void testisinfinite4() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0.00241725013897913, 2.73568372449633e-07, 0.00400531454105884, 0.0305181933571734, 0.022064930648429, 0.000416097494498381, 0.0186357510997526, 0.00896237344987589, 0.00202331168264955, 0.00279067096737535, 0.0447487811957221, 0.000577210896095096, 0.00782925975125774, 0.033211430744327, 0.0093483442273581, 0.00136284952207105, 0.0275004422708864, 0.0135979349769553, 0.000181644594904405, 0.00803803085466393, 0.00350275333198457, 0.014998898960339, 5.39459255498146e-05, 0.00123860219686858, 1.13323906102913e-05, 0.0297916373848854, 0.0312890114433758, 5.85350754663798e-05, 0.0131002435454964, 0.00277072267615578, 0.0222123285012571, 0.00194205331979335, 0.0103231522531299, 0.0261098279661105, 0.0358853728812373, 1.13323906102913e-05, 0.0486308859679786, 0.000674881587747117, 0.0218633172580077, 0.000558592420498928, 0.000802158707806158, 0.0581913205761545, 0.000436809276845313, 0.00631994234432259, 0.000141965876420771, 0.000262833357340149, 0.0055965687842748, 0.000654737007593888, 0.0140931986366498, 0.00241538552182261, 0.00414822230660342, 0.00884150659070285, 0.0647626092888162, 0.0935599413167129, 0.00117891119201738, 0.00742609802768654, 0.0306399064130622, 0.0274290617824389, 0.00217883778937331, 0.0108387379377857, 0.0242348837396833, 0.0168720396936779, 0.022211269097018, 0.0355286679037712, 0.00017126708391638, 0.00443642409999561, 0.0068913158904869, 0.0635882367317516, 0.0566932963429416, 0.00904861729235097, 0.00038919481466495), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(0.00241725013897913, 2.73568372449633e-07, 0.00400531454105884, 0.0305181933571734, 0.022064930648429, 0.000416097494498381, 0.0186357510997526, 0.00896237344987589, 0.00202331168264955, 0.00279067096737535, 0.0447487811957221, 0.000577210896095096, 0.00782925975125774, 0.033211430744327, 0.0093483442273581, 0.00136284952207105, 0.0275004422708864, 0.0135979349769553, 0.000181644594904405, 0.00803803085466393, 0.00350275333198457, 0.014998898960339, 5.39459255498146e-05, 0.00123860219686858, 1.13323906102913e-05, 0.0297916373848854, 0.0312890114433758, 5.85350754663798e-05, 0.0131002435454964, 0.00277072267615578, 0.0222123285012571, 0.00194205331979335, 0.0103231522531299, 0.0261098279661105, 0.0358853728812373, 1.13323906102913e-05, 0.0486308859679786, 0.000674881587747117, 0.0218633172580077, 0.000558592420498928, 0.000802158707806158, 0.0581913205761545, 0.000436809276845313, 0.00631994234432259, 0.000141965876420771, 0.000262833357340149, 0.0055965687842748, 0.000654737007593888, 0.0140931986366498, 0.00241538552182261, 0.00414822230660342, 0.00884150659070285, 0.0647626092888162, 0.0935599413167129, 0.00117891119201738, 0.00742609802768654, 0.0306399064130622, 0.0274290617824389, 0.00217883778937331, 0.0108387379377857, 0.0242348837396833, 0.0168720396936779, 0.022211269097018, 0.0355286679037712, 0.00017126708391638, 0.00443642409999561, 0.0068913158904869, 0.0635882367317516, 0.0566932963429416, 0.00904861729235097, 0.00038919481466495), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71')));is.infinite(argv[[1]]);");
     }
 
     @Test
@@ -46,8 +45,7 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite6() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(1.12411954394441, -0.567321126080105, 1.28594901629635, -0.519809468914999, -1.485548782458, -0.435305441405687, -0.281625943801696, -0.527525498975648, 2.60041695299567, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(1.12411954394441, -0.567321126080105, 1.28594901629635, -0.519809468914999, -1.485548782458, -0.435305441405687, -0.281625943801696, -0.527525498975648, 2.60041695299567, NA), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')));is.infinite(argv[[1]]);");
     }
 
     @Test
@@ -57,26 +55,22 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite8() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0.00544194018731062, 0.00542949133552226, 1.20718999105839e-05, 0.00505497198006266, 0.827687885653788, 0.00315385274195005, 0.0023164952286401, 0.00117183915211372, 2.09167441982205, 0.00193959227691399, 0.00358084102808485, 3.39138861812986e-05, 0.00163051710052444, 0.00168735925488057, 0.0167253073891896, 0.237074502262169, 0.0118967636015583, 0.00307437031103621, 0.00114371252369823, 0.000860763872820255, 0.00028432076263802, 0.00329557354736053, 0.000123683950933913, 0.00026114238659798, 0.00471892942651347, 0.00317288091968884, 6.76955217513137e-05, 0.0119061189538054, 0.00233356124758579, 0.00672098496026968, 0.134965372025281, 0.00102115420103838, 0.00114816901125044), .Names = c('Craig Dunain', 'Ben Rha', 'Ben Lomond', 'Goatfell', 'Bens of Jura', 'Cairnpapple', 'Scolty', 'Traprain', 'Lairig Ghru', 'Dollar', 'Lomonds', 'Cairn Table', 'Eildon Two', 'Cairngorm', 'Seven Hills', 'Knock Hill', 'Black Hill', 'Creag Beag', 'Kildcon Hill', 'Meall Ant-Suidhe', 'Half Ben Nevis', 'Cow Hill', 'N Berwick Law', 'Creag Dubh', 'Burnswark', 'Largo Law', 'Criffel', 'Acmony', 'Ben Nevis', 'Knockfarrel', 'Two Breweries', 'Cockleroi', 'Moffat Chase')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(0.00544194018731062, 0.00542949133552226, 1.20718999105839e-05, 0.00505497198006266, 0.827687885653788, 0.00315385274195005, 0.0023164952286401, 0.00117183915211372, 2.09167441982205, 0.00193959227691399, 0.00358084102808485, 3.39138861812986e-05, 0.00163051710052444, 0.00168735925488057, 0.0167253073891896, 0.237074502262169, 0.0118967636015583, 0.00307437031103621, 0.00114371252369823, 0.000860763872820255, 0.00028432076263802, 0.00329557354736053, 0.000123683950933913, 0.00026114238659798, 0.00471892942651347, 0.00317288091968884, 6.76955217513137e-05, 0.0119061189538054, 0.00233356124758579, 0.00672098496026968, 0.134965372025281, 0.00102115420103838, 0.00114816901125044), .Names = c('Craig Dunain', 'Ben Rha', 'Ben Lomond', 'Goatfell', 'Bens of Jura', 'Cairnpapple', 'Scolty', 'Traprain', 'Lairig Ghru', 'Dollar', 'Lomonds', 'Cairn Table', 'Eildon Two', 'Cairngorm', 'Seven Hills', 'Knock Hill', 'Black Hill', 'Creag Beag', 'Kildcon Hill', 'Meall Ant-Suidhe', 'Half Ben Nevis', 'Cow Hill', 'N Berwick Law', 'Creag Dubh', 'Burnswark', 'Largo Law', 'Criffel', 'Acmony', 'Ben Nevis', 'Knockfarrel', 'Two Breweries', 'Cockleroi', 'Moffat Chase')));is.infinite(argv[[1]]);");
     }
 
     @Test
     public void testisinfinite9() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0.648648743252693, 0.52170345712821, -0.338075767187078, 0.169770656775468, -1.86324282017776, 0.362268009067608, 0.136032794890515, 0.901814933704047, -0.671639624694386, 1.79387977353953, 0.714576709724596, -0.471811539980989, -0.857026690426369, 0.226899513968796, 0.568565310101759, -0.944564385994918, 0.693403222263985, 0.02231307737364, -0.276817414323803, -0.344452836733253, -0.844829717537689, -0.421779195680793, -0.154748062715674, 1.43960300137753, 0.256965508768852, -0.295370227475694, 0.507911869619344, -0.346156318366332, -0.187948961031579, -0.454073164294974, -0.0895014237058297, 1.91227371168715, 0.779246572061347, 0.606406152381391, -0.0628430973426908, 2.1063179091687, -1.32672093069913, -0.754254955100625, -0.59565543740158, -1.95946772292555, -0.495798772099865, -3.58086046245482, -0.721772682345538, -0.254468243441054, 2.41750264738881, -0.0647957309150968, 1.87354174039771, -0.552199273430865, 0.732944502427441, 0.703597322009966, 0.875011400025303, -0.916329805907907, -0.297942295133666, -0.239141969395332, -1.79620422664673, -1.34633804643361, -Inf, 1.84762640960041, -0.344523591926435, 1.12935189480329, -0.902874350916712, -0.187948961031579, 0.444184743731147, -0.595767030989317, -0.878351658910786, 0.131398128073247, -1.16349118303155, -0.612790192876235, -0.231519954928205, -0.944564385994918, 0.136032794890519, -0.250233723215235, -0.972829009134415, 0.576852333601859, 0.226899513968797, -0.316245505808486, 0.101419270213227, 2.16953626752671, -0.383691077846572, 0.547999893193889, 0.00183871707028874, -1.28758691932778, 0.0676445397107313, -0.809987759639438, -1.04896153736838, 0.156556073105978, 0.248659709506608, 1.27246860456928, 0.554771572109539, 1.2326801378144, 2.2926344791142, 1.00034303387372, -0.554771572109538), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(0.648648743252693, 0.52170345712821, -0.338075767187078, 0.169770656775468, -1.86324282017776, 0.362268009067608, 0.136032794890515, 0.901814933704047, -0.671639624694386, 1.79387977353953, 0.714576709724596, -0.471811539980989, -0.857026690426369, 0.226899513968796, 0.568565310101759, -0.944564385994918, 0.693403222263985, 0.02231307737364, -0.276817414323803, -0.344452836733253, -0.844829717537689, -0.421779195680793, -0.154748062715674, 1.43960300137753, 0.256965508768852, -0.295370227475694, 0.507911869619344, -0.346156318366332, -0.187948961031579, -0.454073164294974, -0.0895014237058297, 1.91227371168715, 0.779246572061347, 0.606406152381391, -0.0628430973426908, 2.1063179091687, -1.32672093069913, -0.754254955100625, -0.59565543740158, -1.95946772292555, -0.495798772099865, -3.58086046245482, -0.721772682345538, -0.254468243441054, 2.41750264738881, -0.0647957309150968, 1.87354174039771, -0.552199273430865, 0.732944502427441, 0.703597322009966, 0.875011400025303, -0.916329805907907, -0.297942295133666, -0.239141969395332, -1.79620422664673, -1.34633804643361, -Inf, 1.84762640960041, -0.344523591926435, 1.12935189480329, -0.902874350916712, -0.187948961031579, 0.444184743731147, -0.595767030989317, -0.878351658910786, 0.131398128073247, -1.16349118303155, -0.612790192876235, -0.231519954928205, -0.944564385994918, 0.136032794890519, -0.250233723215235, -0.972829009134415, 0.576852333601859, 0.226899513968797, -0.316245505808486, 0.101419270213227, 2.16953626752671, -0.383691077846572, 0.547999893193889, 0.00183871707028874, -1.28758691932778, 0.0676445397107313, -0.809987759639438, -1.04896153736838, 0.156556073105978, 0.248659709506608, 1.27246860456928, 0.554771572109539, 1.2326801378144, 2.2926344791142, 1.00034303387372, -0.554771572109538), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93')));is.infinite(argv[[1]]);");
     }
 
     @Test
     public void testisinfinite10() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(100, -1e-13, Inf, -Inf, NaN, 3.14159265358979, NA), .Names = c(' 100', '-1e-13', ' Inf', '-Inf', ' NaN', '3.14', '  NA')));is.infinite(argv[[1]]);");
     }
 
     @Test
     public void testisinfinite11() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0.140840156507829, 0.04056135019562, 0.0029302031336855, 0.244192917875952, 0.613916838192149, 0.0888451715064135, 0.0786481028238466, 0.000549230092684491, 0.00048785961836479, 0.235214398525727, 0.000402612842061681, 0.00423992719924668, 0.0355604120039037, 0.00432748168352161, 0.170388213068447, 0.466682597016338), .Names = c('1947', '1948', '1949', '1950', '1951', '1952', '1953', '1954', '1955', '1956', '1957', '1958', '1959', '1960', '1961', '1962')));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(0.140840156507829, 0.04056135019562, 0.0029302031336855, 0.244192917875952, 0.613916838192149, 0.0888451715064135, 0.0786481028238466, 0.000549230092684491, 0.00048785961836479, 0.235214398525727, 0.000402612842061681, 0.00423992719924668, 0.0355604120039037, 0.00432748168352161, 0.170388213068447, 0.466682597016338), .Names = c('1947', '1948', '1949', '1950', '1951', '1952', '1953', '1954', '1955', '1956', '1957', '1958', '1959', '1960', '1961', '1962')));is.infinite(argv[[1]]);");
     }
 
     @Test
@@ -86,7 +80,7 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite13() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:24, .Dim = 2:4));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(1:24, .Dim = 2:4));is.infinite(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java
index 3b125e3880..786da412a5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -24,7 +24,7 @@ public class TestBuiltin_isnan extends TestBase {
 
     @Test
     public void testisnan2() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:7, .Names = c('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7')));is.nan(argv[[1]]);");
+        assertEval("argv <- list(structure(1:7, .Names = c('a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7')));is.nan(argv[[1]]);");
     }
 
     @Test
@@ -34,7 +34,7 @@ public class TestBuiltin_isnan extends TestBase {
 
     @Test
     public void testisnan4() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(NaN, .Dim = c(1L, 1L)));is.nan(argv[[1]]);");
+        assertEval("argv <- list(structure(NaN, .Dim = c(1L, 1L)));is.nan(argv[[1]]);");
     }
 
     @Test
@@ -49,7 +49,7 @@ public class TestBuiltin_isnan extends TestBase {
 
     @Test
     public void testisnan7() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:3, .Dim = c(3L, 1L)));is.nan(argv[[1]]);");
+        assertEval("argv <- list(structure(1:3, .Dim = c(3L, 1L)));is.nan(argv[[1]]);");
     }
 
     @Test
@@ -59,6 +59,6 @@ public class TestBuiltin_isnan extends TestBase {
 
     @Test
     public void testisnan10() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]);");
+        assertEval("argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]);");
     }
 }
-- 
GitLab


From f43b9636fc75e826de247ce43abb705680adc8ef Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Feb 2017 11:39:21 +0100
Subject: [PATCH 037/402] do not convert values with classes to primitives in
 ConvertValue

---
 .../r/nodes/builtin/base/infix/SpecialsUtils.java     | 11 +++++++----
 .../com/oracle/truffle/r/test/ExpectedTestOutput.test | 11 ++++++++---
 .../r/test/library/base/TestSimpleDataFrames.java     |  3 ++-
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 6822ea1686..14eb27121a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -223,13 +224,15 @@ class SpecialsUtils {
             return value;
         }
 
-        @Specialization(guards = "value.getLength() == 1")
-        protected static int convertIntVector(RIntVector value) {
+        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null"})
+        protected static int convertIntVector(RIntVector value,
+                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode) {
             return value.getDataAt(0);
         }
 
-        @Specialization(guards = "value.getLength() == 1")
-        protected static double convertDoubleVector(RDoubleVector value) {
+        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null"})
+        protected static double convertDoubleVector(RDoubleVector value,
+                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode) {
             return value.getDataAt(0);
         }
 
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 3c238793e1..1739ed02fa 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
@@ -41014,7 +41014,7 @@ x3  0.81       -0.97
 - x2    1     26.79  74.76 28.742
 - x1    1    820.91 868.88 60.629
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#
 #argv <- list(structure(c('1', '2', '\\b', '4', '5', '\\040', '\\x20', 'c:\\spencer\\tests', '\\t', '\\n', '\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
                  TEST
 1                   1
@@ -41061,7 +41061,7 @@ c  535  595  655  715
 #argv <- list(quote(y ~ A:U + A:V - 1), NULL, TRUE, NULL, NULL, FALSE, NULL, TRUE, TRUE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 y ~ A:U + A:V - 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#
 #argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
      [,1] [,2] [,3] [,4]
 [1,] ----  "a"  "b" "10"
@@ -79733,6 +79733,11 @@ $x
 [1] FALSE  TRUE  TRUE
 
 
+##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testMisc#
+#x <- data.frame(a=1:3,b=factor(c("a","b","c"))); x[2,]
+  a b
+2 2 b
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testMisc#
 #{ y<-data.frame(7); as.logical(y) }
 [1] TRUE
@@ -138678,7 +138683,7 @@ Levels: 2147483648L
 #typeof(type.convert('2147483648L'))
 [1] "integer"
 
-##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#
 #type.convert('NA', 1)
 Error in type.convert("NA", 1) : invalid 'na.strings' argument
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
index 0abd003a95..c6c1b883c1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -179,5 +179,6 @@ public class TestSimpleDataFrames extends TestBase {
 
         assertEval("{ y<-data.frame(c(1,2,3)); length(y) }");
 
+        assertEval("x <- data.frame(a=1:3,b=factor(c(\"a\",\"b\",\"c\"))); x[2,]");
     }
 }
-- 
GitLab


From 4e256e340879e6529937f2e7eeb0d6bd4a4e4bcd Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Feb 2017 12:10:00 +0100
Subject: [PATCH 038/402] do not switch to SIMPLEDEPARSE for attributes in
 RDeparse

---
 .../com/oracle/truffle/r/runtime/RDeparse.java |  1 -
 .../truffle/r/test/ExpectedTestOutput.test     | 18 ++++++++++++------
 .../r/test/builtins/TestBuiltin_deparse.java   |  3 +--
 .../r/test/builtins/TestBuiltin_dput.java      | 11 ++++++++---
 .../r/test/builtins/TestBuiltin_parse.java     |  2 +-
 5 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 0c3646dac6..40b677b713 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -930,7 +930,6 @@ public class RDeparse {
                                 break;
 
                             default: {
-                                opts = SIMPLEDEPARSE;
                                 if (attrName.contains(" ")) {
                                     append('"');
                                     append(attrName);
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 3c238793e1..e47c20c428 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
@@ -16992,7 +16992,7 @@ a[a <- TRUE]
 #argv <- list(0:12, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "0:12"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse38#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse38#
 #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "structure(list(c0 = structure(integer(0), .Label = character(0), class = \"factor\")), .Names = \"c0\", row.names = character(0), class = structure(\"integer(0)\", .Names = \"c0\"))"
 
@@ -19327,6 +19327,12 @@ Error in (function (x)  : object 'y' not found
 #argv <- list();do.call('double', argv)
 numeric(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput#
+#x <- structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor'), C = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor')), .Names = c('A', 'B', 'C'), row.names = 1:2, class = 'data.frame'); dput(x)
+structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c("G",
+"D"), class = "factor"), C = structure(c(1L, 1L), .Label = c("G",
+"D"), class = "factor")), .Names = c("A", "B", "C"), row.names = 1:2, class = "data.frame")
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput1#
 #argv <- list(logical(0), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))
 logical(0)
@@ -19347,7 +19353,7 @@ structure(numeric(0), .Dim = c(0L, 0L))
 #argv <- list(NULL, structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput6#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput6#
 #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))
 structure(list(c0 = structure(integer(0), .Label = character(0), class = "factor")), .Names = "c0", row.names = character(0), class = structure("integer(0)", .Names = "c0"))
 
@@ -39612,7 +39618,7 @@ expression(NULL)
 #.Internal(parse(stdin(), c(1,2), c('expr1', 'expr2'), '?', '<weird-text', 'unknown'))
 expression(expr1)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseDataFrame#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_parse.testParseDataFrame#
 #eval(parse(text=deparse(data.frame(x=c(1)))))
   x
 1 1
@@ -41014,7 +41020,7 @@ x3  0.81       -0.97
 - x2    1     26.79  74.76 28.742
 - x1    1    820.91 868.88 60.629
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault3#
 #argv <- list(structure(c('1', '2', '\\b', '4', '5', '\\040', '\\x20', 'c:\\spencer\\tests', '\\t', '\\n', '\\r'), .Dim = c(11L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'), 'TEST')), NULL, FALSE, NULL, NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
                  TEST
 1                   1
@@ -41061,7 +41067,7 @@ c  535  595  655  715
 #argv <- list(quote(y ~ A:U + A:V - 1), NULL, TRUE, NULL, NULL, FALSE, NULL, TRUE, TRUE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 y ~ A:U + A:V - 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printdefault.testprintdefault7#
 #argv <- list(structure(c(NA, NA, NA, 'a', NA, NA, 'b', 'd', NA, '10', '12', '14'), .Dim = 3:4), NULL, TRUE, '----', NULL, TRUE, NULL, TRUE, FALSE); .Internal(print.default(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
      [,1] [,2] [,3] [,4]
 [1,] ----  "a"  "b" "10"
@@ -138678,7 +138684,7 @@ Levels: 2147483648L
 #typeof(type.convert('2147483648L'))
 [1] "integer"
 
-##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.utils.TestTypeConvert.testFirstTypeMustBeOfModeTest#
 #type.convert('NA', 1)
 Error in type.convert("NA", 1) : invalid 'na.strings' argument
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
index 70eb09d783..c06c60fb9a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
@@ -215,8 +215,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse38() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        assertEval("argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java
index 0ee4403023..69579bb31d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dput.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -44,8 +44,7 @@ public class TestBuiltin_dput extends TestBase {
 
     @Test
     public void testdput6() {
-        assertEval(Ignored.Unimplemented,
-                        "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -57,4 +56,10 @@ public class TestBuiltin_dput extends TestBase {
     public void testdput8() {
         assertEval("argv <- list(c(0.00508571428571428, 0.876285714285715), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))");
     }
+
+    @Test
+    public void testdput() {
+        assertEval(Output.IgnoreWhitespace,
+                        "x <- structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor'), C = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor')), .Names = c('A', 'B', 'C'), row.names = 1:2, class = 'data.frame'); dput(x)");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java
index bee6607ab3..62df580491 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_parse.java
@@ -36,7 +36,7 @@ public class TestBuiltin_parse extends TestBase {
 
     @Test
     public void testParseDataFrame() {
-        assertEval(Ignored.ImplementationError, "eval(parse(text=deparse(data.frame(x=c(1)))))");
+        assertEval("eval(parse(text=deparse(data.frame(x=c(1)))))");
     }
 
     @Test
-- 
GitLab


From 542a56bea8fee89538d61a197b129711ef170bbd Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Feb 2017 15:46:42 +0100
Subject: [PATCH 039/402] use TypeOfNode.getTypeOf in more places

---
 .../r/nodes/builtin/base/DuplicatedFunctions.java     | 11 ++++++-----
 .../oracle/truffle/r/nodes/access/AccessSlotNode.java |  9 ++-------
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
index 79f201063c..066f216726 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
@@ -47,9 +47,7 @@ public class DuplicatedFunctions {
 
         protected static void casts(Casts casts) {
             // these are similar to those in DuplicatedFunctions.java
-            casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.SHOW_CALLER,
-                            RError.Message.APPLIES_TO_VECTORS,
-                            "duplicated()").asVector();
+            casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.SHOW_CALLER, RError.Message.APPLIES_TO_VECTORS, "duplicated()").asVector();
             // not much more can be done for incomparables as it is either a vector of incomparable
             // values or a (single) logical value
             casts.arg("incomparables").asVector(true);
@@ -76,6 +74,9 @@ public class DuplicatedFunctions {
             if (castTypeNode == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 castTypeNode = insert(CastTypeNodeGen.create(null, null));
+            }
+            if (typeof == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 typeof = insert(TypeofNodeGen.create());
             }
         }
@@ -150,12 +151,12 @@ public class DuplicatedFunctions {
         }
 
         @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"})
+        @TruffleBoundary
         protected int anyDuplicatedTrueIncomparables(RAbstractVector x, Object incomparables, @SuppressWarnings("unused") byte fromLast) {
             initChildren();
-            RType xType = typeof.execute(x);
             // TODO: this is not quite correct, as passing expression generated some obscure error
             // message, but is it worth fixing
-            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, ((RTypedValue) incomparables).getRType().getName(), xType.getName());
+            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, TypeofNode.getTypeof(incomparables).getName(), TypeofNode.getTypeof(x).getName());
         }
 
         @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
index 2a5d3799e8..dd7b46a4b9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
@@ -24,7 +24,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClass
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
-import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -49,7 +48,6 @@ public abstract class AccessSlotNode extends RBaseNode {
     public abstract Object executeAccess(Object o, String name);
 
     @Child private ClassHierarchyNode classHierarchy;
-    @Child private TypeofNode typeofNode;
 
     private final BranchProfile noSlot = BranchProfile.create();
     private final BranchProfile symbolValue = BranchProfile.create();
@@ -83,13 +81,10 @@ public abstract class AccessSlotNode extends RBaseNode {
                 return RNull.instance;
             }
 
+            CompilerDirectives.transferToInterpreter();
             RStringVector classAttr = getClassNode.getClassAttr(object);
             if (classAttr == null) {
-                if (typeofNode == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    typeofNode = insert(TypeofNodeGen.create());
-                }
-                throw RError.error(this, RError.Message.SLOT_CANNOT_GET, name, typeofNode.execute(object).getName());
+                throw RError.error(this, RError.Message.SLOT_CANNOT_GET, name, TypeofNode.getTypeof(object).getName());
             } else {
                 throw RError.error(this, RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0));
             }
-- 
GitLab


From b0017d3a081ff90a592a595afedee6e5a7af7603 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Tue, 21 Feb 2017 17:57:16 +0100
Subject: [PATCH 040/402] Builtin diagnostics uses cast pipelines intermediary
 representation (CP-IR)

---
 .../nodes/builtin/base/BrowserFunctions.java  |  16 +-
 .../r/nodes/builtin/base/FileFunctions.java   |   4 +-
 .../r/nodes/builtin/CastBuilderTest.java      |  26 +-
 .../builtin/ResultTypesAnalyserTest.java      | 489 ++++++++++++++++
 .../r/nodes/builtin/SampleCollectorTest.java  | 534 ++++++++++++++++++
 .../truffle/r/nodes/builtin/TypeExprTest.java |  38 +-
 .../r/nodes/casts/ArgumentFilterSampler.java  | 339 -----------
 .../r/nodes/casts/ArgumentMapperSampler.java  |  33 --
 .../r/nodes/casts/CastNodeSampler.java        | 104 ----
 .../truffle/r/nodes/casts/CastUtils.java      | 123 +++-
 .../r/nodes/casts/FilterSamplerFactory.java   | 478 ----------------
 .../r/nodes/casts/MapperSamplerFactory.java   |  95 ----
 .../truffle/r/nodes/casts/MarkLookup.java     | 250 ++++++++
 .../com/oracle/truffle/r/nodes/casts/Not.java |  28 +-
 .../r/nodes/casts/ResultTypesAnalyser.java    | 453 +++++++++++++++
 .../oracle/truffle/r/nodes/casts/Samples.java |  43 +-
 .../r/nodes/casts/SamplesCollector.java       | 478 ++++++++++++++++
 .../r/nodes/casts/TypeAndInstanceCheck.java   |  68 ++-
 .../r/nodes/casts/TypeConjunction.java        | 116 ----
 .../truffle/r/nodes/casts/TypeExpr.java       | 221 ++++++--
 .../TypePredicateArgumentFilterSampler.java   |  85 ---
 .../r/nodes/casts/UpperBoundsConjunction.java | 211 +++++++
 .../ValuePredicateArgumentFilterSampler.java  |  86 ---
 .../ValuePredicateArgumentMapperSampler.java  |  90 ---
 .../VectorPredicateArgumentFilterSampler.java |  82 ---
 .../truffle/r/nodes/test/ChimneySweeping.java |  47 +-
 .../truffle/r/nodes/test/ExtBuiltinsList.java | 110 ++++
 .../r/nodes/test/RBuiltinDiagnostics.java     | 470 +++++++++++----
 .../r/nodes/unary/BypassNodeGenSampler.java   |  77 ---
 .../unary/CastToVectorNodeGenSampler.java     |  70 ---
 .../r/nodes/unary/ChainedCastNodeSampler.java |  56 --
 .../unary/ConditionalMapNodeGenSampler.java   |  90 ---
 .../r/nodes/unary/FilterNodeGenSampler.java   |  66 ---
 .../nodes/unary/FindFirstNodeGenSampler.java  | 131 -----
 .../truffle/r/nodes/unary/MapNodeSampler.java |  50 --
 .../r/nodes/unary/NonNANodeGenSampler.java    |  85 ---
 .../r/nodes/binary/BoxPrimitiveNode.java      |  12 +-
 .../truffle/r/nodes/builtin/CastBuilder.java  |  10 +
 .../nodes/builtin/NodeWithArgumentCasts.java  |  50 +-
 .../builtin/casts/ExecutionPathVisitor.java   |  70 +++
 .../truffle/r/nodes/builtin/casts/Filter.java | 183 +++---
 .../truffle/r/nodes/builtin/casts/Mapper.java |  28 +-
 .../r/nodes/builtin/casts/PipelineStep.java   |  68 +--
 .../builtin/casts/PipelineToCastNode.java     | 130 ++---
 .../analysis/ForwardedValuesAnalyser.java     |  78 +--
 .../casts/fluent/InitialPhaseBuilder.java     |   8 +-
 .../builtin/casts/fluent/PipelineBuilder.java |   2 +-
 .../r/nodes/unary/CastComplexNode.java        |   6 +
 .../truffle/r/nodes/unary/CastNode.java       |   6 +-
 .../truffle/r/nodes/unary/CastRawNode.java    |   6 +
 .../r/nodes/unary/CastToAttributableNode.java |   6 +-
 .../r/runtime/conn/FileConnections.java       |   2 -
 .../truffle/r/runtime/data/RExpression.java   |   2 +-
 53 files changed, 3725 insertions(+), 2684 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java
 create mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java
 delete mode 100644 com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java
 create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
index 2e2226c339..063f35a81e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
@@ -101,8 +101,8 @@ public class BrowserFunctions {
 
     private abstract static class RetrieveAdapter extends RBuiltinNode {
 
-        static {
-            Casts casts = new Casts(RetrieveAdapter.class);
+        protected static void casts(Class<? extends RetrieveAdapter> builtinClass) {
+            Casts casts = new Casts(builtinClass);
             casts.arg("n").asIntegerVector().findFirst(0).mustBe(gt(0), Message.POSITIVE_CONTEXTS);
         }
 
@@ -118,6 +118,10 @@ public class BrowserFunctions {
     @RBuiltin(name = "browserText", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
     public abstract static class BrowserText extends RetrieveAdapter {
 
+        static {
+            casts(BrowserText.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object browserText(int n) {
@@ -128,6 +132,10 @@ public class BrowserFunctions {
     @RBuiltin(name = "browserCondition", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
     public abstract static class BrowserCondition extends RetrieveAdapter {
 
+        static {
+            casts(BrowserCondition.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object browserCondition(int n) {
@@ -138,6 +146,10 @@ public class BrowserFunctions {
     @RBuiltin(name = "browserSetDebug", visibility = OFF, kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
     public abstract static class BrowserSetDebug extends RetrieveAdapter {
 
+        static {
+            casts(BrowserSetDebug.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RNull browserSetDebug(@SuppressWarnings("unused") int n) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index 5534dd4505..63faccad5a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -425,8 +425,8 @@ public class FileFunctions {
 
     private abstract static class FileLinkAdaptor extends RBuiltinNode {
 
-        static {
-            Casts casts = new Casts(FileLinkAdaptor.class);
+        protected static void casts(Class<? extends FileLinkAdaptor> builtinClass) {
+            Casts casts = new Casts(builtinClass);
             casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector();
             casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector();
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
index 24e9d47732..9e37d05542 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asBoolean;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asInteger;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector;
@@ -80,14 +80,9 @@ import org.junit.Before;
 import org.junit.Test;
 
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.FilterSamplerFactory;
-import com.oracle.truffle.r.nodes.casts.MapperSamplerFactory;
 import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
 import com.oracle.truffle.r.nodes.test.TestUtilities;
 import com.oracle.truffle.r.nodes.test.TestUtilities.NodeHandle;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -130,10 +125,6 @@ public class CastBuilderTest {
     private PreinitialPhaseBuilder arg;
 
     static {
-        if (TEST_SAMPLING) {
-            PipelineConfig.setFilterFactory(FilterSamplerFactory.INSTANCE);
-            PipelineConfig.setMapperFactory(MapperSamplerFactory.INSTANCE);
-        }
         CastNode.testingMode();
     }
 
@@ -886,6 +877,7 @@ public class CastBuilderTest {
      * Casts given object using the configured pipeline in {@link #arg}.
      */
     private Object cast(Object a) {
+        CastNode.clearLastWarning();
         NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.execute(args[0]));
         return argCastNodeHandle.call(a);
     }
@@ -940,22 +932,12 @@ public class CastBuilderTest {
         testPipeline(false);
     }
 
-    private TypeExpr resultTypes() {
-        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(getCastNode());
-        return sampler.resultTypes();
-    }
-
     private void testPipeline(boolean emptyPositiveSamplesAllowed) {
         if (!TEST_SAMPLING) {
             return;
         }
 
-        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(getCastNode());
-        Samples<?> samples = sampler.collectSamples();
-        if (!emptyPositiveSamplesAllowed) {
-            Assert.assertFalse(samples.positiveSamples().isEmpty());
-        }
-        testPipeline(samples);
+        // TODO:
     }
 
     private CastNode getCastNode() {
@@ -992,6 +974,6 @@ public class CastBuilderTest {
      * Just so that we do not have to build the annotation instance by hand.
      */
     @RBuiltin(kind = RBuiltinKind.PRIMITIVE, name = "forTestingOnly", parameterNames = {"x"}, behavior = RBehavior.PURE)
-    private static class DummyBuiltin {
+    static class DummyBuiltin {
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
new file mode 100644
index 0000000000..8e06ec8734
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleToInt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFractional;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom;
+import static com.oracle.truffle.r.nodes.casts.MarkLookup.mark;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.oracle.truffle.r.nodes.builtin.CastBuilderTest.DummyBuiltin;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
+import com.oracle.truffle.r.nodes.casts.MarkLookup;
+import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser;
+import com.oracle.truffle.r.nodes.casts.TypeExpr;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDouble;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RString;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public class ResultTypesAnalyserTest {
+
+    private CastBuilder cb;
+    private PreinitialPhaseBuilder arg;
+
+    @Before
+    public void setUp() {
+        MarkLookup.clear();
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
+        arg = cb.arg("x");
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    @Test
+    public void testAsDoubleVector() {
+        arg.asDoubleVector();
+        assertTypes(RNull.class, RMissing.class, double.class, RDoubleSequence.class, RDoubleVector.class);
+    }
+
+    @Test
+    public void testAsIntegerVector() {
+        arg.asIntegerVector();
+        assertTypes(RNull.class, RMissing.class, int.class, RIntSequence.class, RIntVector.class);
+    }
+
+    @Test
+    public void testAsLogicalVector() {
+        arg.asLogicalVector();
+        assertTypes(RNull.class, RMissing.class, byte.class, RLogicalVector.class,
+                        RArgsValuesAndNames.class);
+    }
+
+    @Test
+    public void testAsStringVector() {
+        arg.asStringVector();
+        assertTypes(RNull.class, RMissing.class, String.class, RStringVector.class);
+    }
+
+    @Test
+    public void testAsRawVector() {
+        arg.asRawVector();
+        assertTypes(RNull.class, RMissing.class, RRaw.class, RRawVector.class);
+    }
+
+    @Test
+    public void testAsComplexVector() {
+        arg.asComplexVector();
+        assertTypes(RNull.class, RMissing.class, RComplex.class, RComplexVector.class);
+    }
+
+    @Test
+    public void testAsVectorPreserveNonVector() {
+        arg.asVector(true);
+        assertTypes(RFunction.class, RNull.class, RMissing.class, RAbstractVector.class);
+    }
+
+    @Test
+    public void testAsVectorVectorNoPreserveNonVector() {
+        arg.asVector(false);
+        assertTypes(RAbstractVector.class, RFunction.class);
+    }
+
+    @Test
+    public void testAsAttributableVector() {
+        arg.asAttributable(false, false, false);
+        assertTypes(RNull.class, RMissing.class, RAttributable.class);
+    }
+
+    @Test
+    public void testBoxPrimitive() {
+        arg.boxPrimitive();
+        TypeExpr expected = TypeExpr.union(RNull.class, RMissing.class, RInteger.class, RLogical.class,
+                        RDouble.class, RString.class);
+        expected = expected.or(expected.not());
+        assertTypes(expected);
+    }
+
+    @Test
+    public void testFindFirst() {
+        arg.asStringVector().findFirst();
+        assertTypes(String.class);
+    }
+
+    @Test
+    public void testFindFirstOrNull() {
+        arg.asStringVector().findFirstOrNull();
+        assertTypes(RNull.class, String.class);
+    }
+
+    @Test
+    public void testFindFirstAfterGenericVector() {
+        arg.asVector().findFirst();
+        assertTypes(atom(RFunction.class).or(atom(RNull.class).or(atom(RMissing.class)).not()));
+    }
+
+    @Test
+    public void testMapToValue() {
+        arg.map(mark(constant(1), "m"));
+        assertTypes(atom(Integer.class).lower(m("m")));
+    }
+
+    @Test
+    public void testMapByteToBoolean() {
+        arg.mustBe(atomicLogicalValue()).map(toBoolean());
+        assertTypes(Boolean.class);
+    }
+
+    @Test
+    public void testMapDoubleToInt() {
+        arg.mustBe(instanceOf(Double.class)).map(doubleToInt());
+        assertTypes(Integer.class);
+    }
+
+    @Test
+    public void testMapToCharAt() {
+        arg.mustBe(instanceOf(String.class)).map(charAt0('A'));
+        assertTypes(Integer.class);
+    }
+
+    @Test
+    public void testTypeFilter() {
+        arg.mustBe(instanceOf(RString.class));
+        assertTypes(RString.class);
+    }
+
+    @Test
+    public void testTypeFilterInSeries() {
+        arg.mustBe(instanceOf(RAbstractVector.class)).mustBe(instanceOf(RString.class));
+        assertTypes(RString.class);
+    }
+
+    @Test
+    public void testRTypeFilter() {
+        arg.mustBe(integerValue());
+        assertTypes(Integer.class, RAbstractIntVector.class);
+    }
+
+    @Test
+    public void testCompareScalarValueFilter() {
+        arg.mustBe(atomicIntegerValue()).mustBe(mark(eq(1), "x"));
+        assertWildTypes("x", Integer.class);
+    }
+
+    @Test
+    public void testCompareNAValueFilter() {
+        arg.mustBe(atomicIntegerValue()).mustBe(mark(intNA(), "x"));
+        assertWildTypes("x", Integer.class);
+    }
+
+    @Test
+    public void testCompareStringLengthFilter() {
+        arg.mustBe(instanceOf(String.class)).mustBe(mark(length(1), "x"));
+        assertWildTypes("x", String.class);
+    }
+
+    @Test
+    public void testCompareVectorSizeFilter() {
+        arg.mustBe(instanceOf(RStringVector.class)).mustBe(mark(size(1), "x"));
+        assertWildTypes("x", RStringVector.class);
+    }
+
+    @Test
+    public void testCompareElementAtFilter() {
+        arg.mustBe(instanceOf(RStringVector.class)).mustBe(mark(elementAt(1, "abc"), "x"));
+        assertWildTypes("x", RStringVector.class);
+    }
+
+    @Test
+    public void testCompareDimFilter() {
+        arg.mustBe(instanceOf(RStringVector.class)).mustBe(mark(dimEq(1, 2), "x"));
+        assertWildTypes("x", RStringVector.class);
+    }
+
+    @Test
+    public void testAndFilter1() {
+        arg.mustBe(instanceOf(RStringVector.class).and(mark(elementAt(1, "abc"), "x")));
+        assertWildTypes("x", RStringVector.class);
+    }
+
+    @Test
+    public void testAndFilter2() {
+        arg.mustBe(instanceOf(RStringVector.class).and(mark(elementAt(1, "abc"), "x1")).and(mark(size(10), "x2")));
+        assertTypes(atom(RStringVector.class).lower(m("x1")).and(atom(RStringVector.class).lower(m("x2"))));
+    }
+
+    @Test
+    public void testAndAsNegationOfOrFilter() {
+        // !(!A || !B) = A && B
+        arg.mustBe(instanceOf(RAbstractStringVector.class).not().or(instanceOf(RAbstractIntVector.class).not()).not());
+        assertTypes(atom(RAbstractStringVector.class).and(atom(RAbstractIntVector.class)));
+    }
+
+    @Test
+    public void testAndAsNegationOfOrFilter2() {
+        // !(!A || !B) = A && B
+        arg.mustBe(instanceOf(RStringVector.class).not().or(instanceOf(RIntVector.class).not()).not());
+        // A and B are mutually exclusive, thus their conjunction is empty
+        assertTypes(TypeExpr.NOTHING);
+    }
+
+    @Test
+    public void testOrFilter1() {
+        arg.mustBe(instanceOf(RStringVector.class).or(nullValue()));
+        assertTypes(RStringVector.class, RNull.class);
+    }
+
+    @Test
+    public void testOrFilter2() {
+        arg.mustBe(instanceOf(RStringVector.class).or(instanceOf(RIntVector.class).not()));
+        assertTypes(atom(RStringVector.class).or(atom(RIntVector.class).not()));
+    }
+
+    @Test
+    public void testNotOrFilter() {
+        arg.mustBe(instanceOf(String.class).or(instanceOf(Integer.class)).not());
+        assertTypes(atom(String.class).not().and(atom(Integer.class).not()));
+    }
+
+    @Test
+    public void testOrAsNegationOfAndFilter() {
+        // !(!A && !B) = A || B
+        arg.mustBe(instanceOf(String.class).not().and(instanceOf(Integer.class).not()).not());
+        assertTypes(atom(String.class).or(atom(Integer.class)));
+    }
+
+    @Test
+    public void testNotFilter1() {
+        arg.mustBe(instanceOf(RStringVector.class).not());
+        assertTypes(atom(RStringVector.class).not());
+    }
+
+    @Test
+    public void testNotFilter2() {
+        // !(x instanceof RStringVector && "abc".equals(x[1]))
+        arg.mustBe(instanceOf(RStringVector.class).and(mark(elementAt(1, "abc"), "x")).not());
+        assertTypes(atom(RStringVector.class).lower(m("x")).not());
+    }
+
+    @Test
+    public void testNotFilter3() {
+        // !(x instanceof RStringVector) && (x instanceof RAbstractStringVector)
+        arg.mustBe(instanceOf(RStringVector.class).not()).mustBe(instanceOf(RAbstractStringVector.class));
+        assertTypes(atom(RAbstractStringVector.class).and(atom(RStringVector.class).not()));
+    }
+
+    @Test
+    public void testNotFilter4() {
+        arg.mustBe(instanceOf(RAbstractStringVector.class)).mustBe(mark(elementAt(1, "abc"), "x").not());
+        assertTypes(atom(RAbstractStringVector.class).and(atom(RAbstractStringVector.class).lower(m("x")).not()));
+    }
+
+    @Test
+    public void testMatrixFilter() {
+        arg.mustBe(instanceOf(RStringVector.class).and(mark(matrix(), "m")));
+        assertTypes(atom(RStringVector.class).lower(m("m")));
+    }
+
+    @Test
+    public void testDoubleFilter() {
+        arg.mustBe(instanceOf(Double.class).and(mark(isFractional(), "x")));
+        assertTypes(atom(Double.class).lower(m("x")));
+    }
+
+    @Test
+    public void testNullFilter() {
+        arg.mustBe(nullValue().or(stringValue()));
+        assertTypes(TypeExpr.union(RNull.class, RAbstractStringVector.class, String.class));
+    }
+
+    @Test
+    public void testMissingFilter() {
+        arg.mustBe(missingValue().or(stringValue()));
+        assertTypes(TypeExpr.union(RMissing.class, RAbstractStringVector.class, String.class));
+    }
+
+    @Test
+    public void testNonNA() {
+        arg.mustBe(atomicIntegerValue()).notNA(RError.Message.GENERIC, "abc");
+        // the type representation of the wildcard result type is the nonNA step
+        PipelineStep<?, ?> notNAStep = cb.getPipelineBuilders()[0].getFirstStep().getNext();
+        assertTypes(atom(Integer.class).lower(notNAStep));
+    }
+
+    @Test
+    public void testCoerceToAttributable() {
+        arg.asAttributable(false, false, false);
+        assertTypes(TypeExpr.union(RAttributable.class, RNull.class, RMissing.class));
+    }
+
+    @Test
+    public void testMapIf() {
+        arg.mapIf(nullValue(), mark(constant(1), "m"));
+        assertTypes(atom(Integer.class).lower(m("m")).or(atom(RNull.class).not()));
+    }
+
+    @Test
+    public void testMapIf2() {
+        arg.mapIf(nullValue(), mark(constant(1), "m1"), mark(constant("abc"), "m2"));
+        assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1"))));
+    }
+
+    @Test
+    public void testMapIf3() {
+        PipelineStep<?, ?> m1 = chain(map(mark(constant(1), "m1"))).end();
+        PipelineStep<?, ?> m2 = chain(map(mark(constant("abc"), "m2"))).end();
+        arg.mapIf(nullValue(), m1, m2);
+        assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1"))));
+    }
+
+    @Test
+    public void testMapIf4() {
+        PipelineStep<?, ?> m1 = chain(map(mark(constant(1), "m1"))).end();
+        PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(mark(constant("abc"), "m2"))).end())).end();
+        arg.mapIf(nullValue(), m1, m2);
+        assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1")).or(atom(RNull.class).not().and(atom(Double.class).not()))));
+    }
+
+    @Test
+    public void testMapIf5() {
+        PipelineStep<?, ?> m1 = chain(map(mark(constant(1), "m1"))).end();
+        PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(mark(constant("abc"), "m2"))).end())).end();
+        arg.mapIf(nullValue(), m1, m2).mapIf(instanceOf(String.class).and(mark(length(10), "m4")), mark(constant((byte) 0), "m3"));
+        //@formatter:off
+        assertTypes(
+                        atom(Byte.class).lower(m("m3")).
+                            or(atom(Integer.class).lower(m("m1"))).
+                            or(atom(String.class).lower(m("m2")).and(atom(String.class).lower(m("m4")).not())).
+                            or(atom(Double.class).not().and(atom(RNull.class).not()).and(atom(String.class).lower(m("m4")).not())));
+        //@formatter:on
+    }
+
+    @Test
+    public void testReturnIf() {
+        arg.mapIf(nullValue(), mark(constant(1), "m1"), mark(constant("abc"), "m2"));
+        assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1"))));
+    }
+
+    @Test
+    public void testTwoWildcardTypes() {
+        arg.mustBe((instanceOf(String.class).and(mark(length(10), "l10").or(mark(length(20), "l20")))));
+        assertTypes(atom(String.class).lower(m("l10")).or(atom(String.class).lower(m("l20"))));
+    }
+
+    private static Function<RAbstractDoubleVector, Object> getDimVal(int dim) {
+        return vec -> vec.getDimensions()[dim];
+    }
+
+    @Test
+    public void testAnalyseRealPipeline() {
+        arg.mustBe(numericValue()).asVector().mustBe(matrix(), RError.ROOTNODE, RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), RError.ROOTNODE,
+                        RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.ROOTNODE, RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
+        assertTypes(TypeExpr.union(RAbstractDoubleVector.class, RAbstractIntVector.class, RAbstractLogicalVector.class), true);
+    }
+
+    // utilities
+
+    private void assertWildTypes(String mark, Class<?>... expectedTypes) {
+        TypeExpr expected = TypeExpr.union(expectedTypes).lower(m(mark));
+        assertTypes(expected);
+    }
+
+    private void assertTypes(Class<?>... expectedTypes) {
+        TypeExpr expected = TypeExpr.union(expectedTypes);
+        assertTypes(expected);
+    }
+
+    private void assertTypes(TypeExpr expectedType) {
+        assertTypes(expectedType, false);
+    }
+
+    private void assertTypes(TypeExpr expectedType, boolean removeWildcards) {
+        PipelineStep<?, ?> firstStep = cb.getPipelineBuilders()[0].getFirstStep();
+        TypeExpr actualType = ResultTypesAnalyser.analyse(firstStep);
+        Set<Type> actualNorm = removeWildcards ? actualType.normalize().removeWildcards().toNormalizedConjunctionSet() : actualType.toNormalizedConjunctionSet();
+        Set<Type> expectedNorm = expectedType.toNormalizedConjunctionSet();
+        Assert.assertEquals(expectedNorm, actualNorm);
+    }
+
+    /**
+     * Look up the filter by its mark.
+     *
+     * @param mark the mark
+     * @return the filter
+     */
+    public Object m(String mark) {
+        Map<String, Object> result = MarkLookup.lookup(cb.getPipelineBuilders()[0].getFirstStep(), mark);
+        Assert.assertNotNull(result.get(mark));
+        return result.get(mark);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
new file mode 100644
index 0000000000..d2af2ddcde
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleToInt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFractional;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hamcrest.CustomMatcher;
+import org.hamcrest.Matcher;
+import org.hamcrest.core.IsNot;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.oracle.truffle.r.nodes.builtin.CastBuilderTest.DummyBuiltin;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
+import com.oracle.truffle.r.nodes.casts.SamplesCollector;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RString;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public class SampleCollectorTest {
+
+    private CastBuilder cb;
+    private PreinitialPhaseBuilder arg;
+
+    @Before
+    public void setUp() {
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
+        arg = cb.arg("x");
+    }
+
+    @After
+    public void tearDown() {
+    }
+
+    @Test
+    public void testAsDoubleVector() {
+        arg.asDoubleVector();
+        assertSamples(0.0, Double.NaN, RRuntime.DOUBLE_NA, vector(RType.Double, 0.0), vector(RType.Double, RRuntime.DOUBLE_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAsIntegerVector() {
+        arg.asIntegerVector();
+        assertSamples(0, RRuntime.INT_NA, vector(RType.Integer, 0), vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAsLogicalVector() {
+        arg.asLogicalVector();
+        assertAsLogicalVectorSamples();
+    }
+
+    private void assertAsLogicalVectorSamples() {
+        assertSamples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA, RRuntime.LOGICAL_TRUE, vector(RType.Logical, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA, RRuntime.LOGICAL_TRUE), RNull.instance,
+                        RMissing.instance);
+    }
+
+    @Test
+    public void testAsStringVector() {
+        arg.asStringVector();
+        assertAsStringVectorSamples();
+    }
+
+    private void assertAsStringVectorSamples() {
+        assertSamples("", RRuntime.STRING_NA, vector(RType.Character, ""), vector(RType.Character), vector(RType.Character, RRuntime.STRING_NA), RNull.instance,
+                        RMissing.instance);
+    }
+
+    @Test
+    public void testAsRawVector() {
+        arg.asRawVector();
+        assertSamples((byte) 0, vector(RType.Raw, RDataFactory.createRaw((byte) 0)), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAsComplexVector() {
+        arg.asComplexVector();
+        RComplex na = RComplex.createNA();
+        RComplex z = RDataFactory.createComplex(0, 0);
+        assertSamples(z, na, vector(RType.Complex, z), vector(RType.Complex, na), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAsVectorPreserveNonVector() {
+        arg.asVector(true);
+        assertSamples();
+    }
+
+    @Test
+    public void testAsVectorVectorNoPreserveNonVector() {
+        arg.asVector(false);
+        assertSamples();
+    }
+
+    @Test
+    public void testAsAttributableVector() {
+        arg.asAttributable(false, false, false);
+        assertSamples();
+    }
+
+    @Test
+    public void testBoxPrimitive() {
+        arg.boxPrimitive();
+        assertSamples();
+    }
+
+    @Test
+    public void testFindFirst() {
+        arg.asStringVector().findFirst();
+        assertAsStringVectorSamples();
+    }
+
+    @Test
+    public void testFindFirstOrNull() {
+        arg.asStringVector().findFirstOrNull();
+        assertAsStringVectorSamples();
+    }
+
+    @Test
+    public void testFindFirstAfterGenericVector() {
+        arg.asVector().findFirst();
+        assertSamples();
+    }
+
+    @Test
+    public void testMapToValue() {
+        arg.map(constant(1));
+        assertSamples(RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMapByteToBoolean() {
+        arg.mustBe(atomicLogicalValue()).map(toBoolean());
+        assertSamples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA, RRuntime.LOGICAL_TRUE, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMapDoubleToInt() {
+        arg.mustBe(instanceOf(Double.class)).map(doubleToInt());
+        assertSamples(0.0, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMapToCharAt() {
+        arg.mustBe(instanceOf(String.class)).map(charAt0('A'));
+        assertSamples("A", RRuntime.STRING_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testTypeFilter() {
+        arg.mustBe(instanceOf(String.class));
+        assertSamples("", RRuntime.STRING_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testTypeFilterInSeries() {
+        arg.mustBe(instanceOf(RAbstractVector.class)).mustBe(instanceOf(RString.class));
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testRTypeFilter() {
+        arg.mustBe(integerValue());
+        assertSamples(0, RRuntime.INT_NA, vector(RType.Integer, 0), vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testCompareScalarValueFilter() {
+        arg.mustBe(atomicIntegerValue()).mustBe(eq(100));
+        assertSamples(100, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testCompareNAValueFilter() {
+        arg.mustBe(atomicIntegerValue()).mustBe(intNA());
+        assertSamples(RRuntime.INT_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testCompareStringLengthFilter() {
+        arg.mustBe(instanceOf(String.class)).mustBe(length(5));
+        assertSamples(stringOfLength(5), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testCompareVectorSizeFilter() {
+        arg.mustBe(instanceOf(RStringVector.class)).mustBe(size(10));
+        assertSamples(vectorOfSize(RType.Character, 10), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testCompareElementAtFilter() {
+        arg.mustBe(instanceOf(RStringVector.class)).mustBe(elementAt(3, "abc"));
+        assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "abc"), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testCompareDimFilter() {
+        arg.mustBe(instanceOf(RStringVector.class)).mustBe(dimEq(1, 2));
+        assertSamples(RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAndFilter1() {
+        arg.mustBe(instanceOf(RStringVector.class).and(elementAt(3, "xyz")));
+        assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAndFilter2() {
+        arg.mustBe(instanceOf(RStringVector.class).and(elementAt(3, "xyz")).and(size(10)));
+        assertSamples(vectorOfSize(RType.Character, 10), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAndAsNegationOfOrFilter() {
+        // !(!A || !B) = A && B
+        arg.mustBe(instanceOf(RAbstractStringVector.class).not().or(instanceOf(RAbstractIntVector.class).not()).not());
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0),
+                        vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testAndAsNegationOfOrFilter2() {
+        // !(!A || !B) = A && B
+        arg.mustBe(instanceOf(RStringVector.class).not().or(instanceOf(RIntVector.class).not()).not());
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0),
+                        vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testOrFilter1() {
+        arg.mustBe(instanceOf(RStringVector.class).or(nullValue()));
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testOrFilter2() {
+        arg.mustBe(instanceOf(RStringVector.class).or(instanceOf(RIntVector.class).not()));
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0),
+                        vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testNotOrFilter() {
+        arg.mustBe(instanceOf(RStringVector.class).or(instanceOf(RIntVector.class)).not());
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0),
+                        vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testOrAsNegationOfAndFilter() {
+        // !(!A && !B) = A || B
+        arg.mustBe(instanceOf(RAbstractStringVector.class).not().and(instanceOf(RAbstractIntVector.class).not()).not());
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), vector(RType.Integer, 0),
+                        vector(RType.Integer, RRuntime.INT_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testNotFilter1() {
+        arg.mustBe(instanceOf(RStringVector.class).not());
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testNotFilter2() {
+        // !(x instanceof RStringVector && "abc".equals(x[1]))
+        arg.mustBe(instanceOf(RStringVector.class).and(elementAt(3, "xyz")).not());
+        assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testNotFilter3() {
+        // !(x instanceof RStringVector) && (x instanceof RAbstractStringVector)
+        arg.mustBe(instanceOf(RStringVector.class).not()).mustBe(instanceOf(RAbstractStringVector.class));
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testNotFilter4() {
+        arg.mustBe(instanceOf(RAbstractStringVector.class)).mustBe(elementAt(3, "xyz").not());
+        assertSamples(vectorOfSize(RType.Character, 4), vector(RType.Character, "xyz"), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMatrixFilter() {
+        arg.mustBe(instanceOf(RStringVector.class).and(matrix()));
+        assertSamples(vector(RType.Character, ""), vector(RType.Character, nonEmptyString()), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testDoubleFilter() {
+        arg.mustBe(instanceOf(Double.class).and(isFractional()));
+        assertSamples(0.0, Double.NaN, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testNullFilter() {
+        arg.mustBe(nullValue().or(stringValue()));
+        assertSamples("", RRuntime.STRING_NA, vector(RType.Character, ""), vector(RType.Character, RRuntime.STRING_NA), RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMissingFilter() {
+        arg.mustBe(missingValue().or(stringValue()));
+        assertAsStringVectorSamples();
+    }
+
+    @Test
+    public void testNonNA() {
+        arg.mustBe(atomicIntegerValue()).notNA(RError.Message.GENERIC, "abc");
+        assertSamples(RRuntime.STRING_NA);
+    }
+
+    @Test
+    public void testMapIf() {
+        arg.mapIf(nullValue(), constant(1));
+        assertSamples(RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMapIf2() {
+        arg.mapIf(nullValue(), constant(1), constant("abc"));
+        assertSamples(RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMapIf3() {
+        PipelineStep<?, ?> m1 = chain(map(constant(1))).end();
+        PipelineStep<?, ?> m2 = chain(map(constant("xyz"))).end();
+        arg.mapIf(stringValue(), m1, m2);
+        assertAsStringVectorSamples();
+    }
+
+    @Test
+    public void testMapIf4() {
+        PipelineStep<?, ?> m1 = chain(map(constant(1))).end();
+        PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(constant("abc"))).end())).end();
+        arg.mapIf(nullValue(), m1, m2);
+        assertSamples(0.0, Double.NaN, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testMapIf5() {
+        PipelineStep<?, ?> m1 = chain(map(constant(1))).end();
+        PipelineStep<?, ?> m2 = chain(mapIf(instanceOf(Double.class), chain(map(constant("abc"))).end())).end();
+        arg.mapIf(nullValue(), m1, m2).mapIf(instanceOf(String.class).and(length(10)), constant((byte) 0));
+        assertSamples("", RRuntime.STRING_NA, 0.0, Double.NaN, RRuntime.DOUBLE_NA, RNull.instance, RMissing.instance);
+    }
+
+    @Test
+    public void testReturnIf() {
+        arg.mapIf(nullValue(), constant(1), constant("abc"));
+        assertSamples(RNull.instance);
+    }
+
+    @Test
+    public void testTwoWildcardTypes() {
+        arg.mustBe((instanceOf(String.class).and(length(10).or(length(20)))));
+        assertSamples(stringOfLength(10), stringOfLength(20));
+    }
+
+    // utilities
+
+    @SuppressWarnings("unchecked")
+    void assertSamples(Object... expected) {
+        Set<Object> samples = collectSamples();
+        Assert.assertFalse(samples.isEmpty());
+        for (Object es : expected) {
+            if (es instanceof Matcher) {
+                Assert.assertThat(samples, (Matcher<Set<Object>>) es);
+            } else {
+                Assert.assertTrue("Samples must contain " + es, samples.contains(es));
+            }
+        }
+    }
+
+    Set<Object> collectSamples() {
+        return SamplesCollector.collect(cb.getPipelineBuilders()[0].getFirstStep());
+    }
+
+    static VectorMatcher vector(RType elemType, Object... expectedElements) {
+        return new VectorMatcher(elemType, expectedElements);
+    }
+
+    static Matcher<?> nonEmptyString() {
+        return new IsNot<>(new StringMatcher(0));
+    }
+
+    static Matcher<?> stringOfLength(int expectedLenght) {
+        return new StringMatcher(expectedLenght);
+    }
+
+    static Matcher<?> vectorOfSize(RType type, int expectedSize) {
+        return new VectorSizeMatcher(type, expectedSize);
+    }
+
+    static final class StringMatcher extends CustomMatcher<Set<Object>> {
+
+        final int expectedLength;
+
+        private StringMatcher(int expectedLength) {
+            super("String of length " + expectedLength + " expected");
+            this.expectedLength = expectedLength;
+        }
+
+        @Override
+        public boolean matches(Object item) {
+            @SuppressWarnings("unchecked")
+            Set<Object> samples = (Set<Object>) item;
+            return samples.stream().filter(s -> s instanceof String && s.toString().length() == expectedLength).findAny().isPresent();
+        }
+
+    }
+
+    static final class VectorSizeMatcher extends CustomMatcher<Set<Object>> {
+
+        final int expectedSize;
+        final RType type;
+
+        private VectorSizeMatcher(RType type, int expectedSize) {
+            super("Vector of size " + expectedSize + " expected");
+            this.type = type;
+            this.expectedSize = expectedSize;
+        }
+
+        @Override
+        public boolean matches(Object item) {
+            @SuppressWarnings("unchecked")
+            Set<Object> samples = (Set<Object>) item;
+            return samples.stream().filter(s -> s instanceof RAbstractVector && ((RAbstractVector) s).getRType() == type && ((RAbstractVector) s).getLength() == expectedSize).findAny().isPresent();
+        }
+
+    }
+
+    static final class VectorMatcher extends CustomMatcher<Set<Object>> {
+        final RType elemType;
+        final Object[] expectedElements;
+
+        VectorMatcher(RType elemType, Object... expectedElements) {
+            super("Expected " + elemType + " vector: " + Arrays.asList(expectedElements));
+            this.elemType = elemType;
+            this.expectedElements = expectedElements;
+        }
+
+        @Override
+        public boolean matches(Object item) {
+            @SuppressWarnings("unchecked")
+            Set<Object> samples = (Set<Object>) item;
+            return samples.stream().filter(s -> s instanceof RAbstractVector && elemType.equals(((RAbstractVector) s).getRType()) && contains((RAbstractVector) s)).findAny().isPresent();
+        }
+
+        boolean contains(RAbstractVector v) {
+            return Arrays.stream(expectedElements).allMatch(expected -> contains(v, expected));
+        }
+
+        static boolean contains(RAbstractVector v, Object expected) {
+            if (expected instanceof Matcher) {
+                Set<Object> vecAsSet = new HashSet<>();
+                for (int i = 0; i < v.getLength(); i++) {
+                    vecAsSet.add(v.getDataAtAsObject(i));
+                }
+                return ((Matcher<?>) expected).matches(vecAsSet);
+            } else {
+                for (int i = 0; i < v.getLength(); i++) {
+                    if (expected.equals(v.getDataAtAsObject(i))) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
index b6d7a40bdc..a016195821 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
@@ -36,11 +36,12 @@ import org.junit.Test;
 
 import com.oracle.truffle.r.nodes.casts.CastUtils;
 import com.oracle.truffle.r.nodes.casts.Not;
-import com.oracle.truffle.r.nodes.casts.TypeConjunction;
 import com.oracle.truffle.r.nodes.casts.TypeExpr;
+import com.oracle.truffle.r.nodes.casts.UpperBoundsConjunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSequence;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -48,14 +49,18 @@ public class TypeExprTest {
 
     @Test
     public void testNormalize() {
-        Assert.assertEquals(toSet(String.class), union(String.class).normalize());
-        Assert.assertEquals(toSet(String.class, Integer.class), union(String.class, Integer.class).normalize());
-        Assert.assertEquals(toSet(RIntSequence.class), atom(RIntSequence.class).and(atom(RSequence.class)).normalize());
-        Assert.assertEquals(toSet(String.class), atom(String.class).and(atom(RNull.class).not()).normalize());
-        Assert.assertEquals(toSet(TypeConjunction.create(negateType(String.class), negateType(Integer.class))),
-                        atom(String.class).not().and(atom(Integer.class).not()).normalize());
-        Assert.assertEquals(toSet(), atom(String.class).not().and(atom(String.class)).normalize());
-        Assert.assertEquals(toSet(TypeConjunction.create(RAbstractIntVector.class, RAbstractStringVector.class)), atom(RAbstractIntVector.class).and(atom(RAbstractStringVector.class)).normalize());
+        Assert.assertEquals(toSet(String.class), union(String.class).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(String.class, Integer.class), union(String.class, Integer.class).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(RIntSequence.class), atom(RIntSequence.class).and(atom(RSequence.class)).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(String.class), atom(String.class).and(atom(RNull.class).not()).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(UpperBoundsConjunction.create(negateType(String.class), negateType(Integer.class))),
+                        atom(String.class).not().and(atom(Integer.class).not()).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(), atom(String.class).not().and(atom(String.class)).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(UpperBoundsConjunction.create(Runnable.class, RAbstractStringVector.class)),
+                        atom(Runnable.class).and(atom(RAbstractStringVector.class)).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(RAbstractStringVector.class), atom(UpperBoundsConjunction.fromType(RAbstractStringVector.class)).toNormalizedConjunctionSet());
+        Assert.assertEquals(toSet(UpperBoundsConjunction.create(RAbstractStringVector.class, Runnable.class)),
+                        atom(UpperBoundsConjunction.fromType(Runnable.class)).and(atom(UpperBoundsConjunction.fromType(RAbstractStringVector.class))).toNormalizedConjunctionSet());
     }
 
     @Test
@@ -74,6 +79,21 @@ public class TypeExprTest {
         Assert.assertTrue(CastUtils.Casts.existsConvertibleActualType(from, Integer.class, false));
     }
 
+    @Test
+    public void testLower() {
+        TypeExpr te = atom(String.class);
+        Assert.assertEquals(toSet(UpperBoundsConjunction.fromType(String.class).asWildcard("a")), te.lower("a").toNormalizedConjunctionSet());
+        te = atom(String.class).or(atom(RNull.class));
+        Assert.assertEquals(toSet(UpperBoundsConjunction.fromType(String.class).asWildcard("a"), UpperBoundsConjunction.fromType(RNull.class).asWildcard("a")),
+                        te.lower("a").toNormalizedConjunctionSet());
+        te = atom(Runnable.class).and(atom(RAbstractStringVector.class));
+        Set<Type> exp = toSet(UpperBoundsConjunction.create(Runnable.class, RAbstractStringVector.class).asWildcard("a"));
+        Assert.assertEquals(exp, te.lower("a").toNormalizedConjunctionSet());
+
+        te = atom(RAbstractIntVector.class).and(atom(RAbstractDoubleVector.class).lower());
+        Assert.assertTrue(te.isNothing());
+    }
+
     private static Set<Type> toSet(Type... classes) {
         return new HashSet<>(Arrays.asList(classes));
     }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java
deleted file mode 100644
index 6132d830f6..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentFilterSampler.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import com.oracle.truffle.r.nodes.builtin.ArgumentFilter;
-
-public interface ArgumentFilterSampler<T, R> extends ArgumentFilter<T, R> {
-
-    Samples<R> collectSamples(TypeExpr inputType);
-
-    TypeExpr trueBranchType();
-
-    TypeExpr falseBranchType();
-
-    interface NarrowingArgumentFilterSampler<T, R extends T> extends NarrowingArgumentFilter<T, R>, ArgumentFilterSampler<T, R> {
-
-        @Override
-        default <S extends T> ArgumentTypeFilterSampler<T, T> or(ArgumentFilter<T, S> o) {
-            final ArgumentFilterSampler<T, S> other = (ArgumentFilterSampler<T, S>) o;
-
-            return new ArgumentTypeFilterSampler<T, T>() {
-
-                @Override
-                public boolean test(T arg) {
-                    if (NarrowingArgumentFilterSampler.this.test(arg)) {
-                        return true;
-                    } else {
-                        return other.test(arg);
-                    }
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return NarrowingArgumentFilterSampler.this.trueBranchType().or(other.trueBranchType());
-                }
-
-                @Override
-                public Samples<T> collectSamples(TypeExpr inputType) {
-                    Samples<R> thisSamples = NarrowingArgumentFilterSampler.this.collectSamples(inputType);
-                    Samples<S> otherSamples = other.collectSamples(inputType);
-                    return Samples.<T> anything().and(thisSamples).or(otherSamples);
-                }
-            };
-        }
-    }
-
-    interface ArgumentValueFilterSampler<T> extends ArgumentValueFilter<T>, NarrowingArgumentFilterSampler<T, T> {
-
-        @Override
-        default TypeExpr falseBranchType() {
-            this.or(null);
-            return trueBranchType();
-        }
-
-        @Override
-        default <S extends T> ArgumentValueFilterSampler<T> or(ArgumentValueFilter<T> o) {
-            final ArgumentValueFilterSampler<T> other = (ArgumentValueFilterSampler<T>) o;
-
-            return new ArgumentValueFilterSampler<T>() {
-
-                @Override
-                public boolean test(T arg) {
-                    if (ArgumentValueFilterSampler.this.test(arg)) {
-                        return true;
-                    } else {
-                        return other.test(arg);
-                    }
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return ArgumentValueFilterSampler.this.trueBranchType().or(other.trueBranchType());
-                }
-
-                @Override
-                public Samples<T> collectSamples(TypeExpr inputType) {
-                    Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType);
-                    Samples<T> otherSamples = other.collectSamples(inputType);
-                    return Samples.<T> anything().and(thisSamples).or(otherSamples);
-                }
-            };
-        }
-
-        @Override
-        default ArgumentValueFilterSampler<T> and(ArgumentValueFilter<T> o) {
-            final ArgumentValueFilterSampler<T> other = (ArgumentValueFilterSampler<T>) o;
-
-            return new ArgumentValueFilterSampler<T>() {
-
-                @Override
-                public boolean test(T arg) {
-                    return ArgumentValueFilterSampler.this.test(arg) && other.test(arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return ArgumentValueFilterSampler.this.trueBranchType().and(other.trueBranchType());
-                }
-
-                @Override
-                public Samples<T> collectSamples(TypeExpr inputType) {
-                    Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType);
-                    Samples<T> otherSamples = other.collectSamples(inputType);
-
-                    return thisSamples.and(otherSamples);
-                }
-            };
-        }
-
-        @Override
-        default <S extends T> ArgumentTypeFilterSampler<T, S> and(ArgumentTypeFilter<T, S> o) {
-            final ArgumentTypeFilterSampler<T, S> other = (ArgumentTypeFilterSampler<T, S>) o;
-
-            return new ArgumentTypeFilterSampler<T, S>() {
-
-                @Override
-                public boolean test(T arg) {
-                    return ArgumentValueFilterSampler.this.test(arg) && other.test(arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return ArgumentValueFilterSampler.this.trueBranchType().and(other.trueBranchType());
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public Samples<S> collectSamples(TypeExpr inputType) {
-                    Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType);
-                    Samples<S> otherSamples = other.collectSamples(inputType);
-
-                    return (Samples<S>) thisSamples.and(otherSamples);
-                }
-            };
-        }
-
-        @Override
-        default ArgumentValueFilterSampler<T> not() {
-            return new ArgumentValueFilterSampler<T>() {
-
-                @Override
-                public boolean test(T arg) {
-                    return !ArgumentValueFilterSampler.this.test(arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return ArgumentValueFilterSampler.this.trueBranchType();
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public Samples<T> collectSamples(TypeExpr inputType) {
-                    Samples<T> thisSamples = ArgumentValueFilterSampler.this.collectSamples(inputType);
-                    return (Samples<T>) thisSamples.swap();
-                }
-            };
-        }
-    }
-
-    interface ArgumentTypeFilterSampler<T, R extends T> extends ArgumentTypeFilter<T, R>, NarrowingArgumentFilterSampler<T, R> {
-
-        @Override
-        default TypeExpr falseBranchType() {
-            return trueBranchType().not();
-        }
-
-        @Override
-        default <S extends R> ArgumentTypeFilterSampler<T, S> and(ArgumentTypeFilter<R, S> o) {
-            final ArgumentTypeFilterSampler<R, S> other = (ArgumentTypeFilterSampler<R, S>) o;
-
-            return new ArgumentTypeFilterSampler<T, S>() {
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public boolean test(T arg) {
-                    return ArgumentTypeFilterSampler.this.test(arg) && other.test((R) arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return ArgumentTypeFilterSampler.this.trueBranchType().and(other.trueBranchType());
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public Samples<S> collectSamples(TypeExpr inputType) {
-                    Samples<R> thisSamples = ArgumentTypeFilterSampler.this.collectSamples(inputType);
-                    Samples<S> otherSamples = other.collectSamples(inputType);
-
-                    return (Samples<S>) thisSamples.and(otherSamples);
-                }
-            };
-        }
-
-        @Override
-        default ArgumentTypeFilter<T, R> and(ArgumentValueFilter<R> o) {
-            final ArgumentValueFilterSampler<R> other = (ArgumentValueFilterSampler<R>) o;
-
-            return new ArgumentTypeFilterSampler<T, R>() {
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public boolean test(T arg) {
-                    return ArgumentTypeFilterSampler.this.test(arg) && other.test((R) arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return ArgumentTypeFilterSampler.this.trueBranchType().and(other.trueBranchType());
-                }
-
-                @Override
-                public Samples<R> collectSamples(TypeExpr inputType) {
-                    Samples<R> thisSamples = ArgumentTypeFilterSampler.this.collectSamples(inputType);
-                    Samples<R> otherSamples = other.collectSamples(inputType);
-
-                    return otherSamples.and(thisSamples);
-                }
-            };
-        }
-
-        @Override
-        default InverseArgumentFilterSampler<T, R> not() {
-            return new InverseArgumentFilterSampler<>(this);
-        }
-    }
-
-    class InverseArgumentFilterSampler<T, R extends T> extends InverseArgumentFilter<T, R> implements ArgumentFilterSampler<T, Object> {
-
-        private final ArgumentTypeFilterSampler<T, R> orig;
-
-        public InverseArgumentFilterSampler(ArgumentTypeFilter<T, R> o) {
-            super(o);
-            this.orig = (ArgumentTypeFilterSampler<T, R>) o;
-        }
-
-        @Override
-        public TypeExpr trueBranchType() {
-            return orig.trueBranchType().not();
-        }
-
-        @Override
-        public TypeExpr falseBranchType() {
-            return orig.falseBranchType().not();
-        }
-
-        @Override
-        public Samples<Object> collectSamples(TypeExpr inputType) {
-            Samples<? extends R> thisSamples = orig.collectSamples(inputType);
-            return thisSamples.swap();
-        }
-
-        @Override
-        public ArgumentTypeFilterSampler<T, R> not() {
-            return orig;
-        }
-
-        @Override
-        public <S extends T> ArgumentTypeFilterSampler<T, S> and(ArgumentTypeFilter<T, S> o) {
-            final ArgumentTypeFilterSampler<T, S> other = (ArgumentTypeFilterSampler<T, S>) o;
-
-            return new ArgumentTypeFilterSampler<T, S>() {
-
-                @Override
-                public boolean test(T arg) {
-                    return InverseArgumentFilterSampler.this.test(arg) && other.test(arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return InverseArgumentFilterSampler.this.trueBranchType().and(other.trueBranchType());
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public Samples<S> collectSamples(TypeExpr inputType) {
-                    Samples<Object> thisSamples = InverseArgumentFilterSampler.this.collectSamples(inputType);
-                    Samples<S> otherSamples = other.collectSamples(inputType);
-
-                    return (Samples<S>) thisSamples.and(otherSamples);
-                }
-            };
-        }
-
-        @Override
-        public <S extends T> ArgumentValueFilterSampler<S> and(ArgumentValueFilter<S> o) {
-            final ArgumentValueFilterSampler<S> other = (ArgumentValueFilterSampler<S>) o;
-
-            return new ArgumentValueFilterSampler<S>() {
-
-                @Override
-                public boolean test(S arg) {
-                    return InverseArgumentFilterSampler.this.test(arg) && other.test(arg);
-                }
-
-                @Override
-                public TypeExpr trueBranchType() {
-                    return InverseArgumentFilterSampler.this.trueBranchType().and(other.trueBranchType());
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public Samples<S> collectSamples(TypeExpr inputType) {
-                    Samples<Object> thisSamples = InverseArgumentFilterSampler.this.collectSamples(inputType);
-                    Samples<S> otherSamples = other.collectSamples(inputType);
-
-                    return (Samples<S>) thisSamples.and(otherSamples);
-                }
-            };
-        }
-
-        @Override
-        public <S extends T> InverseArgumentFilterSampler<T, T> and(InverseArgumentFilter<T, S> o) {
-            InverseArgumentFilterSampler<T, S> other = (InverseArgumentFilterSampler<T, S>) o;
-            return new InverseArgumentFilterSampler<>(other.orig.or(this.orig));
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java
deleted file mode 100644
index 8b1b6b0197..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ArgumentMapperSampler.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import com.oracle.truffle.r.nodes.builtin.ArgumentMapper;
-
-public interface ArgumentMapperSampler<T, R> extends ArgumentMapper<T, R> {
-
-    TypeExpr resultTypes(TypeExpr inputTypes);
-
-    Samples<T> collectSamples(Samples<R> downStreamSamples);
-
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java
deleted file mode 100644
index 880cfb0c9a..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastNodeSampler.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import java.lang.reflect.Constructor;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.oracle.truffle.r.nodes.unary.CastNode;
-
-public class CastNodeSampler<T extends CastNode> {
-
-    protected final T castNode;
-
-    public CastNodeSampler(T castNode) {
-        this.castNode = castNode;
-    }
-
-    public T getCastNode() {
-        return castNode;
-    }
-
-    public final TypeExpr resultTypes() {
-        SamplingContext ctx = new SamplingContext();
-        TypeExpr resTypes = resultTypes(TypeExpr.ANYTHING, ctx);
-        for (TypeExpr altResType : ctx.altResultTypes) {
-            resTypes = resTypes.or(altResType);
-        }
-        return resTypes;
-    }
-
-    public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) {
-        return CastUtils.Casts.createCastNodeCasts(castNode.getClass().getSuperclass()).narrow(inputType);
-    }
-
-    public final Samples<?> collectSamples() {
-        return collectSamples(TypeExpr.ANYTHING, Samples.anything());
-    }
-
-    @SuppressWarnings("unused")
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        return downStreamSamples;
-    }
-
-    public static <T extends CastNode> CastNodeSampler<T> createSampler(T castNode) {
-        return createSampler(castNode, true);
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T extends CastNode> CastNodeSampler<T> createSampler(T castNode, boolean useDefaultSampler) {
-        if (castNode == null) {
-            return null;
-        }
-
-        Class<? extends CastNode> castNodeCls = castNode.getClass();
-        String clsName = castNodeCls.getName();
-        String analyzerClsName = clsName + "Sampler";
-        Class<?> analyzerCls;
-        try {
-            analyzerCls = Class.forName(analyzerClsName);
-        } catch (ClassNotFoundException e) {
-            if (useDefaultSampler) {
-                return new CastNodeSampler<>(castNode);
-            } else {
-                throw new IllegalArgumentException("No sampler class found for cast node " + clsName);
-            }
-        }
-
-        try {
-            Constructor<?> analyzerConstr = analyzerCls.getConstructor(castNodeCls);
-            return (CastNodeSampler<T>) analyzerConstr.newInstance(castNode);
-        } catch (Exception e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    public static final class SamplingContext {
-        private List<TypeExpr> altResultTypes = new LinkedList<>();
-
-        public void addAltResultType(TypeExpr altResType) {
-            altResultTypes.add(altResType);
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
index 58c4a898ee..0b68e310c4 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
@@ -38,17 +38,20 @@ import java.util.stream.Collectors;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RListBase;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -250,6 +253,15 @@ public class CastUtils {
                 }
             };
 
+            /**
+             * It transforms this type coverage into another one that would be returned in the
+             * situation when the source and the target type were either positive or negative, as
+             * determined by the <code>sourcePositive</code> and <code>targetPositive</code>
+             * arguments.
+             * <p>
+             * N.B. It is assumed that this coverage is obtained for the positive source anb target
+             * types.
+             */
             public abstract Coverage transpose(Type sourceType, Type targetType, boolean sourcePositive, boolean targetPositive);
 
             public abstract Coverage or(Coverage other);
@@ -333,14 +345,14 @@ public class CastUtils {
         }
 
         public static Set<Cast> findConvertibleActualType(TypeExpr actualInputTypes, Type formalInputCls, boolean includeImplicits) {
-            Set<Type> normActTypes = actualInputTypes.normalize();
+            Set<Type> normActTypes = actualInputTypes.toNormalizedConjunctionSet();
             return normActTypes.stream().map(actualInputCls -> new Cast(actualInputCls, formalInputCls, isConvertible(actualInputCls, formalInputCls, includeImplicits))).filter(
                             c -> c.coverage != Cast.Coverage.none).collect(Collectors.toSet());
         }
 
         public static Cast.Coverage isConvertible(Type actualInputType, Type formalInputType, boolean includeImplicits) {
-            TypeConjunction from = TypeConjunction.fromType(actualInputType);
-            TypeConjunction to = TypeConjunction.fromType(formalInputType);
+            UpperBoundsConjunction from = UpperBoundsConjunction.fromType(actualInputType);
+            UpperBoundsConjunction to = UpperBoundsConjunction.fromType(formalInputType);
 
             Cast.Coverage result = to.coverageFrom(from, includeImplicits);
             return result;
@@ -415,12 +427,12 @@ public class CastUtils {
         if (argTypeSets.isEmpty()) {
             return Collections.emptySet();
         } else if (argTypeSets.size() == 1) {
-            return argTypeSets.get(0).normalize().stream().map((Type t) -> Collections.singletonList(t)).collect(Collectors.toSet());
+            return argTypeSets.get(0).toNormalizedConjunctionSet().stream().map((Type t) -> Collections.singletonList(t)).collect(Collectors.toSet());
         } else {
             Set<List<Type>> tailPowerSet = argumentProductSet(argTypeSets.subList(1, argTypeSets.size()));
             TypeExpr headArgSet = argTypeSets.get(0);
             Set<List<Type>> resultSet = new HashSet<>();
-            for (Type headType : headArgSet.normalize()) {
+            for (Type headType : headArgSet.toNormalizedConjunctionSet()) {
                 Set<LinkedList<Type>> extSublists = tailPowerSet.stream().map(x -> {
                     LinkedList<Type> extSublist = new LinkedList<>(x);
                     extSublist.addFirst(headType);
@@ -461,13 +473,16 @@ public class CastUtils {
         if (RAbstractComplexVector.class.isAssignableFrom(vectorType) || RComplex.class.isAssignableFrom(vectorType)) {
             return RComplex.class;
         }
+        if (RAbstractRawVector.class.isAssignableFrom(vectorType)) {
+            return RRaw.class;
+        }
         if (RListBase.class.isAssignableFrom(vectorType)) {
             return Object.class;
         }
-        if (RAbstractVector.class.isAssignableFrom(vectorType) || vectorType == Object.class) {
-            return Not.negateType(RAbstractVector.class);
+        if (RAbstractVector.class.isAssignableFrom(vectorType)) {
+            return Object.class;
         }
-        return Not.negateType(RAbstractVector.class);
+        return vectorType;
     }
 
     public static RAbstractVector emptyVector(Class<?> elementType) {
@@ -514,6 +529,81 @@ public class CastUtils {
         return null;
     }
 
+    public static RAbstractVector vectorOfSize(RType vectorType, int size) {
+        switch (vectorType) {
+            case Integer:
+                return RDataFactory.createIntVector(size);
+            case Double:
+                return RDataFactory.createDoubleVector(size);
+            case Logical:
+                return RDataFactory.createLogicalVector(size);
+            case Character:
+                return RDataFactory.createStringVector(size);
+            case Complex:
+                return RDataFactory.createComplexVector(size);
+            case Any:
+                return RDataFactory.createIntVector(size);
+            default:
+                return null;
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public static Class<?>[] rTypeToClasses(RType type) {
+        switch (type) {
+            case Integer:
+                return new Class[]{Integer.class, RAbstractIntVector.class};
+            case Double:
+                return new Class[]{Double.class, RAbstractDoubleVector.class};
+            case Logical:
+                return new Class[]{Byte.class, RAbstractLogicalVector.class};
+            case Character:
+                return new Class[]{String.class, RAbstractStringVector.class};
+            case Complex:
+                return new Class[]{RAbstractComplexVector.class};
+            case Raw:
+                return new Class[]{RAbstractRawVector.class};
+            case Any:
+                return new Class[]{Object.class};
+        }
+        return null;
+    }
+
+    public static RAbstractVector fillVector(RType vectorType, int size, Object value, boolean complete) {
+        switch (vectorType) {
+            case Integer:
+                int[] iarray = new int[size];
+                Arrays.fill(iarray, (int) value);
+                return RDataFactory.createIntVector(iarray, complete);
+            case Double:
+                double[] darray = new double[size];
+                Arrays.fill(darray, (double) value);
+                return RDataFactory.createDoubleVector(darray, complete);
+            case Logical:
+                byte[] larray = new byte[size];
+                Arrays.fill(larray, (byte) value);
+                return RDataFactory.createLogicalVector(larray, complete);
+            case Character:
+                String[] sarray = new String[size];
+                Arrays.fill(sarray, value);
+                return RDataFactory.createStringVector(sarray, complete);
+            case Complex:
+                double[] carray = new double[2 * size];
+                RComplex c = (RComplex) value;
+                for (int i = 0; i < size; i++) {
+                    carray[2 * i] = c.getRealPart();
+                    carray[2 * i + 1] = c.getImaginaryPart();
+                }
+                return RDataFactory.createComplexVector(carray, complete);
+            case Any:
+                Object[] oarray = new Object[size];
+                Arrays.fill(oarray, value);
+                return RDataFactory.createList(oarray);
+            default:
+                return null;
+        }
+    }
+
     public static Object naVector(Class<?> elementType) {
         if (Integer.class.isAssignableFrom(elementType)) {
             return RDataFactory.createIntVectorFromScalar(RRuntime.INT_NA);
@@ -660,13 +750,18 @@ public class CastUtils {
     }
 
     public static Set<?> sampleValuesForTypeExpr(TypeExpr te) {
-        return te.normalize().stream().flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet());
+        return te.toNormalizedConjunctionSet().stream().flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet());
     }
 
-    public static Set<?> sampleValuesForClases(Class<?>[] classes) {
+    public static Set<?> sampleValuesForClasses(Class<?>[] classes) {
         return Arrays.stream(classes).flatMap(t -> CastUtils.sampleValuesForType(t).stream()).collect(Collectors.toSet());
     }
 
+    @SuppressWarnings("rawtypes")
+    public static Set<?> sampleValuesForClass(Class<?> cls) {
+        return sampleValuesForClasses(new Class[]{cls});
+    }
+
     public static Set<?> sampleValuesForType(Type t) {
         HashSet<Object> samples = new HashSet<>();
 
@@ -734,6 +829,8 @@ public class CastUtils {
         }
 
         if (cls == Object.class || RAbstractComplexVector.class.isAssignableFrom(cls)) {
+            samples.add(RComplex.createNA());
+            samples.add(RDataFactory.createComplex(0, 0));
             samples.add(RDataFactory.createComplexVectorFromScalar(RComplex.valueOf(0, 0)));
             samples.add(RDataFactory.createComplexVectorFromScalar(RComplex.valueOf(1, 1)));
             samples.add(RDataFactory.createComplexVectorFromScalar(RComplex.valueOf(-1, 1)));
@@ -747,6 +844,7 @@ public class CastUtils {
         if (cls == Object.class || String.class.isAssignableFrom(cls)) {
             samples.add("");
             samples.add("abc");
+            samples.add(RRuntime.STRING_NA);
         }
 
         if (cls == Object.class || RAbstractStringVector.class.isAssignableFrom(cls)) {
@@ -757,6 +855,11 @@ public class CastUtils {
             samples.add(RDataFactory.createStringVector(new String[]{RRuntime.STRING_NA}, false));
         }
 
+        if (RAbstractRawVector.class.isAssignableFrom(cls)) {
+            samples.add((byte) 0);
+            samples.add(RDataFactory.createRawVector(new byte[]{0}));
+        }
+
         samples.remove(null);
 
         return samples;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java
deleted file mode 100644
index 5341c5cef8..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/FilterSamplerFactory.java
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import static com.oracle.truffle.r.nodes.casts.CastUtils.samples;
-
-import java.util.Arrays;
-import java.util.Set;
-import java.util.function.Predicate;
-
-import com.oracle.truffle.r.nodes.builtin.ArgumentFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.Dim;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ElementAt;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.NATest;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.StringLength;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.VectorSize;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentFilterFactory;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-public final class FilterSamplerFactory
-                implements ArgumentFilterFactory, FilterVisitor<ArgumentFilterSampler<?, ?>>, MatrixFilter.OperationVisitor<ArgumentFilterSampler<RAbstractVector, RAbstractVector>>,
-                DoubleFilter.OperationVisitor<ArgumentFilterSampler<Double, Double>>, CompareFilter.SubjectVisitor<ArgumentFilterSampler<?, ?>> {
-
-    public static final FilterSamplerFactory INSTANCE = new FilterSamplerFactory();
-
-    private FilterSamplerFactory() {
-        // singleton
-    }
-
-    @Override
-    public ArgumentFilter<?, ?> createFilter(Filter<?, ?> filter) {
-        return filter.accept(this);
-    }
-
-    private static <T, R> Predicate<T> toPredicate(ArgumentFilter<T, R> filter) {
-        return x -> filter.test(x);
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(TypeFilter<?, ?> filter) {
-        Class<?>[] filterTypes = new Class[]{filter.getType1(), filter.getType2()};
-        return TypePredicateArgumentFilterSampler.fromLambda(toPredicate(filter.getInstanceOfLambda()),
-                        CastUtils.sampleValuesForClases(filterTypes), CastUtils.samples(null), filterTypes);
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(RTypeFilter<?> filter) {
-        if (filter.getType() == RType.Integer) {
-            return visit(new TypeFilter<>(Integer.class, RAbstractIntVector.class));
-        } else if (filter.getType() == RType.Double) {
-            return visit(new TypeFilter<>(Double.class, RAbstractDoubleVector.class));
-        } else if (filter.getType() == RType.Logical) {
-            return visit(new TypeFilter<>(Byte.class, RAbstractLogicalVector.class));
-        } else if (filter.getType() == RType.Complex) {
-            return visit(new TypeFilter<>(RAbstractComplexVector.class));
-        } else if (filter.getType() == RType.Character) {
-            return visit(new TypeFilter<>(String.class, RAbstractStringVector.class));
-        } else if (filter.getType() == RType.Raw) {
-            return visit(new TypeFilter<>(RAbstractRawVector.class));
-        } else {
-            throw RInternalError.unimplemented("TODO: more types here");
-        }
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(CompareFilter<?> filter) {
-        return filter.getSubject().accept(this, filter.getOperation());
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(AndFilter<?, ?> filter) {
-        ArgumentFilterSampler leftFilter = filter.getLeft().accept(this);
-        ArgumentFilterSampler rightFilter = filter.getRight().accept(this);
-        return new ArgumentFilterSampler<Object, Object>() {
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean test(Object arg) {
-                if (!leftFilter.test(arg)) {
-                    return false;
-                } else {
-                    return rightFilter.test(arg);
-                }
-            }
-
-            @Override
-            public TypeExpr falseBranchType() {
-                return filter.isNarrowing() ? trueBranchType().not() : trueBranchType();
-            }
-
-            @Override
-            public TypeExpr trueBranchType() {
-                return leftFilter.trueBranchType().and(rightFilter.trueBranchType());
-            }
-
-            @SuppressWarnings({"unchecked"})
-            @Override
-            public Samples<Object> collectSamples(TypeExpr inputType) {
-                Samples thisSamples = rightFilter.collectSamples(inputType);
-                Samples otherSamples = leftFilter.collectSamples(inputType);
-
-                return thisSamples.and(otherSamples);
-            }
-        };
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(OrFilter<?> filter) {
-        ArgumentFilterSampler leftFilter = filter.getLeft().accept(this);
-        ArgumentFilterSampler rightFilter = filter.getRight().accept(this);
-        return new ArgumentFilterSampler<Object, Object>() {
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean test(Object arg) {
-                if (leftFilter.test(arg)) {
-                    return true;
-                } else {
-                    return rightFilter.test(arg);
-                }
-            }
-
-            @Override
-            public TypeExpr falseBranchType() {
-                return trueBranchType();
-            }
-
-            @Override
-            public TypeExpr trueBranchType() {
-                return leftFilter.trueBranchType().or(rightFilter.trueBranchType());
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public Samples<Object> collectSamples(TypeExpr inputType) {
-                Samples thisSamples = leftFilter.collectSamples(inputType);
-                Samples otherSamples = rightFilter.collectSamples(inputType);
-                return Samples.<Object> anything().and(thisSamples).or(otherSamples);
-            }
-        };
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(NotFilter<?> filter) {
-        ArgumentFilterSampler toNegate = filter.getFilter().accept(this);
-        return new ArgumentFilterSampler<Object, Object>() {
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean test(Object arg) {
-                return !toNegate.test(arg);
-            }
-
-            @Override
-            public TypeExpr falseBranchType() {
-                return filter.getFilter().isNarrowing() ? trueBranchType() : trueBranchType();
-            }
-
-            @Override
-            public TypeExpr trueBranchType() {
-                return filter.getFilter().isNarrowing() ? toNegate.trueBranchType().not() : toNegate.trueBranchType();
-            }
-
-            @SuppressWarnings({"unchecked"})
-            @Override
-            public Samples<Object> collectSamples(TypeExpr inputType) {
-                Samples thisSamples = toNegate.collectSamples(inputType);
-                return thisSamples.swap();
-            }
-        };
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(NullFilter filter) {
-        return new VectorPredicateArgumentFilterSampler<>("nullValue", x -> false);
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(MissingFilter filter) {
-        return new VectorPredicateArgumentFilterSampler<>("missingValue", x -> false);
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(MatrixFilter<?> filter) {
-        return filter.acceptOperation(this);
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(DoubleFilter filter) {
-        return filter.acceptOperation(this);
-    }
-
-    @Override
-    public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visitIsMatrix() {
-        return new VectorPredicateArgumentFilterSampler<>("matrix", x -> x.isMatrix());
-    }
-
-    @Override
-    public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visitIsSquareMatrix() {
-        return new VectorPredicateArgumentFilterSampler<>("squareMatrix", x -> x.isMatrix() && x.getDimensions()[0] == x.getDimensions()[1], 3);
-    }
-
-    @Override
-    public ArgumentFilterSampler<Double, Double> visitIsFinite() {
-        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> !Double.isInfinite(x), samples(0d), samples(RRuntime.DOUBLE_NA), Double.class);
-    }
-
-    @Override
-    public ArgumentFilterSampler<Double, Double> visitIsFractional() {
-        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> !RRuntime.isNAorNaN(x) && !Double.isInfinite(x) && x != Math.floor(x), samples(0d), samples(RRuntime.DOUBLE_NA),
-                        Double.class);
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(ScalarValue scalarValue, byte operation) {
-        switch (operation) {
-            case CompareFilter.EQ:
-                switch (scalarValue.type) {
-                    case Character:
-                        final String s = (String) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.equals(s), samples(s), CastUtils.samples(null), String.class);
-                    case Integer:
-                        final int i = (int) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg == i, samples(i), CastUtils.<Integer> samples(i + 1), Integer.class);
-                    case Double:
-                        final double d = (double) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg == d, samples(d), CastUtils.<Double> samples(d + 1), Double.class);
-                    case Logical:
-                        final byte l = (byte) scalarValue.value;
-                        Set<Byte> negativeSamples = null;
-                        switch (l) {
-                            case RRuntime.LOGICAL_TRUE:
-                                negativeSamples = CastUtils.samples(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA);
-                                break;
-                            case RRuntime.LOGICAL_FALSE:
-                                negativeSamples = CastUtils.samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_NA);
-                                break;
-                            case RRuntime.LOGICAL_NA:
-                                negativeSamples = CastUtils.samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE);
-                                break;
-                        }
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Byte arg) -> arg == l, samples(l), negativeSamples, Byte.class);
-                    case Any:
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(arg -> arg.equals(scalarValue.value), samples(), CastUtils.samples(null), scalarValue.value.getClass());
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here ");
-                }
-            case CompareFilter.GT:
-                switch (scalarValue.type) {
-                    case Integer:
-                        final int i = (int) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg > i, samples(i + 1), samples(i), Integer.class);
-                    case Double:
-                        final double d = (double) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg > d, CastUtils.<Double> samples(), samples(d), Double.class);
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here");
-                }
-            case CompareFilter.LT:
-                switch (scalarValue.type) {
-                    case Integer:
-                        final int i = (int) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg < i, samples(i - 1), samples(i), Integer.class);
-                    case Double:
-                        final double d = (double) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg < d, CastUtils.<Double> samples(), samples(d), Double.class);
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here");
-                }
-            case CompareFilter.GE:
-                switch (scalarValue.type) {
-                    case Integer:
-                        final int i = (int) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg >= i, samples(i), samples(i - 1), Integer.class);
-                    case Double:
-                        final double d = (double) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg >= d, samples(d), samples(d - 1), Double.class);
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here");
-                }
-            case CompareFilter.LE:
-                switch (scalarValue.type) {
-                    case Integer:
-                        final int i = (int) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer arg) -> arg <= i, samples(i), samples(i + 1), Integer.class);
-                    case Double:
-                        final double d = (double) scalarValue.value;
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double arg) -> arg <= d, samples(d), samples(d + 1), Double.class);
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here");
-                }
-            case CompareFilter.SAME:
-                return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples(arg -> arg == scalarValue.value, samples(scalarValue.value), CastUtils.samples(null), scalarValue.value.getClass());
-
-            default:
-                throw RInternalError.unimplemented("TODO: more operations here");
-        }
-    }
-
-    @Override
-    public ArgumentFilterSampler<?, ?> visit(NATest naTest, byte operation) {
-        switch (operation) {
-            case CompareFilter.EQ:
-                switch (naTest.type) {
-                    case Integer:
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Integer x) -> RRuntime.isNA(x), samples(RRuntime.INT_NA), samples(0), Integer.class);
-                    case Double:
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Double x) -> RRuntime.isNAorNaN(x), samples(RRuntime.DOUBLE_NA), samples(0d), Double.class);
-                    case Logical:
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((Byte x) -> RRuntime.isNA(x), samples(RRuntime.LOGICAL_NA),
-                                        samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE), Byte.class);
-                    case Character:
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String x) -> RRuntime.isNA(x), samples(RRuntime.STRING_NA), samples(""), String.class);
-                    case Complex:
-                        return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((RComplex x) -> x.isNA(), samples(RDataFactory.createComplex(RRuntime.COMPLEX_NA_REAL_PART, 0)),
-                                        samples(RDataFactory.createComplex(0, 0)), RComplex.class);
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here");
-                }
-            default:
-                throw RInternalError.unimplemented("TODO: more operations here");
-        }
-    }
-
-    @Override
-    public ArgumentFilterSampler<String, String> visit(StringLength stringLength, byte operation) {
-        final int l = stringLength.length;
-        switch (operation) {
-            case CompareFilter.EQ:
-                return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() == l, samples(sampleString(l)),
-                                samples(sampleString(l + 1)), String.class);
-
-            case CompareFilter.GT:
-                return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() > l, samples(sampleString(l + 1)),
-                                samples(sampleString(l)), String.class);
-
-            case CompareFilter.LT:
-                return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() < l, samples(sampleString(l - 1)),
-                                samples(sampleString(l)), String.class);
-
-            case CompareFilter.GE:
-                return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() >= l, samples(sampleString(l)),
-                                samples(sampleString(l - 1)), String.class);
-
-            case CompareFilter.LE:
-                return ValuePredicateArgumentFilterSampler.fromLambdaWithSamples((String arg) -> arg.length() <= l, samples(sampleString(l)),
-                                samples(sampleString(l + 1)), String.class);
-
-            default:
-                throw RInternalError.unimplemented("TODO: more operations here");
-        }
-    }
-
-    private static String sampleString(int len) {
-        if (len < 0) {
-            return null;
-        } else if (len == 0) {
-            return "";
-        } else {
-            char[] ch = new char[len];
-            Arrays.fill(ch, 'a');
-            return String.valueOf(ch);
-        }
-    }
-
-    @Override
-    public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation) {
-        final int s = vectorSize.size;
-        switch (operation) {
-            case CompareFilter.EQ:
-                if (s == 0) {
-                    return new VectorPredicateArgumentFilterSampler<>("size(int)", x -> x.getLength() == s, s - 1, s + 1);
-                } else {
-                    return new VectorPredicateArgumentFilterSampler<>("size(int)", x -> x.getLength() == s, 0, s - 1, s + 1);
-                }
-            case CompareFilter.GT:
-                return new VectorPredicateArgumentFilterSampler<>("sizeGt(int)", x -> x.getLength() > s, s - 1, s);
-
-            case CompareFilter.LT:
-                return new VectorPredicateArgumentFilterSampler<>("sizeLt(int)", x -> x.getLength() < s, s, s + 1);
-
-            case CompareFilter.GE:
-                return new VectorPredicateArgumentFilterSampler<>("sizeGe(int)", x -> x.getLength() >= s, s - 1);
-
-            case CompareFilter.LE:
-                return new VectorPredicateArgumentFilterSampler<>("sizeLe(int)", x -> x.getLength() <= s, s + 1);
-
-            default:
-                throw RInternalError.unimplemented("TODO: more operations here");
-        }
-    }
-
-    @Override
-    public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation) {
-        final int index = elementAt.index;
-        switch (operation) {
-            case CompareFilter.EQ:
-                switch (elementAt.type) {
-                    case Integer:
-                        int i = (int) elementAt.value;
-                        return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && i == (int) (x.getDataAtAsObject(index)), 0, index);
-                    case Double:
-                        double d = (double) elementAt.value;
-                        return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && d == (double) (x.getDataAtAsObject(index)), 0, index);
-                    case Logical:
-                        byte l = (byte) elementAt.value;
-                        return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && l == (byte) (x.getDataAtAsObject(index)), 0, index);
-                    case Character:
-                    case Complex:
-                        return new VectorPredicateArgumentFilterSampler<>("elementAt", x -> index < x.getLength() && elementAt.value.equals(x.getDataAtAsObject(index)), 0, index);
-                    default:
-                        throw RInternalError.unimplemented("TODO: more types here");
-                }
-            default:
-                throw RInternalError.unimplemented("TODO: more operations here");
-        }
-    }
-
-    @Override
-    public ArgumentFilterSampler<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation) {
-        switch (operation) {
-            case CompareFilter.EQ:
-                return new VectorPredicateArgumentFilterSampler<>("dimEq", v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] == dim.dimSize, 3);
-            case CompareFilter.GT:
-                return new VectorPredicateArgumentFilterSampler<>("dimGt", v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] > dim.dimSize, 3);
-            default:
-                throw RInternalError.unimplemented("TODO: more operations here");
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java
deleted file mode 100644
index 078025424b..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MapperSamplerFactory.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import static com.oracle.truffle.r.nodes.casts.CastUtils.samples;
-
-import com.oracle.truffle.r.nodes.builtin.ArgumentMapper;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactory;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.ops.na.NACheck;
-
-public final class MapperSamplerFactory implements ArgumentMapperFactory, MapperVisitor<ValuePredicateArgumentMapperSampler<?, ?>> {
-
-    public static final MapperSamplerFactory INSTANCE = new MapperSamplerFactory();
-
-    private MapperSamplerFactory() {
-        // singleton
-    }
-
-    @Override
-    public ArgumentMapper<?, ?> createMapper(Mapper<?, ?> mapper) {
-        return mapper.accept(this);
-    }
-
-    @Override
-    public ValuePredicateArgumentMapperSampler<Object, Object> visit(MapToValue<?, ?> mapper) {
-        final Object value = mapper.getValue();
-        return ValuePredicateArgumentMapperSampler.fromLambda(x -> value, x -> null, CastUtils.samples(), CastUtils.samples(), null, value.getClass());
-    }
-
-    @Override
-    public ValuePredicateArgumentMapperSampler<?, ?> visit(MapByteToBoolean mapper) {
-        return ValuePredicateArgumentMapperSampler.fromLambda(x -> RRuntime.fromLogical(x), (Boolean x) -> RRuntime.asLogical(x),
-                        samples(RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_NA),
-                        CastUtils.<Byte> samples(), Byte.class, Boolean.class);
-    }
-
-    @Override
-    public ValuePredicateArgumentMapperSampler<?, ?> visit(MapDoubleToInt mapper) {
-        final NACheck naCheck = NACheck.create();
-        return ValuePredicateArgumentMapperSampler.fromLambda(x -> {
-            naCheck.enable(x);
-            return naCheck.convertDoubleToInt(x);
-        }, x -> x == null ? null : (double) x, Double.class, Integer.class);
-    }
-
-    @Override
-    public ValuePredicateArgumentMapperSampler<?, ?> visit(MapToCharAt mapper) {
-        final int defaultValue = mapper.getDefaultValue();
-
-        return ValuePredicateArgumentMapperSampler.fromLambda(x -> {
-            if (x == null || x.isEmpty()) {
-                return defaultValue;
-            } else {
-                if (x == RRuntime.STRING_NA) {
-                    return RRuntime.INT_NA;
-                } else {
-                    return (int) x.charAt(0);
-                }
-            }
-        }, x -> {
-            if (x == null) {
-                return defaultValue == RRuntime.INT_NA ? RRuntime.STRING_NA : "" + (char) defaultValue;
-            } else {
-                return x.equals(RRuntime.INT_NA) ? RRuntime.STRING_NA : x.toString();
-            }
-        }, samples(defaultValue == RRuntime.INT_NA ? RRuntime.STRING_NA : "" + (char) defaultValue), CastUtils.<String> samples(), String.class, Integer.class);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
new file mode 100644
index 0000000000..2e6b1af9bb
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.casts;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.oracle.truffle.r.nodes.builtin.casts.Filter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor;
+
+public final class MarkLookup implements PipelineStepVisitor<Map<String, Object>>, FilterVisitor<Map<String, Object>>, MapperVisitor<Map<String, Object>> {
+    private final Map<Object, String> marx = new HashMap<>();
+
+    public static final MarkLookup INSTANCE = new MarkLookup();
+
+    private MarkLookup() {
+    }
+
+    public static void clear() {
+        INSTANCE.marx.clear();
+    }
+
+    public static <T, S extends T, F extends Filter<T, S>> F mark(F filter, String m) {
+        INSTANCE.marx.put(filter, m);
+        return filter;
+    }
+
+    public static <T, S, M extends Mapper<T, S>> M mark(M mapper, String m) {
+        INSTANCE.marx.put(mapper, m);
+        return mapper;
+    }
+
+    public static Map<String, Object> lookup(PipelineStep<?, ?> firstStep, String... filterNames) {
+        return lookup(firstStep, Arrays.stream(filterNames).collect(Collectors.toSet()));
+    }
+
+    public static Map<String, Object> lookup(PipelineStep<?, ?> firstStep, Set<String> filterNames) {
+        Map<String, Object> foundMarks = new HashMap<>();
+        for (String key : filterNames) {
+            foundMarks.put(key, null);
+        }
+        return lookup(firstStep, foundMarks);
+    }
+
+    public static Map<String, Object> lookup(PipelineStep<?, ?> firstStep, Map<String, Object> foundMarks) {
+        return firstStep.acceptPipeline(INSTANCE, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(FindFirstStep<?, ?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(CoercionStep<?, ?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(MapStep<?, ?> step, Map<String, Object> foundMarks) {
+        return step.getMapper().accept(this, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(MapIfStep<?, ?> step, Map<String, Object> foundMarks) {
+        Map<String, Object> found = foundMarks;
+        found = step.getFilter().accept(this, found);
+        if (step.getTrueBranch() != null) {
+            found = step.getTrueBranch().accept(this, found);
+        }
+        if (step.getFalseBranch() != null) {
+            found = step.getFalseBranch().accept(this, found);
+        }
+        return found;
+    }
+
+    @Override
+    public Map<String, Object> visit(FilterStep<?, ?> step, Map<String, Object> foundMarks) {
+        return step.getFilter().accept(this, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(NotNAStep<?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(DefaultErrorStep<?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(DefaultWarningStep<?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(BoxPrimitiveStep<?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(AttributableCoercionStep<?> step, Map<String, Object> foundMarks) {
+        return foundMarks;
+    }
+
+    // Filter visitor
+
+    public Map<String, Object> visitFilter(Filter<?, ?> filter, Map<String, Object> foundMarks) {
+        String mark = marx.get(filter);
+        if (mark != null && foundMarks.containsKey(mark)) {
+            foundMarks.put(mark, filter);
+        }
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(TypeFilter<?, ?> filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(RTypeFilter<?> filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(CompareFilter<?> filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(AndFilter<?, ?> filter, Map<String, Object> foundMarks) {
+        Map<String, Object> found = filter.getLeft().accept(this, visitFilter(filter, foundMarks));
+        return filter.getRight().accept(this, filter.getLeft().accept(this, found));
+    }
+
+    @Override
+    public Map<String, Object> visit(OrFilter<?> filter, Map<String, Object> foundMarks) {
+        Map<String, Object> found = filter.getLeft().accept(this, visitFilter(filter, foundMarks));
+        return filter.getRight().accept(this, filter.getLeft().accept(this, found));
+    }
+
+    @Override
+    public Map<String, Object> visit(NotFilter<?> filter, Map<String, Object> foundMarks) {
+        return filter.getFilter().accept(this, visitFilter(filter, foundMarks));
+    }
+
+    @Override
+    public Map<String, Object> visit(MatrixFilter<?> filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(DoubleFilter filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(NullFilter filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(MissingFilter filter, Map<String, Object> foundMarks) {
+        return visitFilter(filter, foundMarks);
+    }
+
+    // Mapper visitor
+
+    public Map<String, Object> visitMapper(Mapper<?, ?> mapper, Map<String, Object> foundMarks) {
+        String mark = marx.get(mapper);
+        if (mark != null && foundMarks.containsKey(mark)) {
+            foundMarks.put(mark, mapper);
+        }
+        return foundMarks;
+    }
+
+    @Override
+    public Map<String, Object> visit(MapToValue<?, ?> mapper, Map<String, Object> foundMarks) {
+        return visitMapper(mapper, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(MapByteToBoolean mapper, Map<String, Object> foundMarks) {
+        return visitMapper(mapper, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(MapDoubleToInt mapper, Map<String, Object> foundMarks) {
+        return visitMapper(mapper, foundMarks);
+    }
+
+    @Override
+    public Map<String, Object> visit(MapToCharAt mapper, Map<String, Object> foundMarks) {
+        return visitMapper(mapper, foundMarks);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
index 0583db597d..28d9ff8fff 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
@@ -29,19 +29,33 @@ public final class Not<T> implements Type, TypeAndInstanceCheck {
 
     public static final Not<Object> NOTHING = new Not<>(Object.class);
 
-    private final Class<T> negated;
+    private final Type negated;
 
-    private Not(Class<T> negated) {
+    private Not(Type negated) {
         this.negated = negated;
     }
 
-    public Class<T> getNegated() {
+    public Type getNegated() {
         return this.negated;
     }
 
     @Override
     public boolean isInstance(Object x) {
-        return !negated.isInstance(x);
+        if (negated instanceof TypeAndInstanceCheck) {
+            return !((TypeAndInstanceCheck) negated).isInstance(x);
+        } else {
+            assert negated instanceof Class;
+            return !((Class<?>) negated).isInstance(x);
+        }
+    }
+
+    @Override
+    public Type normalize() {
+        if (negated instanceof TypeAndInstanceCheck) {
+            return new Not<>(((TypeAndInstanceCheck) negated).normalize());
+        } else {
+            return this;
+        }
     }
 
     public static boolean isNegative(Type t) {
@@ -61,13 +75,13 @@ public final class Not<T> implements Type, TypeAndInstanceCheck {
             return getPositiveType(t);
         } else {
             assert t instanceof Class;
-            return new Not<>((Class<?>) t);
+            return new Not<>(t);
         }
     }
 
     @Override
     public String toString() {
-        return "Not(" + negated.getSimpleName() + ")";
+        return "Not(" + (negated instanceof Class ? ((Class<?>) negated).getSimpleName() : negated.toString()) + ")";
     }
 
     @Override
@@ -90,7 +104,7 @@ public final class Not<T> implements Type, TypeAndInstanceCheck {
             return false;
         }
         Not<?> other = (Not<?>) obj;
-        return other.negated == this.negated;
+        return other.negated.equals(this.negated);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
new file mode 100644
index 0000000000..8dcc52367a
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.casts;
+
+import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.oracle.truffle.r.nodes.builtin.casts.ExecutionPathVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.Dim;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ElementAt;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.NATest;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.StringLength;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.SubjectVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.VectorSize;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
+import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser.AltTypeExpr;
+import com.oracle.truffle.r.nodes.unary.CastComplexNode;
+import com.oracle.truffle.r.nodes.unary.CastDoubleBaseNode;
+import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
+import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNode;
+import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
+import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNode;
+import com.oracle.truffle.r.nodes.unary.CastLogicalNode;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.nodes.unary.CastRawNode;
+import com.oracle.truffle.r.nodes.unary.CastStringBaseNode;
+import com.oracle.truffle.r.nodes.unary.CastStringNode;
+import com.oracle.truffle.r.nodes.unary.CastToAttributableNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDouble;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RString;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> implements MapperVisitor<TypeExpr>, FilterVisitor<TypeExpr>, SubjectVisitor<TypeExpr> {
+
+    static final class AltTypeExpr {
+        final TypeExpr main;
+        final TypeExpr alt;
+
+        private AltTypeExpr(TypeExpr mainBranch, TypeExpr altBranch) {
+            this.main = mainBranch;
+            this.alt = altBranch;
+        }
+
+        static AltTypeExpr create() {
+            return new AltTypeExpr(TypeExpr.ANYTHING, null);
+        }
+
+        TypeExpr merge() {
+            return alt == null ? main : main.or(alt);
+        }
+
+        AltTypeExpr setMain(TypeExpr newMainType) {
+            return newMainType == null ? this : new AltTypeExpr(newMainType, alt);
+        }
+
+        AltTypeExpr addAlt(TypeExpr newAltType) {
+            return newAltType == null ? this : new AltTypeExpr(main, alt == null ? newAltType : alt.or(newAltType));
+        }
+
+        AltTypeExpr or(AltTypeExpr other) {
+            return setMain(main.or(other.main)).addAlt(other.alt);
+        }
+
+    }
+
+    public static TypeExpr analyse(PipelineStep<?, ?> firstStep) {
+        return analyse(firstStep, AltTypeExpr.create()).merge();
+    }
+
+    public static AltTypeExpr analyse(PipelineStep<?, ?> firstStep, AltTypeExpr inputType) {
+        List<AltTypeExpr> pathResults = new ResultTypesAnalyser().visitPaths(firstStep, inputType);
+        return pathResults.stream().reduce((x, y) -> x.or(y)).get();
+    }
+
+    @Override
+    public AltTypeExpr visit(FindFirstStep<?, ?> step, AltTypeExpr inputType) {
+        TypeExpr rt;
+        if (step.getElementClass() == null || step.getElementClass() == Object.class) {
+            if (inputType.main.isAnything()) {
+                rt = atom(RAbstractVector.class).not();
+            } else {
+                Set<Type> resTypes = inputType.main.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet());
+                rt = TypeExpr.union(resTypes);
+            }
+        } else {
+            rt = atom(step.getElementClass());
+        }
+
+        // findFirstOrNull
+        if (step.getDefaultValue() == RNull.instance) {
+            rt = rt.or(atom(RNull.class));
+        }
+
+        if (step.getDefaultValue() != null) {
+            rt = rt.positiveSamples(step.getDefaultValue());
+        } else {
+            rt = rt.and(atom(RNull.class).not()).and(atom(RMissing.class).not());
+        }
+
+        return inputType.setMain(rt);
+    }
+
+    private static TypeExpr inferResultTypeFromSpecializations(Class<? extends CastNode> castNodeClass, TypeExpr inputType) {
+        return CastUtils.Casts.createCastNodeCasts(castNodeClass).narrow(inputType);
+    }
+
+    @Override
+    public AltTypeExpr visit(CoercionStep<?, ?> step, AltTypeExpr inputType) {
+        RType type = step.getType();
+        TypeExpr res;
+        switch (type) {
+            case Integer:
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastIntegerNode.class, inputType.main) : inferResultTypeFromSpecializations(CastIntegerBaseNode.class, inputType.main);
+                break;
+            case Double:
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastDoubleNode.class, inputType.main) : inferResultTypeFromSpecializations(CastDoubleBaseNode.class, inputType.main);
+                break;
+            case Character:
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastStringNode.class, inputType.main) : inferResultTypeFromSpecializations(CastStringBaseNode.class, inputType.main);
+                break;
+            case Logical:
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastLogicalNode.class, inputType.main) : inferResultTypeFromSpecializations(CastLogicalBaseNode.class, inputType.main);
+                break;
+            case Complex:
+                res = inferResultTypeFromSpecializations(CastComplexNode.class, inputType.main);
+                break;
+            case Raw:
+                res = inferResultTypeFromSpecializations(CastRawNode.class, inputType.main);
+                break;
+            case Any:
+                TypeExpr funOrVecTp = atom(RFunction.class).or(atom(RAbstractVector.class));
+                res = inputType.main.and(funOrVecTp);
+                break;
+            default:
+                throw RInternalError.shouldNotReachHere(Utils.stringFormat("Unsupported type '%s' in AsVectorStep", type));
+        }
+
+        if (step.preserveNonVector) {
+            TypeExpr maskedNullMissing = inputType.main.and(atom(RNull.class).or(atom(RMissing.class)));
+            res = res.or(maskedNullMissing);
+        }
+
+        return inputType.setMain(res);
+    }
+
+    @Override
+    public AltTypeExpr visit(MapStep<?, ?> step, AltTypeExpr inputType) {
+        return inputType.setMain(step.getMapper().accept(this, inputType.main));
+    }
+
+    @Override
+    protected AltTypeExpr visitBranch(MapIfStep<?, ?> step, AltTypeExpr inputType, boolean visitTrueBranch) {
+        TypeExpr filterRes = visitFilter(step.getFilter(), inputType.main);
+        if (visitTrueBranch) {
+            if (step.isReturns()) {
+                AltTypeExpr returnedType = trueBranchResultTypes(step, inputType, filterRes);
+                inputType.addAlt(returnedType.merge());
+                return inputType;
+            } else {
+                return trueBranchResultTypes(step, inputType, filterRes);
+            }
+        } else {
+            return falseBranchResultTypes(step, inputType, filterRes);
+        }
+    }
+
+    private static AltTypeExpr trueBranchResultTypes(MapIfStep<?, ?> step, AltTypeExpr inputType, TypeExpr filterRes) {
+        TypeExpr filterTrueCaseType = inputType.main.and(filterRes);
+        if (step.getTrueBranch() != null) {
+            return analyse(step.getTrueBranch(), inputType.setMain(filterTrueCaseType));
+        } else {
+            return inputType.setMain(filterTrueCaseType);
+        }
+    }
+
+    private static AltTypeExpr falseBranchResultTypes(MapIfStep<?, ?> step, AltTypeExpr inputType, TypeExpr filterRes) {
+        TypeExpr filterFalseCaseType = inputType.main.and(filterRes.not());
+        if (step.getFalseBranch() != null) {
+            return analyse(step.getFalseBranch(), inputType.setMain(filterFalseCaseType));
+        } else {
+            return inputType.setMain(filterFalseCaseType);
+        }
+    }
+
+    @Override
+    public AltTypeExpr visit(FilterStep<?, ?> step, AltTypeExpr inputType) {
+        if (step.isWarning()) {
+            return inputType;
+        } else {
+            return inputType.setMain(inputType.main.and(visitFilter(step.getFilter(), inputType.main)));
+        }
+    }
+
+    @Override
+    public AltTypeExpr visit(NotNAStep<?> step, AltTypeExpr inputType) {
+        Set<Object> naSamples = inputType.main.toNormalizedConjunctionSet().stream().filter(t -> t instanceof Class).map(t -> CastUtils.naValue((Class<?>) t)).filter(x -> x != null).collect(
+                        Collectors.toSet());
+        TypeExpr resType = inputType.main.lower(step);
+        resType = resType.negativeSamples(naSamples);
+        if (step.getReplacement() != null) {
+            resType = resType.positiveSamples(step.getReplacement());
+        }
+        return inputType.setMain(resType);
+    }
+
+    @Override
+    public AltTypeExpr visit(DefaultErrorStep<?> step, AltTypeExpr inputType) {
+        return inputType;
+    }
+
+    @Override
+    public AltTypeExpr visit(DefaultWarningStep<?> step, AltTypeExpr inputType) {
+        return inputType;
+    }
+
+    @Override
+    public AltTypeExpr visit(BoxPrimitiveStep<?> step, AltTypeExpr inputType) {
+        TypeExpr res = TypeExpr.union(RNull.class, RMissing.class, RInteger.class, RLogical.class, RDouble.class, RString.class);
+        return inputType.setMain(res.or(res.not()));
+    }
+
+    @Override
+    public AltTypeExpr visit(AttributableCoercionStep<?> step, AltTypeExpr inputType) {
+        return inputType.setMain(inferResultTypeFromSpecializations(CastToAttributableNode.class, inputType.main));
+    }
+
+    // MapperVisitor
+
+    @Override
+    public TypeExpr visit(MapToValue<?, ?> mapper, TypeExpr inputType) {
+        return atom(mapper.getValue().getClass()).lower(mapper);
+    }
+
+    @Override
+    public TypeExpr visit(MapByteToBoolean mapper, TypeExpr inputType) {
+        return atom(Boolean.class);
+    }
+
+    @Override
+    public TypeExpr visit(MapDoubleToInt mapper, TypeExpr inputType) {
+        return atom(Integer.class);
+    }
+
+    @Override
+    public TypeExpr visit(MapToCharAt mapper, TypeExpr inputType) {
+        return atom(Integer.class);
+    }
+
+    // FilterVisitor
+
+    private TypeExpr visitFilter(Filter<?, ?> filter, TypeExpr inputType) {
+        return filter.accept(this, inputType);
+    }
+
+    @Override
+    public TypeExpr visit(TypeFilter<?, ?> filter, TypeExpr inputType) {
+        TypeExpr resTp = atom(filter.getType1());
+        if (filter.getType2() != null) {
+            resTp = resTp.or(atom(filter.getType2()));
+        }
+        return resTp.and(atom(RNull.class).not().and(atom(RMissing.class).not()));
+    }
+
+    @Override
+    public TypeExpr visit(RTypeFilter<?> filter, TypeExpr previous) {
+        switch (filter.getType()) {
+            case Integer:
+                return visit(new TypeFilter<>(Integer.class, RAbstractIntVector.class), previous);
+            case Double:
+                return visit(new TypeFilter<>(Double.class, RAbstractDoubleVector.class), previous);
+            case Logical:
+                return visit(new TypeFilter<>(Byte.class, RAbstractLogicalVector.class), previous);
+            case Complex:
+                return visit(new TypeFilter<>(RAbstractComplexVector.class), previous);
+            case Character:
+                return visit(new TypeFilter<>(String.class, RAbstractStringVector.class), previous);
+            case Raw:
+                return visit(new TypeFilter<>(RAbstractRawVector.class), previous);
+            default:
+                throw RInternalError.unimplemented("TODO: more types here");
+        }
+    }
+
+    @Override
+    public TypeExpr visit(CompareFilter<?> filter, TypeExpr previous) {
+        return filter.getSubject().accept(this, filter.getOperation(), previous).lower(filter);
+    }
+
+    @Override
+    public TypeExpr visit(AndFilter<?, ?> filter, TypeExpr previous) {
+        TypeExpr res1 = visitFilter(filter.getLeft(), previous);
+        TypeExpr res2 = visitFilter(filter.getRight(), res1);
+        TypeExpr res = res1.and(res2);
+        return res;
+    }
+
+    @Override
+    public TypeExpr visit(OrFilter<?> filter, TypeExpr previous) {
+        TypeExpr res1 = visitFilter(filter.getLeft(), previous);
+        TypeExpr res2 = visitFilter(filter.getRight(), previous);
+        TypeExpr res = res1.or(res2);
+        return res;
+    }
+
+    @Override
+    public TypeExpr visit(NotFilter<?> filter, TypeExpr previous) {
+        return visitFilter(filter.getFilter(), previous).not();
+    }
+
+    @Override
+    public TypeExpr visit(MatrixFilter<?> filter, TypeExpr previous) {
+        return previous.lower(filter);
+    }
+
+    @Override
+    public TypeExpr visit(DoubleFilter filter, TypeExpr previous) {
+        return previous.lower(filter);
+    }
+
+    @Override
+    public TypeExpr visit(NullFilter filter, TypeExpr previous) {
+        TypeExpr res = atom(RNull.class);
+        return res;
+    }
+
+    @Override
+    public TypeExpr visit(MissingFilter filter, TypeExpr previous) {
+        TypeExpr res = atom(RMissing.class);
+        return res;
+    }
+
+    // CompareFilter.SubjectVisitor
+
+    @Override
+    public TypeExpr visit(ScalarValue scalarValue, byte operation, TypeExpr previous) {
+        return visitRType(scalarValue.type);
+    }
+
+    private static TypeExpr visitRType(RType type) {
+        switch (type) {
+            case Integer:
+                return atom(Integer.class);
+            case Double:
+                return atom(Double.class);
+            case Logical:
+                return atom(Byte.class);
+            case Complex:
+                return atom(RComplex.class);
+            case Character:
+                return atom(String.class);
+            case Raw:
+                return atom(RRaw.class);
+            case Any:
+                return TypeExpr.ANYTHING;
+            default:
+                throw RInternalError.unimplemented("Unexpected type: " + type);
+        }
+    }
+
+    @Override
+    public TypeExpr visit(NATest naTest, byte operation, TypeExpr previous) {
+        return visitRType(naTest.type);
+    }
+
+    @Override
+    public TypeExpr visit(StringLength stringLength, byte operation, TypeExpr previous) {
+        return previous;
+    }
+
+    @Override
+    public TypeExpr visit(VectorSize vectorSize, byte operation, TypeExpr previous) {
+        return previous;
+    }
+
+    @Override
+    public TypeExpr visit(ElementAt elementAt, byte operation, TypeExpr previous) {
+        return previous;
+    }
+
+    @Override
+    public TypeExpr visit(Dim dim, byte operation, TypeExpr previous) {
+        return previous;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java
index 3a65ebcc6d..63a2205440 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Samples.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.casts;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Optional;
@@ -49,13 +50,13 @@ public final class Samples<T> {
         return (Samples<T>) NOTHING;
     }
 
-    private final Set<? extends T> posSamples;
-    private final Set<?> negSamples;
+    private final Set<Object> posSamples;
+    private final Set<Object> negSamples;
     private final Predicate<Object> posMembership;
     private final Predicate<Object> negMembership;
     private final String name;
 
-    public Samples(String name, Set<? extends T> positiveSamples, Set<?> negativeSamples, Predicate<Object> posMembership) {
+    public Samples(String name, Set<Object> positiveSamples, Set<Object> negativeSamples, Predicate<Object> posMembership) {
         this.name = name;
         this.posSamples = positiveSamples;
         this.negSamples = negativeSamples;
@@ -63,7 +64,7 @@ public final class Samples<T> {
         this.negMembership = CastUtils.instrument(this.posMembership.negate(), "neg(" + name + ")");
     }
 
-    private Samples(String name, Set<? extends T> positiveSamples, Set<?> negativeSamples, Predicate<Object> posMembership, Predicate<Object> negMembership) {
+    private Samples(String name, Set<Object> positiveSamples, Set<Object> negativeSamples, Predicate<Object> posMembership, Predicate<Object> negMembership) {
         this.name = name;
         this.posSamples = positiveSamples;
         this.negSamples = negativeSamples;
@@ -71,11 +72,23 @@ public final class Samples<T> {
         this.negMembership = CastUtils.instrument(negMembership, "neg(" + name + ")");
     }
 
-    public Set<? extends T> positiveSamples() {
+    public Samples<T> addPositiveSamples(Object... sampleValues) {
+        Set<Object> newPosSamples = new HashSet<>(Arrays.asList(sampleValues));
+        newPosSamples.addAll(posSamples);
+        return new Samples<>(name, newPosSamples, negSamples, posMembership, negMembership);
+    }
+
+    public Samples<T> addNegativeSamples(Object... sampleValues) {
+        Set<Object> newNegSamples = new HashSet<>(Arrays.asList(sampleValues));
+        newNegSamples.addAll(negSamples);
+        return new Samples<>(name, posSamples, newNegSamples, posMembership, negMembership);
+    }
+
+    public Set<Object> positiveSamples() {
         return posSamples;
     }
 
-    public Set<?> negativeSamples() {
+    public Set<Object> negativeSamples() {
         return negSamples;
     }
 
@@ -85,11 +98,11 @@ public final class Samples<T> {
         return all;
     }
 
-    public <R> Samples<R> map(Function<T, R> posMapper, Function<Object, Object> negMapper, Function<Object, Optional<T>> posUnmapper, Function<Object, Optional<Object>> negUnmapper) {
-        Set<R> mappedPositive = positiveSamples().stream().map(posMapper).collect(Collectors.toSet());
+    public <R> Samples<R> map(Function<Object, R> posMapper, Function<Object, Object> negMapper, Function<Object, Optional<Object>> posUnmapper, Function<Object, Optional<Object>> negUnmapper) {
+        Set<Object> mappedPositive = positiveSamples().stream().map(posMapper).collect(Collectors.toSet());
         Set<Object> mappedNegative = negativeSamples().stream().map(negMapper).collect(Collectors.toSet());
         return new Samples<>(name + ".map", mappedPositive, mappedNegative, x -> {
-            Optional<T> um = posUnmapper.apply(x);
+            Optional<Object> um = posUnmapper.apply(x);
             return um.isPresent() ? posMembership.test(um.get()) : false;
         }, x -> {
             Optional<Object> um = negUnmapper.apply(x);
@@ -102,14 +115,13 @@ public final class Samples<T> {
     }
 
     public Samples<T> filter(Predicate<Object> newPosCondition, Predicate<Object> newNegCondition) {
-        Set<T> newPositive = positiveSamples().stream().filter(newPosCondition).collect(Collectors.toSet());
+        Set<Object> newPositive = positiveSamples().stream().filter(newPosCondition).collect(Collectors.toSet());
         Set<Object> newNegative = negativeSamples().stream().filter(newNegCondition).collect(Collectors.toSet());
         return new Samples<>(name + ".filter", newPositive, newNegative, x -> posMembership.test(x) && newPosCondition.test(x),
                         x -> negMembership.test(x) && newNegCondition.test(x));
     }
 
-    @SuppressWarnings("unchecked")
-    public Samples<T> and(Samples<? extends T> other) {
+    public Samples<T> and(Samples<?> other) {
         String newName = "and(" + name + "," + other.name + ")";
 
         Set<Object> negativeUnion = new HashSet<>(other.negativeSamples());
@@ -126,10 +138,9 @@ public final class Samples<T> {
         Predicate<Object> newPosCondition = CastUtils.instrument(posMembership.and(other.posMembership), "and-pos");
         positiveUnion.removeIf(CastUtils.instrument(newPosCondition.negate(), "pruningPosUnion:" + newName));
 
-        return new Samples<>(newName, (Set<T>) positiveUnion, negativeUnion, newPosCondition, newNegCondition);
+        return new Samples<>(newName, positiveUnion, negativeUnion, newPosCondition, newNegCondition);
     }
 
-    @SuppressWarnings("unchecked")
     public Samples<T> or(Samples<?> other) {
         String newName = "or(" + name + "," + other.name + ")";
 
@@ -147,7 +158,7 @@ public final class Samples<T> {
         Predicate<Object> newPosCondition = CastUtils.instrument(posMembership.or(other.posMembership), "or-neg");
         positiveUnion.removeIf(CastUtils.instrument(newPosCondition.negate(), "pruningPosUnion:" + newName));
 
-        return new Samples<>(newName, (Set<T>) positiveUnion, negativeUnion, newPosCondition, newNegCondition);
+        return new Samples<>(newName, positiveUnion, negativeUnion, newPosCondition, newNegCondition);
     }
 
     public Samples<Object> swap() {
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
new file mode 100644
index 0000000000..ed55cf5d82
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.casts;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import com.oracle.truffle.r.nodes.builtin.casts.ExecutionPathVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.Dim;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ElementAt;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.NATest;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.StringLength;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.VectorSize;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.FilterVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.MatrixFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapDoubleToInt;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToCharAt;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapToValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public class SamplesCollector extends ExecutionPathVisitor<Consumer<Object>>
+                implements FilterVisitor<Consumer<Object>>, CompareFilter.SubjectVisitor<Consumer<Object>>, MapperVisitor<Consumer<Object>> {
+
+    public static Set<Object> collect(PipelineStep<?, ?> firstStep) {
+        Set<Object> samples = new HashSet<>();
+        collect(firstStep, s -> samples.add(s));
+        return samples;
+    }
+
+    public static Consumer<Object> collect(PipelineStep<?, ?> firstStep, Consumer<Object> initial) {
+        List<Consumer<Object>> pathResults = new SamplesCollector().visitPaths(firstStep, initial);
+        return pathResults.stream().reduce((x, y) -> s -> {
+            x.accept(s);
+            y.accept(s);
+        }).get();
+    }
+
+    @Override
+    public Consumer<Object> visit(FindFirstStep<?, ?> step, Consumer<Object> previous) {
+        if (step.getDefaultValue() != null) {
+            previous.accept(step.getDefaultValue());
+            previous.accept(RNull.instance);
+            previous.accept(RMissing.instance);
+        }
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(CoercionStep<?, ?> step, Consumer<Object> previous) {
+        Set<?> samples = CastUtils.sampleValuesForClasses(CastUtils.rTypeToClasses(step.getType()));
+        for (Object s : samples) {
+            previous.accept(s);
+        }
+
+        previous.accept(RNull.instance);
+        previous.accept(RMissing.instance);
+
+        return s -> {
+            if (s instanceof VectorPlaceholder) {
+                previous.accept(CastUtils.vectorOfSize(step.type, ((VectorPlaceholder) s).size));
+            } else {
+                previous.accept(s);
+            }
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MapStep<?, ?> step, Consumer<Object> previous) {
+        previous.accept(RNull.instance);
+        previous.accept(RMissing.instance);
+
+        return step.getMapper().accept(this, previous);
+    }
+
+    @Override
+    protected Consumer<Object> visitBranch(MapIfStep<?, ?> step, Consumer<Object> previous, boolean visitTrueBranch) {
+
+        Consumer<Object> filterConsumer = step.getFilter().accept(this, s -> previous.accept(s));
+
+        PipelineStep<?, ?> branch;
+        if (visitTrueBranch) {
+            branch = step.getTrueBranch();
+        } else {
+            branch = step.getFalseBranch();
+        }
+        Consumer<Object> branchSampler = branch != null ? collect(branch, s -> {
+            filterConsumer.accept(s);
+        }) : s -> filterConsumer.accept(s);
+        return s -> {
+            branchSampler.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(FilterStep<?, ?> step, Consumer<Object> previous) {
+        previous.accept(RNull.instance);
+        previous.accept(RMissing.instance);
+
+        Consumer<Object> filterConsumer = step.getFilter().accept(this, s -> previous.accept(s));
+
+        return s -> {
+            filterConsumer.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(NotNAStep<?> step, Consumer<Object> previous) {
+        previous.accept(RRuntime.INT_NA);
+        previous.accept(RRuntime.DOUBLE_NA);
+        previous.accept(RRuntime.LOGICAL_NA);
+        previous.accept(RRuntime.STRING_NA);
+        previous.accept(RRuntime.LOGICAL_NA);
+        previous.accept(RDataFactory.createComplex(RRuntime.COMPLEX_NA_REAL_PART, 0));
+
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(DefaultErrorStep<?> step, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(DefaultWarningStep<?> step, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(BoxPrimitiveStep<?> step, Consumer<Object> previous) {
+        previous.accept(0);
+        previous.accept(0.0);
+        previous.accept((byte) 0);
+        previous.accept("");
+        previous.accept(RNull.instance);
+        previous.accept(RMissing.instance);
+
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(AttributableCoercionStep<?> step, Consumer<Object> previous) {
+        previous.accept(RDataFactory.createInternalEnv());
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MapToValue<?, ?> mapper, Consumer<Object> previous) {
+        return s -> {
+            // no inverse mapping for constants
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MapByteToBoolean mapper, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(RRuntime.asLogical((Boolean) s));
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MapDoubleToInt mapper, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(((Integer) s).doubleValue());
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MapToCharAt mapper, Consumer<Object> previous) {
+        previous.accept(sampleString(mapper.getIndex()) + (char) mapper.getDefaultValue());
+        return s -> {
+            previous.accept(("" + (char) s));
+        };
+    }
+
+    // Filter visitor
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    public Consumer<Object> visit(TypeFilter<?, ?> filter, Consumer<Object> previous) {
+        Class<?>[] filterTypes = new Class[]{filter.getType1(), filter.getType2()};
+        Set<?> samples = CastUtils.sampleValuesForClasses(filterTypes);
+        for (Object s : samples) {
+            previous.accept(s);
+        }
+        // a negative sample
+        previous.accept(RNull.instance);
+
+        return s -> {
+            if (s instanceof VectorPlaceholder) {
+                previous.accept(CastUtils.vectorOfSize(filter.getType1(), ((VectorPlaceholder) s).size));
+            } else {
+                previous.accept(s);
+            }
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(RTypeFilter<?> filter, Consumer<Object> previous) {
+        Class<?>[] cls = CastUtils.rTypeToClasses(filter.getType());
+        if (cls != null) {
+            TypeFilter<?, ?> tf = cls.length == 1 ? new TypeFilter<>(cls[0]) : new TypeFilter<>(cls[0], cls[1]);
+            visit(tf, previous);
+        }
+
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(CompareFilter<?> filter, Consumer<Object> previous) {
+        Consumer<Object> comparisonConsumer = filter.getSubject().accept(this, filter.getOperation(), previous);
+
+        return s -> {
+            comparisonConsumer.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(AndFilter<?, ?> filter, Consumer<Object> previous) {
+        Consumer<Object> leftConsumer = filter.getLeft().accept(this, s -> previous.accept(s));
+        Consumer<Object> rightConsumer = filter.getRight().accept(this, s -> leftConsumer.accept(s));
+
+        return s -> {
+            rightConsumer.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(OrFilter<?> filter, Consumer<Object> previous) {
+        Consumer<Object> leftConsumer = filter.getLeft().accept(this, s -> previous.accept(s));
+        Consumer<Object> rightConsumer = filter.getRight().accept(this, s -> leftConsumer.accept(s));
+
+        return s -> {
+            rightConsumer.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(NotFilter<?> filter, Consumer<Object> previous) {
+        Consumer<Object> notConsumer = filter.getFilter().accept(this, s -> previous.accept(s));
+
+        return s -> {
+            notConsumer.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MatrixFilter<?> filter, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(DoubleFilter filter, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(NullFilter filter, Consumer<Object> previous) {
+        previous.accept(RNull.instance);
+
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(MissingFilter filter, Consumer<Object> previous) {
+        previous.accept(RMissing.instance);
+
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    // Subject of comparison visitor
+
+    @Override
+    public Consumer<Object> visit(ScalarValue scalarValue, byte operation, Consumer<Object> previous) {
+        previous.accept(scalarValue.value);
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(NATest naTest, byte operation, Consumer<Object> previous) {
+        switch (naTest.type) {
+            case Integer:
+                previous.accept(RRuntime.INT_NA);
+                break;
+            case Double:
+                previous.accept(RRuntime.DOUBLE_NA);
+                break;
+            case Logical:
+                previous.accept(RRuntime.LOGICAL_NA);
+                break;
+            case Character:
+                previous.accept(RRuntime.STRING_NA);
+                break;
+            case Complex:
+                previous.accept(RDataFactory.createComplex(RRuntime.COMPLEX_NA_REAL_PART, 0));
+                break;
+            default:
+                throw RInternalError.shouldNotReachHere();
+        }
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(StringLength stringLength, byte operation, Consumer<Object> previous) {
+        previous.accept(sampleString(stringLength.length));
+        // a negative sample
+        previous.accept(sampleString(stringLength.length + 1));
+
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    private static String sampleString(int len) {
+        if (len < 0) {
+            return null;
+        } else if (len == 0) {
+            return "";
+        } else {
+            char[] ch = new char[len];
+            Arrays.fill(ch, 'a');
+            return String.valueOf(ch);
+        }
+    }
+
+    @Override
+    public Consumer<Object> visit(VectorSize vectorSize, byte operation, Consumer<Object> previous) {
+        int s = vectorSize.size;
+        switch (operation) {
+            case CompareFilter.EQ:
+                previous.accept(new VectorPlaceholder(s));
+                // a negative sample
+                previous.accept(new VectorPlaceholder(s + 1));
+                break;
+            case CompareFilter.GT:
+                previous.accept(new VectorPlaceholder(s + 1));
+                // a negative sample
+                previous.accept(new VectorPlaceholder(s));
+                break;
+            case CompareFilter.LT:
+                previous.accept(new VectorPlaceholder(s - 1));
+                // a negative sample
+                previous.accept(new VectorPlaceholder(s));
+                break;
+            case CompareFilter.GE:
+                previous.accept(new VectorPlaceholder(s));
+                // a negative sample
+                previous.accept(new VectorPlaceholder(s - 1));
+                break;
+            case CompareFilter.LE:
+                previous.accept(new VectorPlaceholder(s));
+                // a negative sample
+                previous.accept(new VectorPlaceholder(s + 1));
+                break;
+            default:
+                throw RInternalError.shouldNotReachHere();
+        }
+
+        return sample -> {
+            previous.accept(sample);
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(ElementAt elementAt, byte operation, Consumer<Object> previous) {
+        RAbstractVector vec = CastUtils.fillVector(elementAt.type, elementAt.index + 1, elementAt.value, true);
+        previous.accept(vec);
+
+        // a negative sample
+        vec = CastUtils.fillVector(elementAt.type, elementAt.index, elementAt.value, true);
+        previous.accept(vec);
+
+        return s -> {
+            if (s instanceof VectorPlaceholder) {
+                VectorPlaceholder vectorPlaceholder = (VectorPlaceholder) s;
+                if (elementAt.index < vectorPlaceholder.size) {
+                    previous.accept(CastUtils.fillVector(elementAt.type, vectorPlaceholder.size, elementAt.value, true));
+                } else {
+                    previous.accept(s);
+                }
+            } else {
+                previous.accept(s);
+            }
+        };
+    }
+
+    @Override
+    public Consumer<Object> visit(Dim dim, byte operation, Consumer<Object> previous) {
+        return s -> {
+            previous.accept(s);
+        };
+    }
+
+    private static final class VectorPlaceholder {
+        final int size;
+
+        VectorPlaceholder(int size) {
+            this.size = size;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
index d9c58b6939..e5b115a553 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
@@ -28,46 +28,72 @@ import java.util.Optional;
 
 import com.oracle.truffle.r.nodes.casts.CastUtils.Cast;
 import com.oracle.truffle.r.nodes.casts.CastUtils.Cast.Coverage;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.nodes.casts.CastUtils.Casts;
 
 public interface TypeAndInstanceCheck {
     boolean isInstance(Object x);
 
+    static boolean isInstance(Type t, Object x) {
+        if (t instanceof Class) {
+            return ((Class<?>) t).isInstance(x);
+        } else if (t instanceof TypeAndInstanceCheck) {
+            return ((TypeAndInstanceCheck) t).isInstance(x);
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
     Optional<Class<?>> classify();
 
+    Type normalize();
+
     static Coverage coverage(Type from, Type to, boolean includeImplicits) {
-        assert (to instanceof Not || to instanceof Class);
         assert (from instanceof Not || from instanceof Class);
+        assert (to instanceof Not || to instanceof Class);
 
         if (Not.negateType(to).equals(from)) {
             return Coverage.none;
         }
 
-        boolean toPositive = !Not.isNegative(to);
         boolean fromPositive = !Not.isNegative(from);
-        Class<?> positiveToCls = (Class<?>) CastUtils.Casts.boxType(Not.getPositiveType(to));
-        Class<?> positiveFromCls = (Class<?>) CastUtils.Casts.boxType(Not.getPositiveType(from));
-
+        boolean toPositive = !Not.isNegative(to);
+        Type posFrom = Not.getPositiveType(from);
+        Type posTo = Not.getPositiveType(to);
         Cast.Coverage positiveCoverage;
-        if (((Class<?>) positiveToCls).isAssignableFrom(positiveFromCls)) {
-            positiveCoverage = Cast.Coverage.full;
-        } else if (((Class<?>) positiveFromCls).isAssignableFrom(positiveToCls)) {
-            positiveCoverage = Cast.Coverage.partial;
-        } else if (positiveToCls.isInterface() && (positiveFromCls.isInterface() || !(Modifier.isFinal(positiveFromCls.getModifiers()) || !Modifier.isAbstract(positiveFromCls.getModifiers())))) {
-            positiveCoverage = Cast.Coverage.potential;
-        } else if (positiveFromCls.isInterface() && (positiveToCls.isInterface() || !(Modifier.isFinal(positiveToCls.getModifiers()) || !Modifier.isAbstract(positiveToCls.getModifiers())))) {
-            positiveCoverage = Cast.Coverage.potential;
+        if (posFrom instanceof UpperBoundsConjunction) {
+            positiveCoverage = ((UpperBoundsConjunction) posFrom).coverageTo(posTo, includeImplicits);
+            return positiveCoverage.transpose(posFrom, posTo, fromPositive, toPositive);
+        } else if (posTo instanceof UpperBoundsConjunction) {
+            positiveCoverage = ((UpperBoundsConjunction) posTo).coverageFrom(UpperBoundsConjunction.fromType(posFrom), includeImplicits);
+            return positiveCoverage.transpose(posFrom, posTo, fromPositive, toPositive);
         } else {
-            positiveCoverage = Cast.Coverage.none;
-        }
+            Class<?> positiveFromCls = (Class<?>) CastUtils.Casts.boxType(posFrom);
+            Class<?> positiveToCls = (Class<?>) CastUtils.Casts.boxType(posTo);
 
-        Cast.Coverage implicitCvrg = Cast.Coverage.none;
-        if (includeImplicits && Casts.hasImplicitCast(positiveFromCls, positiveToCls)) {
-            implicitCvrg = Cast.Coverage.potential;
-        }
+            if (TypeExpr.areMutuallyExclusive(positiveToCls, positiveFromCls)) {
+                positiveCoverage = Cast.Coverage.none;
+            } else if (((Class<?>) positiveToCls).isAssignableFrom(positiveFromCls)) {
+                positiveCoverage = Cast.Coverage.full;
+            } else if (((Class<?>) positiveFromCls).isAssignableFrom(positiveToCls)) {
+                positiveCoverage = Cast.Coverage.partial;
+            } else if (positiveToCls.isInterface() && (positiveFromCls.isInterface() || !(Modifier.isFinal(positiveFromCls.getModifiers()) || !Modifier.isAbstract(positiveFromCls.getModifiers())))) {
+                positiveCoverage = Cast.Coverage.potential;
+            } else if (positiveFromCls.isInterface() && (positiveToCls.isInterface() || !(Modifier.isFinal(positiveToCls.getModifiers()) || !Modifier.isAbstract(positiveToCls.getModifiers())))) {
+                positiveCoverage = Cast.Coverage.potential;
+            } else {
+                positiveCoverage = Cast.Coverage.none;
+            }
 
-        positiveCoverage = implicitCvrg.or(positiveCoverage);
+            Cast.Coverage implicitCvrg = Cast.Coverage.none;
+            if (includeImplicits && Casts.hasImplicitCast(positiveFromCls, positiveToCls)) {
+                implicitCvrg = Cast.Coverage.potential;
+            }
+
+            positiveCoverage = implicitCvrg.or(positiveCoverage);
+
+            return positiveCoverage.transpose(positiveFromCls, positiveToCls, fromPositive, toPositive);
+        }
 
-        return positiveCoverage.transpose(positiveFromCls, positiveToCls, fromPositive, toPositive);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java
deleted file mode 100644
index 6e56be18be..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeConjunction.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import java.lang.reflect.Type;
-import java.lang.reflect.WildcardType;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import com.oracle.truffle.r.nodes.casts.CastUtils.Cast.Coverage;
-
-public final class TypeConjunction implements WildcardType, TypeAndInstanceCheck {
-
-    private final Set<Type> upperBounds;
-
-    TypeConjunction(Set<Type> upperBounds) {
-        this.upperBounds = new HashSet<>(upperBounds);
-    }
-
-    public static TypeConjunction create(Type... types) {
-        Set<Type> upperBounds = Arrays.asList(types).stream().flatMap(t -> (t instanceof TypeConjunction ? ((TypeConjunction) t).upperBounds : Collections.singleton(t)).stream()).collect(
-                        Collectors.toSet());
-        return new TypeConjunction(upperBounds);
-    }
-
-    public static TypeConjunction fromType(Type t) {
-        if (t instanceof TypeConjunction) {
-            return (TypeConjunction) t;
-        } else {
-            return new TypeConjunction(Collections.singleton(t));
-        }
-    }
-
-    @Override
-    public Type[] getUpperBounds() {
-        return upperBounds.toArray(new Type[upperBounds.size()]);
-    }
-
-    @Override
-    public Type[] getLowerBounds() {
-        return new Type[0];
-    }
-
-    @Override
-    public boolean isInstance(Object x) {
-        return upperBounds.stream().filter(t -> ((TypeAndInstanceCheck) t).isInstance(x)).findAny().isPresent();
-    }
-
-    public Coverage coverageFrom(TypeConjunction from, boolean includeImplicits) {
-        return upperBounds.stream().map(ubt -> from.coverageTo(ubt, includeImplicits)).reduce((res, cvg) -> cvg.and(res)).orElse(Coverage.none);
-    }
-
-    public Coverage coverageTo(Type to, boolean includeImplicits) {
-        assert to instanceof Not || to instanceof Class;
-        return upperBounds.stream().map(ubt -> TypeAndInstanceCheck.coverage(ubt, to, includeImplicits)).reduce(
-                        (res, cvg) -> res == Coverage.none || cvg == Coverage.none ? Coverage.none : cvg.or(res)).orElse(Coverage.none);
-    }
-
-    @Override
-    public Optional<Class<?>> classify() {
-        Set<Class<?>> classes = upperBounds.stream().filter(t -> t instanceof Class<?>).map(t -> (Class<?>) t).collect(Collectors.toSet());
-        return classes.size() == 1 ? Optional.of(classes.iterator().next()) : Optional.empty();
-    }
-
-    @Override
-    public String toString() {
-        return "(? extends " + upperBounds + ")";
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((upperBounds == null) ? 0 : upperBounds.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        TypeConjunction other = (TypeConjunction) obj;
-        return upperBounds.equals(other.upperBounds);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java
index 7f8ca9c660..d156a5156a 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeExpr.java
@@ -28,21 +28,70 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import com.oracle.truffle.r.nodes.casts.CastUtils.Cast;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public final class TypeExpr {
 
     public static final TypeExpr ANYTHING = TypeExpr.atom(Object.class);
-    public static final TypeExpr NOTHING = new TypeExpr(Collections.emptySet());
+    public static final TypeExpr NOTHING = new TypeExpr(Collections.emptySet(), Samples.nothing());
 
-    private final Set<Set<? extends Type>> disjNormForm;
+    private final Set<Set<Type>> disjNormForm;
 
-    private TypeExpr(Set<Set<? extends Type>> disjNormForm) {
-        this.disjNormForm = disjNormForm;
+    private final Samples<?> samples;
+
+    private static final Set<Set<Class<?>>> mutuallyExclusiveInterfaces = new HashSet<>();
+
+    static {
+        registerMutuallyExclusiveInterfaces(RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class, RAbstractRawVector.class,
+                        RAbstractStringVector.class, RAbstractListVector.class);
+    }
+
+    private TypeExpr(Set<Set<Type>> disjNormForm, Samples<?> samples) {
+        // remove contradictions
+        // Set<Set<Type>> noContra = disjNormForm.stream().filter(conj ->
+        // !isContradiction(conj)).collect(Collectors.toSet());
+        Set<Set<Type>> noContra = disjNormForm.stream().map(conj -> normalizeConjunctionSet(conj)).filter(conj -> !conj.isEmpty()).collect(Collectors.toSet());
+        this.disjNormForm = noContra;
+        this.samples = samples;
+    }
+
+    public static void registerMutuallyExclusiveInterfaces(Class<?>... types) {
+        mutuallyExclusiveInterfaces.add(Arrays.stream(types).collect(Collectors.toSet()));
+    }
+
+    public static Optional<Class<?>> findInMutuallyExclusiveInterfaces(Type t, Set<Class<?>> exclusiveGroup) {
+        if (t instanceof Class) {
+            return exclusiveGroup.stream().filter(x -> x.isAssignableFrom((Class<?>) t)).findFirst();
+        } else {
+            return Optional.empty();
+        }
+    }
+
+    public static boolean areMutuallyExclusiveInterfaces(Type t1, Type t2, Set<Class<?>> exclusiveGroup) {
+        Optional<Class<?>> x1 = findInMutuallyExclusiveInterfaces(t1, exclusiveGroup);
+        if (!x1.isPresent()) {
+            return false;
+        }
+        Optional<Class<?>> x2 = findInMutuallyExclusiveInterfaces(t2, exclusiveGroup);
+        if (!x2.isPresent()) {
+            return false;
+        }
+
+        return x1.get() != x2.get();
+    }
+
+    public static boolean areMutuallyExclusive(Type t1, Type t2) {
+        return mutuallyExclusiveInterfaces.stream().filter(exclusiveTypesSet -> areMutuallyExclusiveInterfaces(t1, t2, exclusiveTypesSet)).findFirst().isPresent();
     }
 
     public boolean isNothing() {
@@ -59,19 +108,8 @@ public final class TypeExpr {
     }
 
     public static TypeExpr atom(Type t) {
-        return new TypeExpr(Collections.singleton(Collections.singleton(t)));
-    }
-
-    public TypeExpr map(Function<Type, Type> typeMapper) {
-        Set<Set<? extends Type>> newDisjNormForm = disjNormForm.stream().map(conj -> conj.stream().map(typeMapper).collect(Collectors.toSet())).collect(Collectors.toSet());
-        return new TypeExpr(newDisjNormForm);
-    }
-
-    public TypeExpr filter(Predicate<Type> filterPred) {
-        Set<Set<? extends Type>> newDisjNormForm = disjNormForm.stream().map(conjSet -> {
-            return conjSet.stream().filter(filterPred).collect(Collectors.toSet());
-        }).filter(newConjSet -> !newConjSet.isEmpty()).collect(Collectors.toSet());
-        return new TypeExpr(newDisjNormForm);
+        Samples<?> samples = new Samples<>(t.getTypeName(), Collections.emptySet(), Collections.emptySet(), x -> TypeAndInstanceCheck.isInstance(t, x));
+        return new TypeExpr(Collections.singleton(Collections.singleton(t)), samples);
     }
 
     public boolean contains(Type tp) {
@@ -79,15 +117,15 @@ public final class TypeExpr {
     }
 
     public TypeExpr or(TypeExpr te) {
-        Set<Set<? extends Type>> newDisjNormForm = new HashSet<>(this.disjNormForm);
+        Set<Set<Type>> newDisjNormForm = new HashSet<>(this.disjNormForm);
         newDisjNormForm.addAll(te.disjNormForm);
-        return new TypeExpr(newDisjNormForm);
+        return new TypeExpr(newDisjNormForm, samples.or(te.samples));
     }
 
     public TypeExpr and(TypeExpr te) {
-        Set<Set<? extends Type>> newDisjNormForm = new HashSet<>();
+        Set<Set<Type>> newDisjNormForm = new HashSet<>();
 
-        for (Set<? extends Type> conj1 : this.disjNormForm) {
+        for (Set<Type> conj1 : this.disjNormForm) {
             for (Set<? extends Type> conj2 : te.disjNormForm) {
                 Set<Type> newConj = new HashSet<>(conj1);
                 newConj.addAll(conj2);
@@ -95,12 +133,71 @@ public final class TypeExpr {
             }
         }
 
-        return new TypeExpr(newDisjNormForm);
+        return new TypeExpr(newDisjNormForm, samples.and(te.samples));
+    }
+
+    public TypeExpr lower() {
+        return lower(new Object());
+    }
+
+    public TypeExpr removeWildcards() {
+        Set<Set<Type>> newDisjNormForm = new HashSet<>();
+
+        for (Set<Type> conj : this.disjNormForm) {
+            newDisjNormForm.add(removeWildcardsFromConj(conj));
+        }
+
+        return new TypeExpr(newDisjNormForm, samples);
+    }
+
+    private static Set<Type> removeWildcardsFromConj(Set<Type> conj) {
+        Set<Type> newConj = new HashSet<>();
+
+        for (Type t : conj) {
+            if (t instanceof Not) {
+                Type neg = ((Not<?>) t).getNegated();
+                if (!(neg instanceof UpperBoundsConjunction && ((UpperBoundsConjunction) neg).isWildcard())) {
+                    newConj.add(t);
+                } // the negation degenerates to Object.class as long as the negated type is a
+                  // wildcard type
+            } else if (t instanceof UpperBoundsConjunction) {
+                Set<Type> flattened = ((UpperBoundsConjunction) t).flatten();
+                flattened = removeWildcardsFromConj(flattened);
+                newConj.addAll(flattened);
+            } else {
+                newConj.add(t);
+            }
+        }
+
+        return newConj;
+    }
+
+    public TypeExpr positiveSamples(Object... sampleValues) {
+        return new TypeExpr(disjNormForm, samples.addPositiveSamples(sampleValues));
+    }
+
+    public TypeExpr negativeSamples(Object... sampleValues) {
+        return new TypeExpr(disjNormForm, samples.addNegativeSamples(sampleValues));
+    }
+
+    public TypeExpr lower(Object typeRepr) {
+        Set<Set<Type>> newDisjNormForm = new HashSet<>();
+
+        for (Set<Type> conj : disjNormForm) {
+            UpperBoundsConjunction upperConj = UpperBoundsConjunction.create(conj.stream()).asWildcard(typeRepr);
+            newDisjNormForm.add(Collections.singleton(upperConj));
+        }
+
+        return new TypeExpr(newDisjNormForm, samples);
     }
 
-    public static TypeExpr union(Set<? extends Type> types) {
-        Set<Set<? extends Type>> disjNormForm = types.stream().map(t -> Collections.singleton(t)).collect(Collectors.toSet());
-        return new TypeExpr(disjNormForm);
+    public static TypeExpr union(Set<Type> types) {
+        Set<Set<Type>> disjNormForm = types.stream().map(t -> Collections.singleton(t)).collect(Collectors.toSet());
+
+        Predicate<Type> isInstancePred = x -> types.stream().filter(t -> TypeAndInstanceCheck.isInstance(t, x)).findFirst().isPresent();
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        Samples<?> samples = new Samples(types.toString(), Collections.emptySet(), Collections.emptySet(), isInstancePred);
+        return new TypeExpr(disjNormForm, samples);
     }
 
     public static TypeExpr union(Class<?>... types) {
@@ -116,34 +213,58 @@ public final class TypeExpr {
         }
         // !(A.B | C.D) = !(A.B).!(C.D) = (!A | !B).(!C | !D) = !A.!C | !A.!D | !B.!C | !B.!D
         // !(!A.!B | !C.!D) = !(!A.!B).!(!C.!D) = (A | B).(C | D) = A.C | A.D | B.C | B.D
-        Set<TypeExpr> asUnions = disjNormForm.stream().map(conj -> union(conj)).collect(Collectors.toSet());
+        Set<TypeExpr> asUnions = disjNormForm.stream().map(conj -> union(negateTypes(conj))).collect(Collectors.toSet());
         TypeExpr conj = asUnions.stream().reduce((res, te) -> res.and(te)).orElse(NOTHING);
-        return conj.map(t -> Not.negateType(t));
+        return new TypeExpr(conj.disjNormForm, samples.swap()); // add the negated samples
     }
 
-    public Set<Type> normalize() {
-        return disjNormForm.stream().map(conj -> normalize(conj)).filter(t -> !t.equals(Not.NOTHING)).collect(Collectors.toSet());
+    private static Set<Type> negateTypes(Set<Type> types) {
+        return types.stream().map(t -> Not.negateType(t)).collect(Collectors.toSet());
+    }
+
+    public TypeExpr normalize() {
+        Set<Set<Type>> conjunctionsNormalized = disjNormForm.stream().map(conj -> normalizeConjunctionSet(conj)).filter(t -> !t.equals(Not.NOTHING)).collect(Collectors.toSet());
+        return new TypeExpr(conjunctionsNormalized, samples);
+    }
+
+    public Set<Type> toNormalizedConjunctionSet() {
+        Set<Type> conjunctionsNormalized = disjNormForm.stream().map(conj -> normalizeConjunction(conj)).filter(t -> !t.equals(Not.NOTHING)).collect(Collectors.toSet());
+        return conjunctionsNormalized;
+        // return squashDisjunctions(conjunctionsNormalized);
     }
 
     public Set<Class<?>> toClasses() {
-        return normalize().stream().filter(t -> t instanceof Class).map(t -> (Class<?>) t).collect(Collectors.toSet());
+        return toNormalizedConjunctionSet().stream().filter(t -> t instanceof Class).map(t -> (Class<?>) t).collect(Collectors.toSet());
+    }
+
+    static Type normalizeConjunction(Set<Type> conj) {
+        Set<Type> moreSpecific = normalizeConjunctionSet(conj);
+        if (moreSpecific.isEmpty()) {
+            return Not.NOTHING;
+        } else if (moreSpecific.size() == 1) {
+            Type t = moreSpecific.iterator().next();
+            return t;
+        } else {
+            UpperBoundsConjunction ub = UpperBoundsConjunction.create(moreSpecific.stream());
+            return ub;
+        }
     }
 
-    private static Type normalize(Set<? extends Type> conj) {
+    static Set<Type> normalizeConjunctionSet(Set<Type> conj) {
         Type[] conjArray = conj.toArray(new Type[conj.size()]);
         Set<Type> lessSpecific = new HashSet<>();
 
         for (int i = 0; i < conj.size(); i++) {
             for (int j = i + 1; j < conj.size(); j++) {
 
-                switch (CastUtils.Casts.isConvertible(conjArray[i], conjArray[j], true)) {
+                switch (CastUtils.Casts.isConvertible(conjArray[i], conjArray[j], false)) {
                     case none:
                         // a contradiction found
-                        return Not.NOTHING;
+                        return Collections.emptySet();
                     case potential:
                         break;
                     case partial:
-                        if (CastUtils.Casts.isConvertible(conjArray[j], conjArray[i], true) == Cast.Coverage.full) {
+                        if (CastUtils.Casts.isConvertible(conjArray[j], conjArray[i], false) == Cast.Coverage.full) {
                             lessSpecific.add(conjArray[i]);
                         }
                         break;
@@ -154,20 +275,30 @@ public final class TypeExpr {
             }
         }
 
-        HashSet<Type> moreSpecific = new HashSet<>(conj);
+        Set<Type> moreSpecific = new HashSet<>(conj);
         moreSpecific.removeAll(lessSpecific);
+        moreSpecific = moreSpecific.stream().map(t -> t instanceof TypeAndInstanceCheck ? ((TypeAndInstanceCheck) t).normalize() : t).collect(Collectors.toSet());
+        return moreSpecific;
+    }
 
-        if (moreSpecific.size() == 1) {
-            Type t = moreSpecific.iterator().next();
-            return t;
-        } else {
-            assert !moreSpecific.isEmpty();
-            return new TypeConjunction(moreSpecific);
+    static boolean isContradiction(Set<Type> conj) {
+        Type[] conjArray = conj.toArray(new Type[conj.size()]);
+        for (int i = 0; i < conj.size(); i++) {
+            for (int j = i + 1; j < conj.size(); j++) {
+
+                switch (CastUtils.Casts.isConvertible(conjArray[i], conjArray[j], true)) {
+                    case none:
+                        // a contradiction found
+                        return true;
+                }
+            }
         }
+
+        return false;
     }
 
     public Set<Class<?>> classify() {
-        return normalize().stream().map(t -> classify(t)).filter(ot -> ot.isPresent()).map(ot -> ot.get()).collect(Collectors.toSet());
+        return toNormalizedConjunctionSet().stream().map(t -> classify(t)).filter(ot -> ot.isPresent()).map(ot -> ot.get()).collect(Collectors.toSet());
     }
 
     private static Optional<Class<?>> classify(Type t) {
@@ -180,7 +311,7 @@ public final class TypeExpr {
     }
 
     public boolean isInstance(Object x) {
-        return normalize().stream().filter(t -> {
+        return toNormalizedConjunctionSet().stream().filter(t -> {
             if (t instanceof TypeAndInstanceCheck) {
                 return ((TypeAndInstanceCheck) t).isInstance(x);
             } else {
@@ -191,7 +322,7 @@ public final class TypeExpr {
     }
 
     public Cast.Coverage isConvertibleFrom(Type from, boolean includeImplicits) {
-        return normalize().stream().map(t -> CastUtils.Casts.isConvertible(from, t, includeImplicits)).reduce((res, cvg) -> res.or(cvg)).orElse(Cast.Coverage.none);
+        return toNormalizedConjunctionSet().stream().map(t -> CastUtils.Casts.isConvertible(from, t, includeImplicits)).reduce((res, cvg) -> res.or(cvg)).orElse(Cast.Coverage.none);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java
deleted file mode 100644
index 317f3db075..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypePredicateArgumentFilterSampler.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import com.oracle.truffle.r.nodes.builtin.TypePredicateArgumentFilter;
-import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentTypeFilterSampler;
-
-public class TypePredicateArgumentFilterSampler<T, R extends T> extends TypePredicateArgumentFilter<T, R> implements ArgumentTypeFilterSampler<T, R> {
-
-    private final TypeExpr trueBranchTypes;
-    private final Samples<R> samples;
-    private final String desc;
-
-    @SuppressWarnings("unchecked")
-    public TypePredicateArgumentFilterSampler(String desc, Predicate<? super T> valuePredicate, Set<? extends R> positiveSamples, Set<?> negativeSamples, Set<Class<?>> allowedTypeSet) {
-        super(valuePredicate);
-
-        this.trueBranchTypes = allowedTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(allowedTypeSet);
-        Predicate<Object> posMembership = x -> trueBranchTypes.isInstance(x) && test((T) x);
-        this.samples = new Samples<>(desc, positiveSamples, negativeSamples, posMembership);
-
-        assert positiveSamples.stream().allMatch(x -> valuePredicate.test(x));
-
-        this.desc = desc;
-    }
-
-    @Override
-    public TypeExpr trueBranchType() {
-        return trueBranchTypes;
-    }
-
-    @Override
-    public Samples<R> collectSamples(TypeExpr inputType) {
-        return samples;
-    }
-
-    @Override
-    public String toString() {
-        return desc;
-    }
-
-    public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<? super T> predicate, Set<? extends R> positiveSamples, Set<?> negativeSamples,
-                    Class<?>... resultClass) {
-        return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Arrays.asList(resultClass).stream().collect(Collectors.toSet()));
-    }
-
-    public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<T> predicate, Class<?>... resultClass) {
-        return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), Collections.emptySet(),
-                        Arrays.asList(resultClass).stream().collect(Collectors.toSet()));
-    }
-
-    public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<T> predicate, Set<? extends R> positiveSamples, Set<?> negativeSamples) {
-        return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Collections.emptySet());
-    }
-
-    public static <T, R extends T> TypePredicateArgumentFilterSampler<T, R> fromLambda(Predicate<T> predicate, @SuppressWarnings("unused") Class<R> commonAncestorClass, Set<Class<?>> resultClasses) {
-        return new TypePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), Collections.emptySet(), resultClasses);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
new file mode 100644
index 0000000000..f7475baa48
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.casts;
+
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.oracle.truffle.r.nodes.casts.CastUtils.Cast.Coverage;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+public final class UpperBoundsConjunction implements WildcardType, TypeAndInstanceCheck {
+    private static final Type[] EMPTY_TYPES = new Type[0];
+
+    private final Set<Type> upperBounds;
+    private final boolean useAsWildcard;
+    /**
+     * This typeRepr object represents the wildcard type. Two wildcard types are equivalent if their
+     * type representations are the same.
+     */
+    private final Object typeRepr;
+
+    UpperBoundsConjunction(Set<Type> upperBounds, boolean useAsWildcard, Object typeRepr) {
+        this.upperBounds = TypeExpr.normalizeConjunctionSet(upperBounds);
+        this.useAsWildcard = useAsWildcard;
+        this.typeRepr = typeRepr == null && useAsWildcard ? new Object() : typeRepr;
+    }
+
+    public UpperBoundsConjunction asWildcard(Object typeRepres) {
+        return new UpperBoundsConjunction(upperBounds, true, typeRepres);
+    }
+
+    private UpperBoundsConjunction removeWildcardAndNormalize() {
+        return new UpperBoundsConjunction(fromType(TypeExpr.normalizeConjunction(flatten())).upperBounds, false, null);
+    }
+
+    public Set<Type> flatten() {
+        Set<Type> flattened = new HashSet<>();
+        for (Type t : upperBounds) {
+            if (t instanceof UpperBoundsConjunction) {
+                flattened.addAll(((UpperBoundsConjunction) t).flatten());
+            } else {
+                flattened.add(t);
+            }
+        }
+        return flattened;
+    }
+
+    public static UpperBoundsConjunction create(Type... types) {
+        Stream<Type> typeStream = Arrays.asList(types).stream();
+        return create(typeStream);
+    }
+
+    public static UpperBoundsConjunction create(Stream<? extends Type> typeStream) {
+        Set<Type> upperBounds = typeStream.flatMap(t -> ((t instanceof UpperBoundsConjunction && !((UpperBoundsConjunction) t).isWildcard()) ? ((UpperBoundsConjunction) t).upperBounds
+                        : Collections.singleton(t)).stream()).collect(Collectors.toSet());
+        return new UpperBoundsConjunction(upperBounds, false, null);
+    }
+
+    public static UpperBoundsConjunction fromType(Type t) {
+        if (t instanceof UpperBoundsConjunction) {
+            return (UpperBoundsConjunction) t;
+        } else {
+            return new UpperBoundsConjunction(Collections.singleton(t), false, null);
+        }
+    }
+
+    @Override
+    public Type[] getUpperBounds() {
+        return upperBounds.toArray(new Type[upperBounds.size()]);
+    }
+
+    @Override
+    public Type[] getLowerBounds() {
+        return useAsWildcard ? EMPTY_TYPES : getUpperBounds();
+    }
+
+    public boolean isWildcard() {
+        return useAsWildcard;
+    }
+
+    @Override
+    public boolean isInstance(Object x) {
+        return upperBounds.stream().filter(t -> ((TypeAndInstanceCheck) t).isInstance(x)).findAny().isPresent();
+    }
+
+    public Coverage coverageFrom(UpperBoundsConjunction from, boolean includeImplicits) {
+        return adjustCoverageFrom(upperBounds.stream().map(ubt -> {
+            return from.coverageTo(ubt, includeImplicits);
+        }).reduce((res, cvg) -> cvg.and(res)).orElse(Coverage.none), from);
+    }
+
+    public Coverage coverageTo(Type to, boolean includeImplicits) {
+        assert to instanceof Not || to instanceof Class;
+        return adjustCoverageTo(upperBounds.stream().map(ubt -> {
+            return TypeAndInstanceCheck.coverage(ubt, to, includeImplicits);
+        }).reduce((res, cvg) -> res == Coverage.none || cvg == Coverage.none ? Coverage.none : cvg.or(res)).orElse(Coverage.none));
+    }
+
+    private Coverage adjustCoverageTo(Coverage cvg) {
+        if (isWildcard()) {
+            switch (cvg) {
+                case full:
+                    return Coverage.full;
+                case partial:
+                    return Coverage.potential;
+                case potential:
+                    return Coverage.potential;
+                case none:
+                    return Coverage.none;
+                default:
+                    throw RInternalError.shouldNotReachHere();
+            }
+        } else {
+            return cvg;
+        }
+    }
+
+    private Coverage adjustCoverageFrom(Coverage cvg, UpperBoundsConjunction from) {
+        if (isWildcard()) {
+            switch (cvg) {
+                case full:
+                    UpperBoundsConjunction fromNoWildCard = from.removeWildcardAndNormalize();
+                    UpperBoundsConjunction toNoWildCard = this.removeWildcardAndNormalize();
+
+                    boolean bijection = fromNoWildCard.upperBounds.equals(toNoWildCard.upperBounds);
+                    return bijection ? Coverage.partial : Coverage.potential;
+                case partial:
+                    return Coverage.partial;
+                case potential:
+                    return Coverage.potential;
+                case none:
+                    return Coverage.none;
+                default:
+                    throw RInternalError.shouldNotReachHere();
+            }
+        } else {
+            return cvg;
+        }
+    }
+
+    @Override
+    public Type normalize() {
+        Set<Type> normUpperBounds = fromType(TypeExpr.normalizeConjunction(upperBounds)).upperBounds;
+        if (!isWildcard() && normUpperBounds.size() == 1) {
+            return normUpperBounds.iterator().next();
+        } else {
+            return new UpperBoundsConjunction(normUpperBounds, useAsWildcard, typeRepr);
+        }
+    }
+
+    @Override
+    public Optional<Class<?>> classify() {
+        Set<Class<?>> classes = upperBounds.stream().filter(t -> t instanceof Class<?>).map(t -> (Class<?>) t).collect(Collectors.toSet());
+        return classes.size() == 1 ? Optional.of(classes.iterator().next()) : Optional.empty();
+    }
+
+    @Override
+    public String toString() {
+        return isWildcard() ? "(" + System.identityHashCode(typeRepr) + " extends " + upperBounds + ")" : "(" + upperBounds + ")";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((upperBounds == null) ? 0 : upperBounds.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        UpperBoundsConjunction other = (UpperBoundsConjunction) obj;
+        return useAsWildcard == other.useAsWildcard && upperBounds.equals(other.upperBounds) && (!useAsWildcard || typeRepr.equals(other.typeRepr));
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java
deleted file mode 100644
index b8ad3169c5..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentFilterSampler.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentFilter;
-import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler;
-
-public class ValuePredicateArgumentFilterSampler<T> extends ValuePredicateArgumentFilter<T> implements ArgumentValueFilterSampler<T> {
-
-    private final TypeExpr trueBranchTypes;
-    private final Samples<T> samples;
-    private final String desc;
-
-    @SuppressWarnings("unchecked")
-    public ValuePredicateArgumentFilterSampler(String desc, Predicate<? super T> valuePredicate, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples, Set<Class<?>> allowedTypeSet) {
-        super(valuePredicate);
-
-        this.trueBranchTypes = allowedTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(allowedTypeSet);
-        Predicate<Object> posMembership = x -> trueBranchTypes.isInstance(x) && test((T) x);
-        this.samples = new Samples<>(desc, positiveSamples, negativeSamples, posMembership);
-
-        assert positiveSamples.stream().allMatch(x -> valuePredicate.test(x));
-
-        this.desc = desc;
-    }
-
-    @Override
-    public TypeExpr trueBranchType() {
-        return trueBranchTypes;
-    }
-
-    @Override
-    public String toString() {
-        return desc;
-    }
-
-    @Override
-    public Samples<T> collectSamples(TypeExpr inputType) {
-        return samples;
-    }
-
-    public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithSamples(Predicate<? super T> predicate, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples,
-                    Class<?> resultClass) {
-        return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Collections.singleton(resultClass));
-    }
-
-    public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithResTypes(Predicate<T> predicate, Class<?>... resultClass) {
-        return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), Collections.emptySet(),
-                        Arrays.asList(resultClass).stream().collect(Collectors.toSet()));
-    }
-
-    public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithSamples(Predicate<T> predicate, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples) {
-        return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, positiveSamples, negativeSamples, Collections.emptySet());
-    }
-
-    public static <T> ValuePredicateArgumentFilterSampler<T> fromLambdaWithSamples(Predicate<T> predicate, Set<T> negativeSamples,
-                    @SuppressWarnings("unused") Class<T> commonAncestorClass, Set<Class<?>> resultClasses) {
-        return new ValuePredicateArgumentFilterSampler<>(CastUtils.getPredefStepDesc(), predicate, Collections.emptySet(), negativeSamples, resultClasses);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java
deleted file mode 100644
index 26a790eaf4..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ValuePredicateArgumentMapperSampler.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-import com.oracle.truffle.r.nodes.builtin.ValuePredicateArgumentMapper;
-
-public class ValuePredicateArgumentMapperSampler<T, R> extends ValuePredicateArgumentMapper<T, R> implements ArgumentMapperSampler<T, R> {
-
-    private final Function<R, T> unmapper;
-    private final TypeExpr inputTypes;
-    private final TypeExpr resTypes;
-    private final String desc;
-    private final Samples<T> samples;
-
-    public ValuePredicateArgumentMapperSampler(String desc, Function<T, R> mapper, Function<R, T> unmapper, Set<? extends T> positiveSamples, Set<?> negativeSamples, Set<Class<?>> inputTypeSet,
-                    Set<Class<?>> resultTypeSet) {
-        super(mapper);
-        this.unmapper = unmapper;
-        this.inputTypes = inputTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(inputTypeSet);
-        this.resTypes = resultTypeSet.isEmpty() ? TypeExpr.ANYTHING : TypeExpr.union(resultTypeSet);
-        this.desc = desc;
-        Predicate<Object> posMembership = x -> inputTypes.isInstance(x) && !negativeSamples.contains(x);
-        this.samples = new Samples<>(desc, positiveSamples, negativeSamples, posMembership);
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr it) {
-        return resTypes;
-    }
-
-    @Override
-    public String toString() {
-        return desc;
-    }
-
-    public static <T, R> ValuePredicateArgumentMapperSampler<T, R> fromLambda(Function<T, R> mapper, Function<R, T> unmapper, Class<T> inputClass, Class<R> resultClass) {
-        return new ValuePredicateArgumentMapperSampler<>(CastUtils.getPredefStepDesc(), mapper, unmapper, Collections.emptySet(), Collections.emptySet(),
-                        inputClass == null ? Collections.emptySet() : Collections.singleton(inputClass),
-                        resultClass == null ? Collections.emptySet() : Collections.singleton(resultClass));
-    }
-
-    public static <T, R> ValuePredicateArgumentMapperSampler<T, R> fromLambda(Function<T, R> mapper, Function<R, T> unmapper, Set<? extends T> positiveSamples, Set<? extends T> negativeSamples,
-                    Class<T> inputClass, Class<?> resultClass) {
-        return new ValuePredicateArgumentMapperSampler<>(CastUtils.getPredefStepDesc(), mapper, unmapper, positiveSamples, negativeSamples,
-                        inputClass == null ? Collections.emptySet() : Collections.singleton(inputClass),
-                        resultClass == null ? Collections.emptySet() : Collections.singleton(resultClass));
-    }
-
-    @Override
-    public Samples<T> collectSamples(Samples<R> downStreamSamples) {
-        if (unmapper == null) {
-            return samples;
-        } else {
-            Samples<R> filtered = downStreamSamples.filter(x -> resTypes.isInstance(x), x -> resTypes.isInstance(x));
-            @SuppressWarnings("unchecked")
-            Samples<T> unmappedSamples = filtered.map(x -> unmapper.apply(x), x -> unmapper.apply((R) x),
-                            x -> inputTypes.isInstance(x) ? Optional.of(mapper.apply((T) x)) : Optional.empty(),
-                            x -> inputTypes.isInstance(x) ? Optional.of(mapper.apply((T) x)) : Optional.empty());
-
-            Samples<T> combined = samples.and(unmappedSamples);
-            return combined;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java
deleted file mode 100644
index 8676a5c2b0..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/VectorPredicateArgumentFilterSampler.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.casts;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import com.oracle.truffle.r.nodes.builtin.VectorPredicateArgumentFilter;
-import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler.ArgumentValueFilterSampler;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-public class VectorPredicateArgumentFilterSampler<T extends RAbstractVector> extends VectorPredicateArgumentFilter<T> implements ArgumentValueFilterSampler<T> {
-
-    private final String desc;
-    private final List<Integer> invalidVectorSize;
-
-    public VectorPredicateArgumentFilterSampler(String desc, Predicate<T> valuePredicate, Integer... invalidVectorSize) {
-        super(valuePredicate);
-        this.desc = desc;
-        this.invalidVectorSize = invalidVectorSize == null ? Collections.emptyList() : Arrays.asList(invalidVectorSize);
-    }
-
-    @SuppressWarnings("unchecked")
-    private boolean testVector(Object x) {
-        if (x instanceof RAbstractVector) {
-            return test((T) x);
-        } else {
-            Object v = CastUtils.singletonVector(x);
-            if (v == RNull.instance || v == RMissing.instance) {
-                // these values are ignored, they should never appear in a filter or a mapper
-                return true;
-            }
-            return test((T) v);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return this.desc;
-    }
-
-    @Override
-    public Samples<T> collectSamples(TypeExpr inputType) {
-        Set<RAbstractVector> negSamples = inputType.toClasses().stream().flatMap(vt -> invalidVectorSize.stream().map(sz -> CastUtils.vectorOfSize(vt, sz))).collect(Collectors.toSet());
-
-        Predicate<Object> posMembership = this::testVector;
-        final Samples<T> samples = new Samples<>(desc, Collections.emptySet(), negSamples, posMembership);
-
-        return samples;
-    }
-
-    @Override
-    public TypeExpr trueBranchType() {
-        return TypeExpr.ANYTHING;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
index c6091bd38e..3d94165a36 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
@@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -43,8 +44,9 @@ import org.junit.Assert;
 import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Value;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
 import com.oracle.truffle.r.nodes.casts.Samples;
+import com.oracle.truffle.r.nodes.casts.SamplesCollector;
 import com.oracle.truffle.r.nodes.test.RBuiltinDiagnostics.DiagConfig;
 import com.oracle.truffle.r.nodes.test.RBuiltinDiagnostics.RIntBuiltinDiagFactory;
 import com.oracle.truffle.r.nodes.test.RBuiltinDiagnostics.SingleBuiltinDiagnostics;
@@ -167,7 +169,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
             // these values are not determined via the pipeline static type analysis
             config.performPipelineSelfTest = config.missingAndNullSamplesOnly ? false : !Arrays.stream(args).filter(arg -> NO_SELF_TEST_ARG.equals(arg)).findFirst().isPresent();
             config.maxSweeps = Arrays.stream(args).filter(arg -> arg.startsWith(MAX_SWEEPS_ARG)).map(x -> Integer.parseInt(x.split("=")[1])).findFirst().orElse(Integer.MAX_VALUE);
-            return RBuiltinDiagnostics.initDiagConfig(config, args);
+            return RBuiltinDiagnostics.initDiagConfig(config, args, false);
         }
 
         private static Optional<String> getSweepMode(String[] args) {
@@ -202,24 +204,35 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
         }
     }
 
-    private final List<Samples<?>> argSamples;
     private final ChimneySweepingSuite diagSuite;
-    private final Set<RList> validArgsList;
     private final RBuiltinKind kind;
 
+    private List<Samples<?>> argSamples;
+    private Set<RList> validArgsList;
+    private CastNode[] castNodes;
+
     private final Set<List<String>> printedOutputPairs = new HashSet<>();
     private final Set<String> printedErrors = new HashSet<>();
     private int sweepCounter = 0;
 
     ChimneySweeping(ChimneySweepingSuite diagSuite, RIntBuiltinDiagFactory builtinFactory) {
         super(diagSuite, builtinFactory);
+        this.diagSuite = diagSuite;
+        this.kind = builtinFactory.getBuiltinKind();
+    }
+
+    @Override
+    SingleBuiltinDiagnostics init() throws Throwable {
+        super.init();
+
+        this.castNodes = builtinFactory.getCastNodes();
 
         print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinNodeClass().getName() + ") ***");
 
-        this.kind = builtinFactory.getBuiltinKind();
-        this.diagSuite = diagSuite;
         this.validArgsList = extractValidArgsForBuiltin();
         this.argSamples = createSamples();
+
+        return this;
     }
 
     @Override
@@ -250,6 +263,8 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
         DefaultArgsExtractor defArgExt = new DefaultArgsExtractor(diagSuite.fastRSession, msg -> print(1, msg));
         Map<String, Samples<?>> defaultArgs = defArgExt.extractDefaultArgs(builtinName);
 
+        PipelineBuilder[] plBuilders = casts.getPipelineBuilders();
+
         List<Samples<?>> as = new ArrayList<>();
         for (int i = 0; i < argLength; i++) {
             Samples samples;
@@ -257,18 +272,18 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
             if (diagSuite.diagConfig.missingAndNullSamplesOnly) {
                 samples = Samples.anything(RNull.instance).or(Samples.anything(RMissing.instance));
             } else {
-                CastNode cn;
-                if (i < castNodes.length) {
-                    cn = castNodes[i];
+                PipelineBuilder plBuilder;
+                if (i < plBuilders.length) {
+                    plBuilder = plBuilders[i];
                 } else {
-                    cn = null;
+                    plBuilder = null;
                 }
                 try {
-                    if (cn == null) {
+                    if (plBuilder == null) {
                         samples = Samples.anything();
                     } else {
-                        CastNodeSampler<CastNode> sampler = CastNodeSampler.createSampler(cn);
-                        samples = sampler.collectSamples();
+                        Set<Object> sampleSet = SamplesCollector.collect(plBuilder.getFirstStep());
+                        samples = new Samples<>("", sampleSet, Collections.emptySet(), x -> sampleSet.contains(x));
                     }
                 } catch (Exception e) {
                     throw new RuntimeException("Error in sample generation from argument " + i, e);
@@ -373,7 +388,11 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
     private RList evalValidArgs(String argsExpr, PolyglotEngine vm) {
         try {
             Value eval = vm.eval(RSource.fromTextInternal(argsExpr, RSource.Internal.UNIT_TEST));
-            RList args = (RList) eval.get();
+            Object res = eval.get();
+            // TODO: do not use reflection here
+            Method getter = res.getClass().getDeclaredMethod("getDelegate");
+            getter.setAccessible(true);
+            RList args = (RList) getter.invoke(res);
             return args;
         } catch (Exception e) {
             print(1, "Warning: Cannot parse arguments: " + argsExpr);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
new file mode 100644
index 0000000000..8b6d15fd21
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+
+/**
+ * This class contains a list of external builtins.
+ */
+public class ExtBuiltinsList {
+
+    @SuppressWarnings("rawtypes") private static final Class[] builtins = {
+                    com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode.class,
+                    com.oracle.truffle.r.nodes.objects.NewObjectNodeGen.class,
+                    com.oracle.truffle.r.nodes.objects.GetPrimNameNodeGen.class,
+                    com.oracle.truffle.r.library.utils.TypeConvertNodeGen.class,
+                    com.oracle.truffle.r.library.utils.RprofNodeGen.class,
+                    com.oracle.truffle.r.library.utils.RprofmemNodeGen.class,
+                    com.oracle.truffle.r.library.utils.ObjectSizeNodeGen.class,
+                    com.oracle.truffle.r.library.utils.MenuNodeGen.class,
+                    com.oracle.truffle.r.library.utils.DownloadNodeGen.class,
+                    com.oracle.truffle.r.library.utils.Crc64NodeGen.class,
+                    com.oracle.truffle.r.library.utils.CountFields.class,
+                    com.oracle.truffle.r.library.parallel.ParallelFunctionsFactory.MCIsChildNodeGen.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.WriteTableNodeGen.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.ReadTableHeadNodeGen.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.MakeQuartzDefault.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.Flushconsole.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.FftNodeGen.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.Dqrdc2NodeGen.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.Dqrcf.class,
+                    com.oracle.truffle.r.nodes.builtin.base.foreign.CairoPropsNodeGen.class,
+                    com.oracle.truffle.r.library.tools.ToolsTextFactory.DoTabExpandNodeGen.class,
+                    com.oracle.truffle.r.library.tools.ToolsTextFactory.CodeFilesAppendNodeGen.class,
+                    com.oracle.truffle.r.library.tools.Rmd5NodeGen.class,
+                    com.oracle.truffle.r.library.tools.DirChmodNodeGen.class,
+                    com.oracle.truffle.r.library.tools.C_ParseRdNodeGen.class,
+                    com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen.class,
+                    com.oracle.truffle.r.library.grDevices.DevicesCCalls.C_DevCur.class,
+                    com.oracle.truffle.r.library.grDevices.DevicesCCalls.C_PDF.class,
+                    com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_PlotXY.class,
+                    com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_Par.class,
+                    com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_mtext.class,
+                    com.oracle.truffle.r.library.stats.WilcoxFreeNode.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_2NodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_1NodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_2NodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_1NodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function2_1NodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function2_2NodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.ApproxTestNodeGen.class,
+                    com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.ApproxNodeGen.class,
+                    com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen.class,
+                    com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen.class,
+                    com.oracle.truffle.r.library.stats.SignrankFreeNode.class,
+                    com.oracle.truffle.r.library.stats.RMultinomNodeGen.class,
+                    com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction3NodeGen.class,
+                    com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction2NodeGen.class,
+                    com.oracle.truffle.r.library.stats.RandFunctionsNodesFactory.RandFunction1NodeGen.class,
+                    com.oracle.truffle.r.library.stats.DoubleCentreNodeGen.class,
+                    com.oracle.truffle.r.library.stats.CutreeNodeGen.class,
+                    com.oracle.truffle.r.library.stats.CovcorNodeGen.class,
+                    com.oracle.truffle.r.library.stats.CompleteCases.class,
+                    com.oracle.truffle.r.library.stats.CdistNodeGen.class,
+                    com.oracle.truffle.r.library.stats.BinDistNodeGen.class,
+                    com.oracle.truffle.r.library.grid.GridFunctionsFactory.InitGridNodeGen.class,
+                    com.oracle.truffle.r.library.grid.GridFunctionsFactory.ValidUnitsNodeGen.class,
+                    com.oracle.truffle.r.library.grid.GridFunctions.KillGrid.class,
+                    com.oracle.truffle.r.library.methods.SubstituteDirectNodeGen.class,
+                    com.oracle.truffle.r.library.methods.SlotFactory.R_getSlotNodeGen.class,
+                    com.oracle.truffle.r.library.methods.SlotFactory.R_setSlotNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_initMethodDispatchNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_methodsPackageMetaNameNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getClassFromCacheNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_set_method_dispatchNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_M_setPrimitiveMethodsNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_identCNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getGenericNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_nextMethodCallNodeGen.class,
+                    com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_externalPtrPrototypeObjectNodeGen.class,
+    };
+
+    @SuppressWarnings("unchecked")
+    public static List<Class<? extends RExternalBuiltinNode>> getBuiltins() {
+        return Arrays.asList(builtins);
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index e4b307888c..3ec99e591e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -39,29 +39,31 @@ import java.util.stream.Collectors;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
 import com.oracle.truffle.r.nodes.casts.CastUtils;
 import com.oracle.truffle.r.nodes.casts.CastUtils.Cast;
 import com.oracle.truffle.r.nodes.casts.CastUtils.Casts;
-import com.oracle.truffle.r.nodes.casts.FilterSamplerFactory;
-import com.oracle.truffle.r.nodes.casts.MapperSamplerFactory;
 import com.oracle.truffle.r.nodes.casts.Not;
+import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser;
 import com.oracle.truffle.r.nodes.casts.TypeExpr;
 import com.oracle.truffle.r.nodes.test.ChimneySweeping.ChimneySweepingSuite;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
 
 public class RBuiltinDiagnostics {
 
     private static final String OUTPUT_MAX_LEVEL_ARG = "--outMaxLev=";
 
+    private static final TypeExpr rmissingType = TypeExpr.atom(RMissing.class);
+
     static class DiagConfig {
         boolean verbose;
         boolean ignoreRNull;
@@ -70,46 +72,40 @@ public class RBuiltinDiagnostics {
         int outputMaxLevel;
     }
 
-    static {
-        PipelineConfig.setFilterFactory(FilterSamplerFactory.INSTANCE);
-        PipelineConfig.setMapperFactory(MapperSamplerFactory.INSTANCE);
-    }
-
-    private final DiagConfig diagConfig;
+    final DiagConfig diagConfig;
+    int warningCounter = 0;
+    int reportedBuiltinsCounter = 0;
 
     RBuiltinDiagnostics(DiagConfig diagConfig) {
         this.diagConfig = diagConfig;
     }
 
-    static RBuiltinDiagnostics createRBuiltinDiagnostics(String[] args) {
-        return new RBuiltinDiagnostics(initDiagConfig(new DiagConfig(), args));
+    static RBuiltinDiagnostics createRBuiltinDiagnostics(String[] args, boolean batchDiag) {
+        return new RBuiltinDiagnostics(initDiagConfig(new DiagConfig(), args, batchDiag));
     }
 
-    static <C extends DiagConfig> C initDiagConfig(C diagConfig, String[] args) {
+    static <C extends DiagConfig> C initDiagConfig(C diagConfig, String[] args, boolean batchDiag) {
         diagConfig.verbose = Arrays.stream(args).filter(arg -> "-v".equals(arg)).findFirst().isPresent();
         diagConfig.ignoreRNull = Arrays.stream(args).filter(arg -> "-n".equals(arg)).findFirst().isPresent();
         diagConfig.ignoreRMissing = Arrays.stream(args).filter(arg -> "-m".equals(arg)).findFirst().isPresent();
-        diagConfig.outputMaxLevel = Arrays.stream(args).filter(arg -> arg.startsWith(OUTPUT_MAX_LEVEL_ARG)).map(x -> Integer.parseInt(x.split("=")[1])).findFirst().orElse(Integer.MAX_VALUE);
+        diagConfig.outputMaxLevel = Arrays.stream(args).filter(arg -> arg.startsWith(OUTPUT_MAX_LEVEL_ARG)).map(x -> Integer.parseInt(x.split("=")[1])).findFirst().orElse(
+                        batchDiag ? 0 : Integer.MAX_VALUE);
         return diagConfig;
     }
 
     public static void main(String[] args) throws Throwable {
-        // TODO: Enable it when the diagnostics is rewritten using CP-IR
-        if (true) {
-            System.out.println("Temporarily disabled until the diagnostics is rewritten using CP-IR");
-            return;
-        }
-
-        @SuppressWarnings("unused")
-        RBuiltinDiagnostics rbDiag = ChimneySweepingSuite.createChimneySweepingSuite(args).orElseGet(() -> createRBuiltinDiagnostics(args));
-
         List<String> bNames = Arrays.stream(args).filter(arg -> !arg.startsWith("-")).collect(Collectors.toList());
+
+        RBuiltinDiagnostics rbDiag = ChimneySweepingSuite.createChimneySweepingSuite(args).orElseGet(() -> createRBuiltinDiagnostics(args, bNames.isEmpty()));
         if (bNames.isEmpty()) {
             rbDiag.diagnoseAllBuiltins();
         } else {
+            boolean ok = true;
             for (String bName : bNames) {
-                rbDiag.diagnoseSingleBuiltin(bName);
+                ok &= rbDiag.diagnoseSingleBuiltin(bName);
             }
+
+            System.exit(ok ? 0 : 1);
         }
     }
 
@@ -117,49 +113,210 @@ public class RBuiltinDiagnostics {
         return new SingleBuiltinDiagnostics(this, bf);
     }
 
-    public void diagnoseSingleBuiltin(String builtinName) throws Exception {
+    public boolean diagnoseSingleBuiltin(String builtinName) throws Exception {
+        SingleBuiltinDiagnostics diag;
+        try {
+            print(0, "Diagnosing '" + builtinName + "' ...");
+
+            BasePackage bp = new BasePackage();
+            RBuiltinFactory bf = bp.lookupByName(builtinName);
+            RBuiltinDiagFactory bdf;
+
+            if (bf == null) {
+                Class<?> bltnCls = loadBuiltinClass(toReflClassName(builtinName));
+                if (RExternalBuiltinNode.class.isAssignableFrom(bltnCls)) {
+                    bdf = RExtBuiltinDiagFactory.create(bltnCls);
+                } else {
+                    bdf = new RIntBuiltinDiagFactory(findBuiltInFactory(bltnCls, bp));
+                }
+            } else {
+                bdf = new RIntBuiltinDiagFactory(bf);
+            }
+
+            diag = createBuiltinDiagnostics(bdf);
+        } catch (Throwable t) {
+            print(0, "Error in initialization of builtin " + builtinName);
+            t.printStackTrace();
+            return false;
+        }
+
+        boolean ok = true;
+        try {
+            diag.init().diagnoseBuiltin();
+
+            print(1, "Finished");
+            print(1, "--------");
+        } catch (WarningException e) {
+            diag.print(0, "Warning: " + e.getMessage());
+        } catch (InfoException e) {
+            print(0, e.getMessage());
+        } catch (Throwable e) {
+            ok = false;
+            e.printStackTrace();
+        }
+        return ok;
+    }
+
+    public void diagnoseAllBuiltins() {
         BasePackage bp = new BasePackage();
-        RBuiltinFactory bf = bp.lookupByName(builtinName);
-        RBuiltinDiagFactory bdf;
-        if (bf == null) {
+
+        List<Class<? extends RExternalBuiltinNode>> extBltn = ExtBuiltinsList.getBuiltins();
+        Collection<RBuiltinFactory> intBltn = bp.getBuiltins().values();
+        int nBltn = intBltn.size() + extBltn.size();
+        System.out.println("Diagnosing " + nBltn + " builtins (" + intBltn.size() + " internal, " + extBltn.size() + " external)");
+
+        boolean ok = true;
+        int errCounter = 0;
+
+        for (RBuiltinFactory bf : intBltn) {
+            System.out.print(".");
+            SingleBuiltinDiagnostics diag;
             try {
-                bdf = RExtBuiltinDiagFactory.create(builtinName);
-            } catch (Exception e) {
-                print(0, "No builtin '" + builtinName + "' found");
-                return;
+                diag = createBuiltinDiagnostics(new RIntBuiltinDiagFactory((bf)));
+            } catch (WarningException e) {
+                print(0, "Warning: " + e.getMessage());
+                continue;
+            } catch (InfoException e) {
+                print(1, e.getMessage());
+                continue;
+            } catch (Throwable t) {
+                errCounter++;
+                print(0, "Error in initialization of builtin " + bf.getName());
+                t.printStackTrace();
+                continue;
+            }
+            try {
+                diag.init().diagnoseBuiltin();
+            } catch (WarningException e) {
+                diag.print(0, "Warning: " + e.getMessage());
+            } catch (InfoException e) {
+                diag.print(1, e.getMessage());
+            } catch (Throwable t) {
+                errCounter++;
+                ok = false;
+                diag.print(0, "");
+                t.printStackTrace();
+            }
+        }
+
+        for (Class<? extends RExternalBuiltinNode> extBltCls : extBltn) {
+            System.out.print(".");
+            SingleBuiltinDiagnostics diag;
+            try {
+                diag = createBuiltinDiagnostics(RExtBuiltinDiagFactory.create(extBltCls));
+            } catch (WarningException e) {
+                print(0, "Warning: " + e.getMessage());
+                continue;
+            } catch (InfoException e) {
+                print(1, e.getMessage());
+                continue;
+            } catch (Throwable t) {
+                errCounter++;
+                print(0, "Error in initialization of " + extBltCls.getName() + " builtin");
+                t.printStackTrace();
+                continue;
+            }
+            try {
+                diag.init().diagnoseBuiltin();
+            } catch (WarningException e) {
+                diag.print(0, "Warning: " + e.getMessage());
+            } catch (InfoException e) {
+                diag.print(1, e.getMessage());
+            } catch (Throwable t) {
+                errCounter++;
+                ok = false;
+                diag.print(0, "");
+                t.printStackTrace();
             }
-        } else {
-            bdf = new RIntBuiltinDiagFactory(bf);
         }
 
-        createBuiltinDiagnostics(bdf).diagnoseBuiltin();
+        print(0, "\n\nFinished:");
+        print(0, " Total builtins: " + nBltn);
+        print(0, " Dubious builtins: " + reportedBuiltinsCounter);
+        print(0, " Clean builtins: " + (nBltn - reportedBuiltinsCounter));
+        print(0, " Errors: " + errCounter);
+        print(0, " Warnings: " + warningCounter);
 
-        print(0, "Finished");
-        print(0, "--------");
+        System.exit(ok ? 0 : 1);
+    }
 
-        System.exit(0);
+    private static RBuiltinFactory findBuiltInFactory(Class<?> bltnCls, BasePackage bp) {
+        Optional<RBuiltinFactory> bltnFact = bp.getBuiltins().values().stream().filter(bf -> bf.getBuiltinNodeClass().isAssignableFrom(bltnCls)).findFirst();
+        if (bltnFact.isPresent()) {
+            return bltnFact.get();
+        } else {
+            throw new IllegalArgumentException("No builtin found for class " + bltnCls.getName());
+        }
     }
 
-    public void diagnoseAllBuiltins() {
-        BasePackage bp = new BasePackage();
-        for (RBuiltinFactory bf : bp.getBuiltins().values()) {
-            try {
-                createBuiltinDiagnostics(new RIntBuiltinDiagFactory((bf))).diagnoseBuiltin();
-            } catch (Exception e) {
-                e.printStackTrace();
-                print(0, bf.getName() + " failed: " + e.getMessage());
+    public static Class<?> loadBuiltinClass(String builtinClsName) throws ClassNotFoundException {
+        Class<?> nodeClass = Class.forName(builtinClsName);
+        if (!Modifier.isFinal(nodeClass.getModifiers())) {
+            nodeClass = toNodeGenClass(nodeClass);
+            if (!Modifier.isFinal(nodeClass.getModifiers())) {
+                throw new IllegalArgumentException("Invalid external builtin class name: " + builtinClsName);
             }
         }
 
-        print(0, "Finished");
-        print(0, "--------");
+        return nodeClass;
+    }
+
+    private static String toReflClassName(String qualified) {
+        String[] split = qualified.split("\\.");
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < split.length; i++) {
+            String s = split[i];
+            sb.append(s);
+            if (i < split.length - 1) {
+                if (Character.isUpperCase(s.charAt(0))) {
+                    sb.append("$");
+                } else {
+                    sb.append(".");
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private static Class<?> toNodeGenClass(Class<?> nodeCls) throws ClassNotFoundException {
+        String nodeGenClsName;
+        if (nodeCls.getEnclosingClass() == null) {
+            nodeGenClsName = nodeCls.getName() + "NodeGen";
+        } else {
+            String[] split = nodeCls.getName().split("\\.");
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < split.length; i++) {
+                String s = split[i];
+                if (i == split.length - 1) {
+                    String[] lastSplit = s.split("\\$");
+                    sb.append(lastSplit[0] + "Factory$");
+                    sb.append(lastSplit[1]);
+                    if (s.endsWith("Node")) {
+                        sb.append("Gen");
+                    } else {
+                        sb.append("NodeGen");
+                    }
+                } else {
+                    sb.append(s);
+                }
+                if (i < split.length - 1) {
+                    sb.append(".");
+                }
+            }
+            nodeGenClsName = sb.toString();
+        }
 
-        System.exit(0);
+        return Class.forName(nodeGenClsName);
     }
 
     protected void print(int level, Object x) {
+        String msg = "" + x;
+        if (msg.startsWith("Warning:")) {
+            warningCounter++;
+        }
+
         if (level <= diagConfig.outputMaxLevel) {
-            System.out.println(x);
+            System.out.println(msg);
         }
     }
 
@@ -169,35 +326,52 @@ public class RBuiltinDiagnostics {
         final String builtinName;
         final int argLength;
         final String[] parameterNames;
-        final CastNode[] castNodes;
-        final List<Method> specMethods;
-        final List<TypeExpr> argResultSets;
-        final HashMap<Method, List<Set<Cast>>> convResultTypePerSpec;
-        final Set<List<Type>> nonCoveredArgsSet;
+
+        NodeWithArgumentCasts.Casts casts;
+        List<Method> specMethods;
+        List<TypeExpr> argResultSets;
+        HashMap<Method, List<Set<Cast>>> convResultTypePerSpec;
+        Set<List<Type>> nonCoveredArgsSet;
 
         SingleBuiltinDiagnostics(RBuiltinDiagnostics diagSuite, RBuiltinDiagFactory builtinFactory) {
             this.diagSuite = diagSuite;
             this.builtinFactory = builtinFactory;
             this.builtinName = builtinFactory.getBuiltinName();
-
             String[] pn = builtinFactory.getParameterNames();
             this.argLength = pn.length;
             this.parameterNames = Arrays.stream(pn).map(n -> n == null || n.isEmpty() ? null : n).toArray(String[]::new);
+        }
 
-            this.castNodes = getCastNodesFromBuiltin();
+        SingleBuiltinDiagnostics init() throws Throwable {
+            String builtinClassName = builtinFactory.getBuiltinNodeClass().getName();
+            // causes the invocation of the static initializer in the builtin node class
+            Class<?> bltnCls = NodeWithArgumentCasts.Casts.getBuiltinClass(Class.forName(builtinClassName));
 
-            List<TypeExpr> argResultSetsPreliminary = createArgResultSets();
-            argResultSets = argResultSetsPreliminary.stream().map(te -> te.filter(t -> {
-                return !((diagSuite.diagConfig.ignoreRNull && t == RNull.class) || (diagSuite.diagConfig.ignoreRMissing && t == RMissing.class));
-            })).collect(Collectors.toList());
+            try {
+                this.casts = builtinFactory.getCasts();
+            } catch (RInternalError e) {
+                // It will be converted into an error after all builtins are fixed
+                throw new WarningException("Builtin " + builtinClassName + " should declare argument casts or use Casts.noCasts(" + bltnCls.getSimpleName() + ".class)");
+            }
+
+            if (this.casts == null || this.casts.declaresNoCasts()) {
+                throw new InfoException("Builtin " + builtinClassName + " has no-casts");
+            }
+
+            argResultSets = createArgResultSets();
 
             this.specMethods = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class);
 
             this.convResultTypePerSpec = createConvResultTypePerSpecialization();
             this.nonCoveredArgsSet = combineArguments();
+
+            return this;
         }
 
+        private boolean headerPrinted;
+
         protected void print(int level, Object x) {
+            printBuiltinHeader(level);
             diagSuite.print(level, x);
         }
 
@@ -233,29 +407,37 @@ public class RBuiltinDiagnostics {
         }
 
         public void diagnoseBuiltin() throws Exception {
-            print(0, "****************************************************************************");
-            print(0, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getName() + ")");
-            print(0, "****************************************************************************");
-
-            print(0, "Argument cast pipelines binding:");
+            print(1, "Argument cast pipelines binding:");
             for (int i = 0; i < argLength; i++) {
                 diagnosePipeline(i);
             }
 
-            print(0, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size());
-            print(0, "");
+            print(1, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size());
+            print(1, "");
 
             printDeadSpecs();
 
             if (diagSuite.diagConfig.verbose) {
                 for (List<Type> uncoveredArgs : nonCoveredArgsSet) {
-                    print(0, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList()));
+                    print(1, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList()));
                 }
             }
         }
 
+        private void printBuiltinHeader(int level) {
+            if (!headerPrinted && level <= diagSuite.diagConfig.outputMaxLevel) {
+                diagSuite.print(level, "\n");
+                diagSuite.print(level, "****************************************************************************");
+                diagSuite.print(level, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getCanonicalName() + ")");
+                diagSuite.print(level, "****************************************************************************");
+                headerPrinted = true;
+                diagSuite.reportedBuiltinsCounter++;
+            }
+        }
+
         private void printDeadSpecs() {
-            print(0, "Dead specializations: ");
+            StringBuilder sb = new StringBuilder();
+            int deadSpecCnt = 0;
             for (Map.Entry<Method, List<Set<Cast>>> resTpPerSpec : convResultTypePerSpec.entrySet()) {
                 List<Set<Cast>> argsCasts = resTpPerSpec.getValue();
                 List<Integer> missingCasts = new ArrayList<>();
@@ -267,52 +449,90 @@ public class RBuiltinDiagnostics {
                 }
 
                 if (!missingCasts.isEmpty()) {
-                    print(0, "   " + methodName(resTpPerSpec.getKey(), missingCasts));
+                    sb.append("   " + methodName(resTpPerSpec.getKey(), missingCasts) + "\n");
+                    deadSpecCnt++;
                 }
             }
 
-            print(0, "");
+            int logLev = deadSpecCnt == 0 ? 1 : 0;
+            String msg = deadSpecCnt == 0 ? "Dead specializations: " + deadSpecCnt : "Warning: Dead specializations: " + deadSpecCnt;
+            print(logLev, msg);
+            print(logLev, sb.toString());
         }
 
         protected void diagnosePipeline(int i) {
             TypeExpr argResultSet = argResultSets.get(i);
-            print(0, "\n Pipeline for '" + parameterNames[i] + "' (arg[" + i + "]):");
-            print(0, "  Result types union:");
-            Set<Type> argSetNorm = argResultSet.normalize();
-            print(0, "   " + argSetNorm.stream().map(argType -> typeName(argType)).collect(Collectors.toSet()));
-            print(0, "  Bound result types:");
+
+            String pipelineHeader = "Pipeline for '" + parameterNames[i] + "' (arg[" + i + "])";
+
+            StringBuilder sb = new StringBuilder();
+            sb.append("  Result types union:").append('\n');
+            Set<Type> argSetNorm = argResultSet.toNormalizedConjunctionSet();
+            sb.append("   " + argSetNorm.stream().map(argType -> typeName(argType)).collect(Collectors.toSet())).append('\n');
+            sb.append("  Bound result types:").append('\n');
             final int curParIndex = i;
             Set<Type> unboundArgTypes = new HashSet<>(argSetNorm);
             for (Map.Entry<Method, List<Set<Cast>>> entry : convResultTypePerSpec.entrySet()) {
                 Set<Cast> argCastInSpec = entry.getValue().get(i);
                 argCastInSpec.stream().forEach(
                                 partialCast -> {
-                                    print(0, "   " + partialCast.coverage() + " (" + typeName(partialCast.inputType()) + "->" + typeName(partialCast.resultType()) + ")" + " in " +
-                                                    methodName(entry.getKey(), Collections.singleton(curParIndex)));
+                                    sb.append("   " + partialCast.coverage() + " (" + typeName(partialCast.inputType()) + "->" + typeName(partialCast.resultType()) + ")" + " in " +
+                                                    methodName(entry.getKey(), Collections.singleton(curParIndex))).append('\n');
                                     unboundArgTypes.remove(partialCast.inputType());
                                 });
             }
-            print(0, "  Unbound types:");
-            print(0, "   " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet()));
-
-        }
+            if (unboundArgTypes.isEmpty()) {
+                print(1, pipelineHeader);
+            } else {
+                print(0, "Warning: " + pipelineHeader);
+                print(0, "   Unbound types: " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet()));
+            }
+            print(1, sb.toString());
 
-        private CastNode[] getCastNodesFromBuiltin() {
-            return builtinFactory.getCasts();
         }
 
         private List<TypeExpr> createArgResultSets() {
+            Object[] defParams = null;
+            try {
+                defParams = builtinFactory.getDefaultParameterValues();
+            } catch (Throwable t) {
+                print(0, "Warning: Cannot obtain default parameter values. Cause: " + t.getMessage());
+                if (diagSuite.diagConfig.outputMaxLevel > 0) {
+                    t.printStackTrace();
+                }
+            }
+
+            if (defParams != null && defParams.length > 0 && defParams.length < argLength) {
+                throw new RInternalError("Builtin " + builtinName + " provides invalid default parameter values");
+            }
+
             List<TypeExpr> as = new ArrayList<>();
+            PipelineBuilder[] plBuilders = casts.getPipelineBuilders();
             for (int i = 0; i < argLength; i++) {
-                CastNode cn;
-                if (i < castNodes.length) {
-                    cn = castNodes[i];
+
+                PipelineBuilder plBuilder;
+                if (i < plBuilders.length) {
+                    plBuilder = plBuilders[i];
                 } else {
-                    cn = null;
+                    plBuilder = null;
                 }
                 TypeExpr te;
                 try {
-                    te = cn == null ? TypeExpr.ANYTHING : CastNodeSampler.createSampler(cn).resultTypes();
+                    if (plBuilder == null) {
+                        te = TypeExpr.ANYTHING;
+                    } else {
+                        te = ResultTypesAnalyser.analyse(plBuilder.getFirstStep()).removeWildcards();
+
+                        if (!te.and(rmissingType).isNothing()) {
+                            // try to find a replacement for RMissing
+                            if ((defParams != null && defParams.length > i) && defParams[i] != RMissing.instance) {
+                                // Cancel RMissing in the result type if there is a
+                                // substitution for it
+                                te = te.and(rmissingType.not());
+                            }
+                        }
+
+                    }
                 } catch (Exception e) {
                     throw new RuntimeException("Cannot create sampler for argument " + parameterNames[i], e);
                 }
@@ -368,8 +588,11 @@ public class RBuiltinDiagnostics {
 
         String[] getParameterNames();
 
-        CastNode[] getCasts();
+        Object[] getDefaultParameterValues();
 
+        CastNode[] getCastNodes();
+
+        NodeWithArgumentCasts.Casts getCasts();
     }
 
     public static final class RIntBuiltinDiagFactory implements RBuiltinDiagFactory {
@@ -378,6 +601,11 @@ public class RBuiltinDiagnostics {
 
         public RIntBuiltinDiagFactory(RBuiltinFactory fact) {
             super();
+
+            if (!RBuiltinNode.class.isAssignableFrom(fact.getBuiltinNodeClass())) {
+                throw new InfoException("A 'fake' builtin");
+            }
+
             this.fact = fact;
         }
 
@@ -403,9 +631,25 @@ public class RBuiltinDiagnostics {
         }
 
         @Override
-        public CastNode[] getCasts() {
+        public CastNode[] getCastNodes() {
             return fact.getConstructor().get().getCasts();
         }
+
+        @Override
+        public NodeWithArgumentCasts.Casts getCasts() {
+            return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinNodeClass());
+        }
+
+        @Override
+        public Object[] getDefaultParameterValues() {
+            switch (getBuiltinKind()) {
+                case SUBSTITUTE:
+                case PRIMITIVE:
+                    return fact.getConstructor().get().getDefaultParameterValues();
+                default:
+                    return null;
+            }
+        }
     }
 
     public static final class RExtBuiltinDiagFactory implements RBuiltinDiagFactory {
@@ -422,18 +666,10 @@ public class RBuiltinDiagnostics {
         }
 
         @SuppressWarnings("unchecked")
-        public static RExtBuiltinDiagFactory create(String extBuiltinClsName) throws ClassNotFoundException {
-            Class<?> nodeClass = Class.forName(extBuiltinClsName);
-
-            if (!Modifier.isFinal(nodeClass.getModifiers())) {
-                nodeClass = Class.forName(extBuiltinClsName + "NodeGen");
-                if (!Modifier.isFinal(nodeClass.getModifiers())) {
-                    throw new IllegalArgumentException("Invalid external builtin class name: " + extBuiltinClsName);
-                }
-            }
+        public static RExtBuiltinDiagFactory create(Class<?> nodeClass) {
 
             if (!RExternalBuiltinNode.class.isAssignableFrom(nodeClass)) {
-                throw new IllegalArgumentException(extBuiltinClsName + " is not a subclass of " + RExternalBuiltinNode.class.getName());
+                throw new IllegalArgumentException(nodeClass.getName() + " is not a subclass of " + RExternalBuiltinNode.class.getName());
             }
 
             Optional<Method> execMethod = Arrays.stream(nodeClass.getMethods()).filter(
@@ -441,7 +677,7 @@ public class RBuiltinDiagnostics {
             if (execMethod.isPresent()) {
                 return new RExtBuiltinDiagFactory((Class<RExternalBuiltinNode>) nodeClass, execMethod.get().getParameterCount());
             } else {
-                throw new UnsupportedOperationException(extBuiltinClsName + " is not a supported external builtin class");
+                throw new InfoException("no-args builtin '" + nodeClass.getName());
             }
         }
 
@@ -461,12 +697,36 @@ public class RBuiltinDiagnostics {
         }
 
         @Override
-        public CastNode[] getCasts() {
+        public CastNode[] getCastNodes() {
             try {
                 return ((RExternalBuiltinNode) nodeClass.getMethod("create").invoke(null)).getCasts();
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
         }
+
+        @Override
+        public NodeWithArgumentCasts.Casts getCasts() {
+            return NodeWithArgumentCasts.Casts.getCasts(getBuiltinNodeClass());
+        }
+
+        @Override
+        public Object[] getDefaultParameterValues() {
+            return null;
+        }
+    }
+
+    @SuppressWarnings("serial")
+    private static final class InfoException extends RuntimeException {
+        InfoException(String msg) {
+            super(msg);
+        }
+    }
+
+    @SuppressWarnings("serial")
+    private static final class WarningException extends RuntimeException {
+        WarningException(String msg) {
+            super(msg);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java
deleted file mode 100644
index 8ec4b0dc84..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/BypassNodeGenSampler.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.r.nodes.casts.ArgumentMapperSampler;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
-
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class BypassNodeGenSampler extends CastNodeSampler<BypassNodeGen> {
-
-    private final CastNodeSampler wrappedHeadSampler;
-    private final ArgumentMapperSampler nullMapper;
-    private final ArgumentMapperSampler missingMapper;
-
-    public BypassNodeGenSampler(BypassNodeGen bypassNode) {
-        super(bypassNode);
-        this.wrappedHeadSampler = bypassNode.getWrappedHead() == null ? null : createSampler(bypassNode.getWrappedHead());
-
-        assert bypassNode.getNullMapper() == null || bypassNode.getNullMapper() instanceof ArgumentMapperSampler;
-        assert bypassNode.getMissingMapper() == null || bypassNode.getMissingMapper() instanceof ArgumentMapperSampler;
-
-        this.nullMapper = (ArgumentMapperSampler) bypassNode.getNullMapper();
-        this.missingMapper = (ArgumentMapperSampler) bypassNode.getMissingMapper();
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputTypes, SamplingContext ctx) {
-        TypeExpr rt = wrappedHeadSampler == null ? TypeExpr.ANYTHING : wrappedHeadSampler.resultTypes(inputTypes, ctx);
-        if (nullMapper != null) {
-            rt = rt.or(nullMapper.resultTypes(inputTypes));
-        } else {
-            rt = rt.and(TypeExpr.atom(RNull.class).not());
-        }
-        if (missingMapper != null) {
-            rt = rt.or(missingMapper.resultTypes(inputTypes));
-        } else {
-            rt = rt.and(TypeExpr.atom(RMissing.class).not());
-        }
-        return rt;
-    }
-
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        Samples<?> samples = wrappedHeadSampler == null ? Samples.nothing() : wrappedHeadSampler.collectSamples(inputType, downStreamSamples);
-        if (nullMapper != null) {
-            samples = samples.or(nullMapper.collectSamples(downStreamSamples));
-        }
-        if (missingMapper != null) {
-            samples = samples.or(missingMapper.collectSamples(downStreamSamples));
-        }
-        return samples;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java
deleted file mode 100644
index c493163b64..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/CastToVectorNodeGenSampler.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import java.util.Arrays;
-import java.util.List;
-
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.CastUtils.Cast;
-import com.oracle.truffle.r.nodes.casts.CastUtils.Casts;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-import com.oracle.truffle.r.runtime.data.RExpression;
-import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-public class CastToVectorNodeGenSampler extends CastNodeSampler<CastToVectorNodeGen> {
-
-    public CastToVectorNodeGenSampler(CastToVectorNodeGen castNode) {
-        super(castNode);
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) {
-        List<Cast> castList;
-        if (castNode.isPreserveNonVector()) {
-            castList = Arrays.asList(new Cast(RNull.class, RNull.class),
-                            new Cast(RMissing.class, RNull.class),
-                            new Cast(RFunction.class, RFunction.class),
-                            new Cast(RAbstractVector.class, RAbstractVector.class),
-                            new Cast(RExpression.class, RList.class));
-        } else {
-            castList = Arrays.asList(new Cast(RNull.class, RList.class),
-                            new Cast(RMissing.class, RList.class),
-                            new Cast(RFunction.class, RList.class),
-                            new Cast(RAbstractVector.class, RAbstractVector.class),
-                            new Cast(RExpression.class, RList.class));
-        }
-        TypeExpr narrowed = Casts.createCasts(castList).narrow(inputType);
-        return narrowed;
-    }
-
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        return downStreamSamples;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java
deleted file mode 100644
index d2a01b173d..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ChainedCastNodeSampler.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-
-public final class ChainedCastNodeSampler extends CastNodeSampler<ChainedCastNode> {
-
-    private final CastNodeSampler<?> firstCast;
-    private final CastNodeSampler<?> secondCast;
-
-    public ChainedCastNodeSampler(ChainedCastNode castNode) {
-        super(castNode);
-
-        firstCast = createSampler(castNode.getFirstCast());
-        secondCast = createSampler(castNode.getSecondCast());
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputTypes, SamplingContext ctx) {
-        return secondCast.resultTypes(firstCast.resultTypes(inputTypes, ctx), ctx);
-    }
-
-    @Override
-    public String toString() {
-        return firstCast.toString();
-    }
-
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputTypes, Samples<?> downStreamSamples) {
-        TypeExpr rt1 = firstCast.resultTypes(inputTypes, new SamplingContext());
-        return firstCast.collectSamples(inputTypes, secondCast.collectSamples(rt1, downStreamSamples));
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java
deleted file mode 100644
index 3b8a88b017..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNodeGenSampler.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class ConditionalMapNodeGenSampler extends CastNodeSampler<ConditionalMapNodeGen> {
-
-    private final ArgumentFilterSampler argFilter;
-    private final CastNodeSampler trueBranch;
-    private final CastNodeSampler falseBranch;
-
-    public ConditionalMapNodeGenSampler(ConditionalMapNodeGen castNode) {
-        super(castNode);
-        argFilter = (ArgumentFilterSampler) castNode.getFilter();
-        trueBranch = createSampler(castNode.getTrueBranch());
-        falseBranch = createSampler(castNode.getFalseBranch());
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) {
-        if (castNode.isReturns()) {
-            ctx.addAltResultType(trueBranchResultTypes(inputType, ctx));
-            return falseBranchResultTypes(inputType, ctx);
-        } else {
-            return trueBranchResultTypes(inputType, ctx).or(falseBranchResultTypes(inputType, ctx));
-        }
-    }
-
-    private TypeExpr trueBranchResultTypes(TypeExpr inputType, SamplingContext ctx) {
-        if (trueBranch != null) {
-            return trueBranch.resultTypes(argFilter.trueBranchType().and(inputType), ctx);
-        } else {
-            return argFilter.trueBranchType().and(inputType);
-        }
-    }
-
-    private TypeExpr falseBranchResultTypes(TypeExpr inputType, SamplingContext ctx) {
-        if (falseBranch != null) {
-            return falseBranch.resultTypes(argFilter.falseBranchType().and(inputType), ctx);
-        } else {
-            return argFilter.falseBranchType().and(inputType);
-        }
-    }
-
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        TypeExpr trueBranchResultType = trueBranchResultTypes(inputType, new SamplingContext());
-        TypeExpr falseBranchResultType = falseBranchResultTypes(inputType, new SamplingContext());
-
-        // filter out the incompatible samples
-        Samples compatibleTrueBranchDownStreamSamples = downStreamSamples.filter(x -> trueBranchResultType.isInstance(x));
-        Samples compatibleFalseBranchDownStreamSamples = downStreamSamples.filter(x -> falseBranchResultType.isInstance(x));
-
-        Samples trueBranchSamples = trueBranch.collectSamples(argFilter.trueBranchType().and(inputType), compatibleTrueBranchDownStreamSamples);
-        Samples falseBranchSamples = falseBranch == null ? compatibleFalseBranchDownStreamSamples
-                        : falseBranch.collectSamples(argFilter.falseBranchType().and(inputType), compatibleFalseBranchDownStreamSamples);
-        Samples bothBranchesSamples = trueBranchSamples.or(falseBranchSamples);
-
-        // Collect the "interesting" samples from the condition. Both positive and negative samples
-        // are actually interpreted as positive ones.
-        Samples origConditionSamples = argFilter.collectSamples(inputType).makePositive();
-        // Merge the samples from the branches with the condition samples
-        return origConditionSamples.or(bothBranchesSamples);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java
deleted file mode 100644
index 4a73a29cce..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FilterNodeGenSampler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.r.nodes.casts.ArgumentFilterSampler;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-
-@SuppressWarnings("rawtypes")
-public class FilterNodeGenSampler extends CastNodeSampler<FilterNodeGen> {
-
-    private final ArgumentFilterSampler filter;
-    private final boolean isWarning;
-    private final TypeExpr resType;
-
-    public FilterNodeGenSampler(FilterNodeGen castNode) {
-        super(castNode);
-        assert castNode.getFilter() instanceof ArgumentFilterSampler : "Check PredefFiltersSamplers is installed in Predef";
-        this.filter = (ArgumentFilterSampler) castNode.getFilter();
-        this.isWarning = castNode.isWarning();
-        this.resType = filter.trueBranchType();
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) {
-        if (isWarning) {
-            return inputType;
-        } else {
-            return inputType.and(resType);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        if (isWarning) {
-            return downStreamSamples;
-        } else {
-            Samples samples = filter.collectSamples(inputType);
-
-            Samples<?> combined = samples.and(downStreamSamples);
-            return combined;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java
deleted file mode 100644
index 2135903ab2..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/FindFirstNodeGenSampler.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import java.lang.reflect.Type;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.CastUtils;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-public class FindFirstNodeGenSampler extends CastNodeSampler<FindFirstNodeGen> {
-
-    private final Object defaultValue;
-    private final Class<?> elementClass;
-
-    public FindFirstNodeGenSampler(FindFirstNodeGen castNode) {
-        super(castNode);
-        this.elementClass = castNode.getElementClass();
-        this.defaultValue = castNode.getDefaultValue();
-    }
-
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        Samples<Object> defaultSamples = defaultSamples();
-
-        // convert scalar samples to vector ones
-        Samples<Object> vectorizedSamples = downStreamSamples.map(x -> CastUtils.singletonVector(x), x -> CastUtils.singletonVector(x),
-                        x -> CastUtils.firstElement(x, defaultValue), x -> CastUtils.firstElement(x, defaultValue));
-        Samples<Object> combined = defaultSamples.and(vectorizedSamples);
-        return combined;
-    }
-
-    private Samples<Object> defaultSamples() {
-        Set<Object> defaultNegativeSamples = new HashSet<>();
-        Set<Object> defaultPositiveSamples = new HashSet<>();
-
-        if (defaultValue == null) {
-            defaultNegativeSamples.add(RNull.instance);
-            Object emptyVec = CastUtils.emptyVector(elementClass);
-            if (emptyVec != null) {
-                defaultNegativeSamples.add(emptyVec);
-            }
-
-            Predicate<Object> posMembership = this::testVectorForNoDefaultValCase;
-
-            return new Samples<>("findFirst-noDef", defaultPositiveSamples, defaultNegativeSamples, posMembership);
-        } else {
-            defaultPositiveSamples.add(CastUtils.singletonVector(defaultValue));
-            defaultPositiveSamples.add(RNull.instance);
-            Object emptyVec = CastUtils.emptyVector(elementClass);
-            if (emptyVec != null) {
-                defaultPositiveSamples.add(emptyVec);
-            }
-
-            Predicate<Object> posMembership = this::testVectorForDefaultValCase;
-
-            return new Samples<>("findFirst-withDef", defaultPositiveSamples, defaultNegativeSamples, posMembership);
-        }
-    }
-
-    private boolean testVectorForNoDefaultValCase(Object x) {
-        if (x == RMissing.instance || x == RNull.instance || x == null) {
-            return false;
-        }
-
-        if (x instanceof RAbstractVector) {
-            Class<?> elemCls = CastUtils.vectorElementType(x).orElse(null);
-            return elemCls != null && elementClass.isAssignableFrom(elemCls) && ((RAbstractVector) x).getLength() > 0;
-        } else {
-            return elementClass.isInstance(x);
-        }
-    }
-
-    private boolean testVectorForDefaultValCase(Object x) {
-        if (x == RMissing.instance || x == RNull.instance || x == null) {
-            return true;
-        }
-
-        if (x instanceof RAbstractVector) {
-            Class<?> elemCls = CastUtils.vectorElementType(x).orElse(null);
-            return elemCls != null && elementClass.isAssignableFrom(elemCls);
-        } else {
-            return elementClass.isInstance(x);
-        }
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) {
-        TypeExpr rt;
-        if (elementClass == null || elementClass == Object.class) {
-            if (inputType.isAnything()) {
-                rt = TypeExpr.atom(RAbstractVector.class).not();
-            } else {
-                Set<Type> resTypes = inputType.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet());
-                rt = TypeExpr.union(resTypes);
-            }
-        } else {
-            rt = TypeExpr.atom(elementClass);
-        }
-
-        return rt;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java
deleted file mode 100644
index 079c4090a1..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/MapNodeSampler.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.r.nodes.casts.ArgumentMapperSampler;
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class MapNodeSampler extends CastNodeSampler<MapNode> {
-
-    private final ArgumentMapperSampler mapFn;
-
-    public MapNodeSampler(MapNode castNode) {
-        super(castNode);
-        assert castNode.getMapper() instanceof ArgumentMapperSampler;
-        this.mapFn = (ArgumentMapperSampler) castNode.getMapper();
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputTypes, SamplingContext ctx) {
-        return mapFn.resultTypes(inputTypes);
-    }
-
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputType, Samples<?> downStreamSamples) {
-        return mapFn.collectSamples(downStreamSamples);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java
deleted file mode 100644
index 3f2f805208..0000000000
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/unary/NonNANodeGenSampler.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import com.oracle.truffle.r.nodes.casts.CastNodeSampler;
-import com.oracle.truffle.r.nodes.casts.CastUtils;
-import com.oracle.truffle.r.nodes.casts.Samples;
-import com.oracle.truffle.r.nodes.casts.TypeExpr;
-
-public class NonNANodeGenSampler extends CastNodeSampler<NonNANodeGen> {
-
-    private final Object naReplacement;
-
-    public NonNANodeGenSampler(NonNANodeGen castNode) {
-        super(castNode);
-        naReplacement = castNode.getNAReplacement();
-    }
-
-    @Override
-    public TypeExpr resultTypes(TypeExpr inputType, SamplingContext ctx) {
-        return inputType;
-    }
-
-    @SuppressWarnings("unchecked")
-    private <T> Optional<T> unmap(T x) {
-        if (naReplacement == null) {
-            return CastUtils.isNaValue(x) ? Optional.empty() : Optional.of(x);
-        } else {
-            return CastUtils.isNaValue(x) ? Optional.of((T) naReplacement) : Optional.of(x);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Samples<?> collectSamples(TypeExpr inputTypes, Samples<?> downStreamSamples) {
-        Set<Object> defaultPositiveSamples;
-        Set<Object> defaultNegativeSamples;
-
-        Samples<Object> mappedSamples = ((Samples<Object>) downStreamSamples).map(x -> x, x -> x, this::unmap, this::unmap);
-
-        Set<Object> naSamples = inputTypes.normalize().stream().filter(t -> t instanceof Class).map(t -> CastUtils.naValue((Class<?>) t)).filter(x -> x != null).collect(Collectors.toSet());
-        if (naReplacement != null) {
-            defaultNegativeSamples = Collections.emptySet();
-            defaultPositiveSamples = new HashSet<>();
-            defaultPositiveSamples.add(naReplacement);
-            defaultPositiveSamples.addAll(naSamples);
-        } else {
-            defaultNegativeSamples = naSamples;
-            defaultPositiveSamples = Collections.emptySet();
-        }
-
-        Predicate<Object> posMembership = x -> naReplacement != null || !CastUtils.isNaValue(x);
-        Samples<Object> defaultSamples = new Samples<>("nonNA-" + naReplacement == null ? "noDef" : "withDef", defaultPositiveSamples, defaultNegativeSamples, posMembership);
-
-        Samples<Object> combined = defaultSamples.and(mappedSamples);
-        return combined;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java
index 192e48d595..944c3574d9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java
@@ -28,6 +28,8 @@ import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -44,28 +46,28 @@ public abstract class BoxPrimitiveNode extends CastNode {
     }
 
     @Specialization
-    protected static RAbstractVector doInt(int vector) {
+    protected static RInteger doInt(int vector) {
         return RInteger.valueOf(vector);
     }
 
     @Specialization
-    protected static RAbstractVector doDouble(double vector) {
+    protected static RDouble doDouble(double vector) {
         return RDouble.valueOf(vector);
     }
 
     @Specialization
-    protected static RAbstractVector doLogical(byte vector) {
+    protected static RLogical doLogical(byte vector) {
         return RLogical.valueOf(vector);
     }
 
     @Specialization
-    protected static RAbstractVector doString(String value) {
+    protected static RString doString(String value) {
         return RString.valueOf(value);
     }
 
     /*
      * For the limit we use the number of primitive specializations - 1. After that its better to
-     * check !isPrimitve.
+     * check !isPrimitive.
      */
     @Specialization(limit = "3", guards = "vector.getClass() == cachedClass")
     protected static Object doCached(Object vector,
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 98aedf151d..976a9281b7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -134,6 +134,16 @@ public final class CastBuilder {
         return castNodes;
     }
 
+    /**
+     * The argument pipeline builders are needed when analyzing pipelines without instantiating
+     * them. It's useful in tests.
+     *
+     * @return the arguments cast pipeline builders
+     */
+    public PipelineBuilder[] getPipelineBuilders() {
+        return argumentBuilders;
+    }
+
     // ---------------------
     // The cast-pipelines API starts here
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
index cd1b4a44df..2567981144 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
@@ -25,17 +25,21 @@ package com.oracle.truffle.r.nodes.builtin;
 import java.util.concurrent.ConcurrentHashMap;
 
 import com.oracle.truffle.api.dsl.GeneratedBy;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 public interface NodeWithArgumentCasts {
 
     default Casts getCastHolder() {
-        Class<?> cls = Casts.getBuiltinClass(getClass());
-        Casts casts = Casts.forClass(cls);
-        assert casts != null || Casts.noCastsAllowed(getClass().getSuperclass()) : "No casts associated with builtin " + cls;
+        return getStaticCasts(getClass());
+    }
+
+    static Casts getStaticCasts(Class<?> builtinClass) {
+        Casts casts = Casts.getCasts(builtinClass);
         return casts == null ? Casts.empty : casts;
     }
 
@@ -46,21 +50,36 @@ public interface NodeWithArgumentCasts {
 
     final class Casts {
         private static final ConcurrentHashMap<Class<?>, Casts> castsMap = new ConcurrentHashMap<>();
-        private static final Casts empty = new Casts();
+        private static final Casts empty = new Casts(false);
 
         protected final CastBuilder casts;
+        private final boolean declaresNoCasts;
 
-        private Casts() {
+        private Casts(boolean noCasts) {
             casts = new CastBuilder();
+            this.declaresNoCasts = noCasts;
         }
 
-        public Casts(Class<? extends NodeWithArgumentCasts> cls) {
-            casts = new CastBuilder(cls.getAnnotation(RBuiltin.class));
+        private Casts(Class<? extends NodeWithArgumentCasts> cls, boolean noCasts) {
             castsMap.put(cls, this);
+            casts = new CastBuilder(cls.getAnnotation(RBuiltin.class));
+            this.declaresNoCasts = noCasts;
+        }
+
+        public Casts(Class<? extends NodeWithArgumentCasts> cls) {
+            this(cls, false);
         }
 
         public static void noCasts(Class<? extends NodeWithArgumentCasts> cls) {
-            castsMap.put(cls, new Casts(cls));
+            castsMap.put(cls, new Casts(cls, true));
+        }
+
+        /**
+         * Indicates that a builtin uses the {@link Casts#noCasts(Class)} to declare that it uses no
+         * arguments casts although it has one or more arguments.
+         */
+        public boolean declaresNoCasts() {
+            return declaresNoCasts;
         }
 
         public static Casts forClass(Class<?> cls) {
@@ -71,6 +90,10 @@ public interface NodeWithArgumentCasts {
             return casts.getCasts();
         }
 
+        public PipelineBuilder[] getPipelineBuilders() {
+            return casts.getPipelineBuilders();
+        }
+
         public PreinitialPhaseBuilder arg(String argumentName) {
             return casts.arg(argumentName);
         }
@@ -83,6 +106,15 @@ public interface NodeWithArgumentCasts {
             return casts.arg(argumentIndex);
         }
 
+        public static Casts getCasts(Class<?> builtinClass) {
+            Class<?> cls = Casts.getBuiltinClass(builtinClass);
+            Casts casts = Casts.forClass(cls);
+            if (casts == null && !noCastsAllowed(cls)) {
+                throw RInternalError.shouldNotReachHere("No casts associated with builtin " + cls);
+            }
+            return casts;
+        }
+
         private static boolean noCastsAllowed(Class<?> cls) {
             boolean res = RExternalBuiltinNode.Arg0.class.isAssignableFrom(cls) || UnaryArithmeticBuiltinNode.class.isAssignableFrom(cls) ||
                             (RBuiltinNode.class.isAssignableFrom(cls) && hasNoArguments(cls));
@@ -94,7 +126,7 @@ public interface NodeWithArgumentCasts {
             return a != null && a.parameterNames().length == 0;
         }
 
-        private static Class<?> getBuiltinClass(Class<?> cls) {
+        public static Class<?> getBuiltinClass(Class<?> cls) {
             if (cls.getAnnotation(GeneratedBy.class) != null) {
                 return cls.getSuperclass();
             } else {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
new file mode 100644
index 0000000000..fc8abb28d8
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.casts;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor;
+
+public abstract class ExecutionPathVisitor<T> implements PipelineStepVisitor<T> {
+
+    private Map<MapIfStep<?, ?>, Integer> mapIfStepStatuses;
+    private BitSet bs;
+    private int mapIfCounter;
+    private List<T> results = new ArrayList<>();
+
+    public List<T> visitPaths(PipelineStep<?, ?> firstStep, T initial) {
+        if (firstStep == null) {
+            return Collections.singletonList(initial);
+        }
+        mapIfStepStatuses = new HashMap<>();
+        results.add(firstStep.acceptPipeline(this, initial));
+        int n = 1 << mapIfStepStatuses.size();
+        for (long i = 1; i < n; i++) {
+            bs = BitSet.valueOf(new long[]{i});
+            results.add(firstStep.acceptPipeline(this, initial));
+        }
+        return results;
+    }
+
+    @Override
+    public final T visit(MapIfStep<?, ?> step, T previous) {
+        boolean visitTrueBranch = bs == null ? false : bs.get(mapIfStepStatuses.get(step));
+        if (bs == null) {
+            visitTrueBranch = false;
+            mapIfStepStatuses.put(step, mapIfCounter++);
+        } else {
+            visitTrueBranch = bs.get(mapIfStepStatuses.get(step));
+        }
+        return visitBranch(step, previous, visitTrueBranch);
+    }
+
+    protected abstract T visitBranch(MapIfStep<?, ?> step, T previous, boolean visitTrueBranch);
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
index f26904e04c..4771b0097c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
@@ -40,11 +40,6 @@ public abstract class Filter<T, R extends T> {
     protected Filter() {
     }
 
-    /**
-     * @return true if this filter narrows the input type to a sub-type
-     */
-    public abstract boolean isNarrowing();
-
     public ResultForArg resultForNull() {
         return ResultForArg.UNDEFINED;
     }
@@ -53,7 +48,7 @@ public abstract class Filter<T, R extends T> {
         return ResultForArg.UNDEFINED;
     }
 
-    public abstract <D> D accept(FilterVisitor<D> visitor);
+    public abstract <D> D accept(FilterVisitor<D> visitor, D previous);
 
     public <S extends R> AndFilter<T, S> and(Filter<? super R, S> other) {
         return new AndFilter<>(this, other);
@@ -68,25 +63,25 @@ public abstract class Filter<T, R extends T> {
     }
 
     public interface FilterVisitor<D> {
-        D visit(TypeFilter<?, ?> filter);
+        D visit(TypeFilter<?, ?> filter, D previous);
 
-        D visit(RTypeFilter<?> filter);
+        D visit(RTypeFilter<?> filter, D previous);
 
-        D visit(CompareFilter<?> filter);
+        D visit(CompareFilter<?> filter, D previous);
 
-        D visit(AndFilter<?, ?> filter);
+        D visit(AndFilter<?, ?> filter, D previous);
 
-        D visit(OrFilter<?> filter);
+        D visit(OrFilter<?> filter, D previous);
 
-        D visit(NotFilter<?> filter);
+        D visit(NotFilter<?> filter, D previous);
 
-        D visit(MatrixFilter<?> filter);
+        D visit(MatrixFilter<?> filter, D previous);
 
-        D visit(DoubleFilter filter);
+        D visit(DoubleFilter filter, D previous);
 
-        D visit(NullFilter filter);
+        D visit(NullFilter filter, D previous);
 
-        D visit(MissingFilter filter);
+        D visit(MissingFilter filter, D previous);
     }
 
     /**
@@ -134,11 +129,6 @@ public abstract class Filter<T, R extends T> {
             return extraCondition;
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return true;
-        }
-
         @SuppressWarnings("unchecked")
         public ArgumentFilter<Object, Object> getInstanceOfLambda() {
             final ArgumentFilter<Object, Object> instanceOfLambda;
@@ -163,8 +153,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -195,13 +185,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public boolean isNarrowing() {
-            return true;
-        }
-
-        @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -223,13 +208,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public boolean isNarrowing() {
-            return true;
-        }
-
-        @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -251,13 +231,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public boolean isNarrowing() {
-            return true;
-        }
-
-        @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -278,21 +253,21 @@ public abstract class Filter<T, R extends T> {
     public static final class CompareFilter<T> extends Filter<T, T> {
 
         public interface Subject {
-            <D> D accept(SubjectVisitor<D> visitor, byte operation);
+            <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous);
         }
 
         public interface SubjectVisitor<D> {
-            D visit(ScalarValue scalarValue, byte operation);
+            D visit(ScalarValue scalarValue, byte operation, D previous);
 
-            D visit(NATest naTest, byte operation);
+            D visit(NATest naTest, byte operation, D previous);
 
-            D visit(StringLength stringLength, byte operation);
+            D visit(StringLength stringLength, byte operation, D previous);
 
-            D visit(VectorSize vectorSize, byte operation);
+            D visit(VectorSize vectorSize, byte operation, D previous);
 
-            D visit(ElementAt elementAt, byte operation);
+            D visit(ElementAt elementAt, byte operation, D previous);
 
-            D visit(Dim dim, byte operation);
+            D visit(Dim dim, byte operation, D previous);
         }
 
         public static final class ScalarValue implements Subject {
@@ -305,8 +280,8 @@ public abstract class Filter<T, R extends T> {
             }
 
             @Override
-            public <D> D accept(SubjectVisitor<D> visitor, byte operation) {
-                return visitor.visit(this, operation);
+            public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) {
+                return visitor.visit(this, operation, previous);
             }
         }
 
@@ -318,8 +293,8 @@ public abstract class Filter<T, R extends T> {
             }
 
             @Override
-            public <D> D accept(SubjectVisitor<D> visitor, byte operation) {
-                return visitor.visit(this, operation);
+            public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) {
+                return visitor.visit(this, operation, previous);
             }
         }
 
@@ -331,8 +306,8 @@ public abstract class Filter<T, R extends T> {
             }
 
             @Override
-            public <D> D accept(SubjectVisitor<D> visitor, byte operation) {
-                return visitor.visit(this, operation);
+            public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) {
+                return visitor.visit(this, operation, previous);
             }
         }
 
@@ -344,8 +319,8 @@ public abstract class Filter<T, R extends T> {
             }
 
             @Override
-            public <D> D accept(SubjectVisitor<D> visitor, byte operation) {
-                return visitor.visit(this, operation);
+            public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) {
+                return visitor.visit(this, operation, previous);
             }
         }
 
@@ -361,8 +336,8 @@ public abstract class Filter<T, R extends T> {
             }
 
             @Override
-            public <D> D accept(SubjectVisitor<D> visitor, byte operation) {
-                return visitor.visit(this, operation);
+            public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) {
+                return visitor.visit(this, operation, previous);
             }
         }
 
@@ -376,8 +351,8 @@ public abstract class Filter<T, R extends T> {
             }
 
             @Override
-            public <D> D accept(SubjectVisitor<D> visitor, byte operation) {
-                return visitor.visit(this, operation);
+            public <D> D accept(SubjectVisitor<D> visitor, byte operation, D previous) {
+                return visitor.visit(this, operation, previous);
             }
         }
 
@@ -397,11 +372,6 @@ public abstract class Filter<T, R extends T> {
             this.subject = subject;
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return false;
-        }
-
         public Subject getSubject() {
             return subject;
         }
@@ -411,8 +381,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -430,22 +400,22 @@ public abstract class Filter<T, R extends T> {
 
         private static final MatrixFilter<RAbstractVector> IS_MATRIX = new MatrixFilter<RAbstractVector>() {
             @Override
-            public <D> D acceptOperation(OperationVisitor<D> visitor) {
-                return visitor.visitIsMatrix();
+            public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) {
+                return visitor.visitIsMatrix(previous);
             }
         };
 
         private static final MatrixFilter<RAbstractVector> IS_SQUARE_MATRIX = new MatrixFilter<RAbstractVector>() {
             @Override
-            public <D> D acceptOperation(OperationVisitor<D> visitor) {
-                return visitor.visitIsSquareMatrix();
+            public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) {
+                return visitor.visitIsSquareMatrix(previous);
             }
         };
 
         public interface OperationVisitor<D> {
-            D visitIsMatrix();
+            D visitIsMatrix(D previous);
 
-            D visitIsSquareMatrix();
+            D visitIsSquareMatrix(D previous);
         }
 
         @SuppressWarnings("unchecked")
@@ -461,16 +431,11 @@ public abstract class Filter<T, R extends T> {
         private MatrixFilter() {
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return false;
-        }
-
-        public abstract <D> D acceptOperation(OperationVisitor<D> visitor);
+        public abstract <D> D acceptOperation(OperationVisitor<D> visitor, D previous);
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -478,38 +443,33 @@ public abstract class Filter<T, R extends T> {
 
         public static final DoubleFilter IS_FINITE = new DoubleFilter() {
             @Override
-            public <D> D acceptOperation(OperationVisitor<D> visitor) {
-                return visitor.visitIsFinite();
+            public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) {
+                return visitor.visitIsFinite(previous);
             }
         };
 
         public static final DoubleFilter IS_FRACTIONAL = new DoubleFilter() {
             @Override
-            public <D> D acceptOperation(OperationVisitor<D> visitor) {
-                return visitor.visitIsFractional();
+            public <D> D acceptOperation(OperationVisitor<D> visitor, D previous) {
+                return visitor.visitIsFractional(previous);
             }
         };
 
         public interface OperationVisitor<D> {
-            D visitIsFinite();
+            D visitIsFinite(D previous);
 
-            D visitIsFractional();
+            D visitIsFractional(D previous);
         }
 
         private DoubleFilter() {
 
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return false;
-        }
-
-        public abstract <D> D acceptOperation(OperationVisitor<D> visitor);
+        public abstract <D> D acceptOperation(OperationVisitor<D> visitor, D previous);
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -522,11 +482,6 @@ public abstract class Filter<T, R extends T> {
             this.right = right;
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return left.isNarrowing() || right.isNarrowing();
-        }
-
         public Filter<?, ?> getLeft() {
             return left;
         }
@@ -536,8 +491,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -560,11 +515,6 @@ public abstract class Filter<T, R extends T> {
             this.right = right;
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return false;
-        }
-
         public Filter<?, ?> getLeft() {
             return left;
         }
@@ -574,8 +524,8 @@ public abstract class Filter<T, R extends T> {
         }
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
@@ -596,18 +546,13 @@ public abstract class Filter<T, R extends T> {
             this.filter = filter;
         }
 
-        @Override
-        public boolean isNarrowing() {
-            return false;
-        }
-
         public Filter<?, ?> getFilter() {
             return filter;
         }
 
         @Override
-        public <D> D accept(FilterVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(FilterVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java
index c47c8dd179..6c10646f38 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,16 +29,16 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
  */
 public abstract class Mapper<T, R> {
 
-    public abstract <D> D accept(MapperVisitor<D> visitor);
+    public abstract <D> D accept(MapperVisitor<D> visitor, D previous);
 
     public interface MapperVisitor<D> {
-        D visit(MapToValue<?, ?> mapper);
+        D visit(MapToValue<?, ?> mapper, D previous);
 
-        D visit(MapByteToBoolean mapper);
+        D visit(MapByteToBoolean mapper, D previous);
 
-        D visit(MapDoubleToInt mapper);
+        D visit(MapDoubleToInt mapper, D previous);
 
-        D visit(MapToCharAt mapper);
+        D visit(MapToCharAt mapper, D previous);
     }
 
     public static final class MapToValue<T, R> extends Mapper<T, R> {
@@ -53,8 +53,8 @@ public abstract class Mapper<T, R> {
         }
 
         @Override
-        public <D> D accept(MapperVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(MapperVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -67,8 +67,8 @@ public abstract class Mapper<T, R> {
         }
 
         @Override
-        public <D> D accept(MapperVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(MapperVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -80,8 +80,8 @@ public abstract class Mapper<T, R> {
         }
 
         @Override
-        public <D> D accept(MapperVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(MapperVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -103,8 +103,8 @@ public abstract class Mapper<T, R> {
         }
 
         @Override
-        public <D> D accept(MapperVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(MapperVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index e6bbe5e5a4..d692458bf9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -48,38 +48,38 @@ public abstract class PipelineStep<T, R> {
         return this;
     }
 
-    public abstract <D> D accept(PipelineStepVisitor<D> visitor);
+    public abstract <D> D accept(PipelineStepVisitor<D> visitor, D previous);
 
-    public <D> D acceptPipeline(PipelineStepVisitor<D> visitor) {
+    public <D> D acceptPipeline(PipelineStepVisitor<D> visitor, D initial) {
         PipelineStep<?, ?> curStep = this;
-        D result = null;
+        D result = initial;
         while (curStep != null) {
-            result = curStep.accept(visitor);
+            result = curStep.accept(visitor, result);
             curStep = curStep.getNext();
         }
         return result;
     }
 
     public interface PipelineStepVisitor<T> {
-        T visit(FindFirstStep<?, ?> step);
+        T visit(FindFirstStep<?, ?> step, T previous);
 
-        T visit(CoercionStep<?, ?> step);
+        T visit(CoercionStep<?, ?> step, T previous);
 
-        T visit(MapStep<?, ?> step);
+        T visit(MapStep<?, ?> step, T previous);
 
-        T visit(MapIfStep<?, ?> step);
+        T visit(MapIfStep<?, ?> step, T previous);
 
-        T visit(FilterStep<?, ?> step);
+        T visit(FilterStep<?, ?> step, T previous);
 
-        T visit(NotNAStep<?> step);
+        T visit(NotNAStep<?> step, T previous);
 
-        T visit(DefaultErrorStep<?> step);
+        T visit(DefaultErrorStep<?> step, T previous);
 
-        T visit(DefaultWarningStep<?> step);
+        T visit(DefaultWarningStep<?> step, T previous);
 
-        T visit(BoxPrimitiveStep<?> step);
+        T visit(BoxPrimitiveStep<?> step, T previous);
 
-        T visit(AttributableCoercionStep<?> step);
+        T visit(AttributableCoercionStep<?> step, T previous);
     }
 
     /**
@@ -105,8 +105,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -117,8 +117,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -127,8 +127,8 @@ public abstract class PipelineStep<T, R> {
      */
     public static final class BoxPrimitiveStep<T> extends PipelineStep<T, T> {
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -155,8 +155,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -192,8 +192,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -246,8 +246,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -266,8 +266,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -283,8 +283,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -321,8 +321,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 
@@ -353,8 +353,8 @@ public abstract class PipelineStep<T, R> {
         }
 
         @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor) {
-            return visitor.visit(this);
+        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
+            return visitor.visit(this, previous);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 09f6591a27..4256f4575c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -153,7 +153,7 @@ public final class PipelineToCastNode {
         CastNode prevCastNode = null;
         PipelineStep<?, ?> currCastStep = firstStep;
         while (currCastStep != null) {
-            CastNode node = currCastStep.accept(nodeFactory);
+            CastNode node = currCastStep.accept(nodeFactory, prevCastNode);
             if (node != null) {
                 if (prevCastNode == null) {
                     prevCastNode = node;
@@ -207,66 +207,66 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public CastNode visit(FindFirstStep<?, ?> step) {
+        public CastNode visit(FindFirstStep<?, ?> step, CastNode previous) {
             assert !canBeOptimized || targetType != null : "There must be a coercion step before find first";
             findFirstStep = step;
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(CoercionStep<?, ?> step) {
+        public CastNode visit(CoercionStep<?, ?> step, CastNode previous) {
             canBeOptimized(step.type);
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(MapStep<?, ?> step) {
+        public CastNode visit(MapStep<?, ?> step, CastNode previous) {
             cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(MapIfStep<?, ?> step) {
+        public CastNode visit(MapIfStep<?, ?> step, CastNode previous) {
             cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(FilterStep<?, ?> step) {
+        public CastNode visit(FilterStep<?, ?> step, CastNode previous) {
             targetType = checkFilter(step.getFilter());
             if (targetType == null) {
                 canBeOptimized = false;
             }
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(NotNAStep<?> step) {
+        public CastNode visit(NotNAStep<?> step, CastNode previous) {
             // TODO: we can remember that we saw not NA and do this check in the BypassNode
             canBeOptimized = false;
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(DefaultErrorStep<?> step) {
-            return inner.visit(step);
+        public CastNode visit(DefaultErrorStep<?> step, CastNode previous) {
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(DefaultWarningStep<?> step) {
-            return inner.visit(step);
+        public CastNode visit(DefaultWarningStep<?> step, CastNode previous) {
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(BoxPrimitiveStep<?> step) {
+        public CastNode visit(BoxPrimitiveStep<?> step, CastNode previous) {
             canBeOptimized = false;
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         @Override
-        public CastNode visit(AttributableCoercionStep<?> step) {
+        public CastNode visit(AttributableCoercionStep<?> step, CastNode previous) {
             cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step);
+            return inner.visit(step, previous);
         }
 
         private void cannotBeOptimizedBeforeFindFirst() {
@@ -352,24 +352,24 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public CastNode visit(DefaultErrorStep<?> step) {
+        public CastNode visit(DefaultErrorStep<?> step, CastNode previous) {
             defaultError = step.getDefaultMessage();
             return null;
         }
 
         @Override
-        public CastNode visit(DefaultWarningStep<?> step) {
+        public CastNode visit(DefaultWarningStep<?> step, CastNode previous) {
             defaultWarning = step.getDefaultMessage();
             return null;
         }
 
         @Override
-        public CastNode visit(BoxPrimitiveStep<?> step) {
+        public CastNode visit(BoxPrimitiveStep<?> step, CastNode previous) {
             return BoxPrimitiveNode.create();
         }
 
         @Override
-        public CastNode visit(FindFirstStep<?, ?> step) {
+        public CastNode visit(FindFirstStep<?, ?> step, CastNode previous) {
             boxPrimitives = false;
 
             // See FindFirstStep documentation on how it should be interpreted
@@ -391,7 +391,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public CastNode visit(FilterStep<?, ?> step) {
+        public CastNode visit(FilterStep<?, ?> step, CastNode previous) {
             ArgumentFilter<?, ?> filter = filterFactory.createFilter(step.getFilter());
             MessageData msg = getDefaultIfNull(step.getMessage(), step.isWarning());
             return FilterNode.create(filter, step.isWarning(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), boxPrimitives, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
@@ -399,7 +399,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public CastNode visit(NotNAStep<?> step) {
+        public CastNode visit(NotNAStep<?> step, CastNode previous) {
             if (step.getReplacement() == null) {
                 MessageData msg = getDefaultErrorIfNull(step.getMessage());
                 return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement());
@@ -414,7 +414,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public CastNode visit(CoercionStep<?, ?> step) {
+        public CastNode visit(CoercionStep<?, ?> step, CastNode previous) {
             boxPrimitives = true;
 
             RType type = step.getType();
@@ -443,17 +443,17 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public CastNode visit(AttributableCoercionStep<?> step) {
+        public CastNode visit(AttributableCoercionStep<?> step, CastNode previous) {
             return CastToAttributableNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
         }
 
         @Override
-        public CastNode visit(MapStep<?, ?> step) {
+        public CastNode visit(MapStep<?, ?> step, CastNode previous) {
             return MapNode.create(mapperFactory.createMapper(step.getMapper()));
         }
 
         @Override
-        public CastNode visit(MapIfStep<?, ?> step) {
+        public CastNode visit(MapIfStep<?, ?> step, CastNode previous) {
             ArgumentFilter<?, ?> condition = filterFactory.createFilter(step.getFilter());
             CastNode trueCastNode = PipelineToCastNode.convert(step.getTrueBranch(), this);
             CastNode falseCastNode = PipelineToCastNode.convert(step.getFalseBranch(), this);
@@ -490,16 +490,16 @@ public final class PipelineToCastNode {
 
         @Override
         public ArgumentFilter<?, ?> createFilter(Filter<?, ?> filter) {
-            return filter.accept(this);
+            return filter.accept(this, null);
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(TypeFilter<?, ?> filter) {
+        public ArgumentFilter<?, ?> visit(TypeFilter<?, ?> filter, ArgumentFilter<?, ?> previous) {
             return filter.getInstanceOfLambda();
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(RTypeFilter<?> filter) {
+        public ArgumentFilter<?, ?> visit(RTypeFilter<?> filter, ArgumentFilter<?, ?> previous) {
             if (filter.getType() == RType.Integer) {
                 return x -> x instanceof Integer || x instanceof RAbstractIntVector;
             } else if (filter.getType() == RType.Double) {
@@ -518,15 +518,15 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(CompareFilter<?> filter) {
-            return filter.getSubject().accept(this, filter.getOperation());
+        public ArgumentFilter<?, ?> visit(CompareFilter<?> filter, ArgumentFilter<?, ?> previous) {
+            return filter.getSubject().accept(this, filter.getOperation(), previous);
         }
 
         @SuppressWarnings({"rawtypes", "unchecked"})
         @Override
-        public ArgumentFilter<?, ?> visit(AndFilter<?, ?> filter) {
-            ArgumentFilter leftFilter = filter.getLeft().accept(this);
-            ArgumentFilter rightFilter = filter.getRight().accept(this);
+        public ArgumentFilter<?, ?> visit(AndFilter<?, ?> filter, ArgumentFilter<?, ?> previous) {
+            ArgumentFilter leftFilter = filter.getLeft().accept(this, previous);
+            ArgumentFilter rightFilter = filter.getRight().accept(this, previous);
             return (ArgumentTypeFilter<Object, Object>) arg -> {
                 if (!leftFilter.test(arg)) {
                     return false;
@@ -538,9 +538,9 @@ public final class PipelineToCastNode {
 
         @SuppressWarnings({"rawtypes", "unchecked"})
         @Override
-        public ArgumentFilter<?, ?> visit(OrFilter<?> filter) {
-            ArgumentFilter leftFilter = filter.getLeft().accept(this);
-            ArgumentFilter rightFilter = filter.getRight().accept(this);
+        public ArgumentFilter<?, ?> visit(OrFilter<?> filter, ArgumentFilter<?, ?> previous) {
+            ArgumentFilter leftFilter = filter.getLeft().accept(this, previous);
+            ArgumentFilter rightFilter = filter.getRight().accept(this, previous);
             return (ArgumentTypeFilter<Object, Object>) arg -> {
                 if (leftFilter.test(arg)) {
                     return true;
@@ -552,53 +552,53 @@ public final class PipelineToCastNode {
 
         @SuppressWarnings({"rawtypes", "unchecked"})
         @Override
-        public ArgumentFilter<?, ?> visit(NotFilter<?> filter) {
-            ArgumentFilter toNegate = filter.getFilter().accept(this);
+        public ArgumentFilter<?, ?> visit(NotFilter<?> filter, ArgumentFilter<?, ?> previous) {
+            ArgumentFilter toNegate = filter.getFilter().accept(this, previous);
             return (ArgumentFilter<Object, Object>) arg -> !toNegate.test(arg);
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(NullFilter filter) {
+        public ArgumentFilter<?, ?> visit(NullFilter filter, ArgumentFilter<?, ?> previous) {
             return (ArgumentFilter<Object, Object>) arg -> false;
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(MissingFilter filter) {
+        public ArgumentFilter<?, ?> visit(MissingFilter filter, ArgumentFilter<?, ?> previous) {
             return (ArgumentFilter<Object, Object>) arg -> false;
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(MatrixFilter<?> filter) {
-            return filter.acceptOperation(this);
+        public ArgumentFilter<?, ?> visit(MatrixFilter<?> filter, ArgumentFilter<?, ?> previous) {
+            return filter.acceptOperation(this, null);
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(DoubleFilter filter) {
-            return filter.acceptOperation(this);
+        public ArgumentFilter<?, ?> visit(DoubleFilter filter, ArgumentFilter<?, ?> previous) {
+            return filter.acceptOperation(this, null);
         }
 
         @Override
-        public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsMatrix() {
+        public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsMatrix(ArgumentFilter<RAbstractVector, RAbstractVector> previous) {
             return RAbstractVector::isMatrix;
         }
 
         @Override
-        public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsSquareMatrix() {
+        public ArgumentFilter<RAbstractVector, RAbstractVector> visitIsSquareMatrix(ArgumentFilter<RAbstractVector, RAbstractVector> previous) {
             return x -> x.isMatrix() && x.getDimensions()[0] == x.getDimensions()[1];
         }
 
         @Override
-        public ArgumentFilter<Double, Double> visitIsFinite() {
+        public ArgumentFilter<Double, Double> visitIsFinite(ArgumentFilter<Double, Double> previous) {
             return x -> !Double.isInfinite(x);
         }
 
         @Override
-        public ArgumentFilter<Double, Double> visitIsFractional() {
+        public ArgumentFilter<Double, Double> visitIsFractional(ArgumentFilter<Double, Double> previous) {
             return x -> !RRuntime.isNAorNaN(x) && !Double.isInfinite(x) && x != Math.floor(x);
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(ScalarValue scalarValue, byte operation) {
+        public ArgumentFilter<?, ?> visit(ScalarValue scalarValue, byte operation, ArgumentFilter<?, ?> previous) {
             switch (operation) {
                 case CompareFilter.EQ:
                     switch (scalarValue.type) {
@@ -668,7 +668,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ArgumentFilter<?, ?> visit(NATest naTest, byte operation) {
+        public ArgumentFilter<?, ?> visit(NATest naTest, byte operation, ArgumentFilter<?, ?> previous) {
             switch (operation) {
                 case CompareFilter.EQ:
                     switch (naTest.type) {
@@ -691,7 +691,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ArgumentFilter<String, String> visit(StringLength stringLength, byte operation) {
+        public ArgumentFilter<String, String> visit(StringLength stringLength, byte operation, ArgumentFilter<?, ?> previous) {
             switch (operation) {
                 case CompareFilter.EQ:
                     return arg -> arg.length() == stringLength.length;
@@ -714,7 +714,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ArgumentFilter<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation) {
+        public ArgumentFilter<RAbstractVector, RAbstractVector> visit(VectorSize vectorSize, byte operation, ArgumentFilter<?, ?> previous) {
             switch (operation) {
                 case CompareFilter.EQ:
                     return arg -> arg.getLength() == vectorSize.size;
@@ -737,7 +737,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ArgumentFilter<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation) {
+        public ArgumentFilter<RAbstractVector, RAbstractVector> visit(ElementAt elementAt, byte operation, ArgumentFilter<?, ?> previous) {
             switch (operation) {
                 case CompareFilter.EQ:
                     switch (elementAt.type) {
@@ -759,7 +759,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ArgumentFilter<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation) {
+        public ArgumentFilter<RAbstractVector, RAbstractVector> visit(Dim dim, byte operation, ArgumentFilter<?, ?> previous) {
             switch (operation) {
                 case CompareFilter.EQ:
                     return v -> v.isMatrix() && v.getDimensions().length > dim.dimIndex && v.getDimensions()[dim.dimIndex] == dim.dimSize;
@@ -785,22 +785,22 @@ public final class PipelineToCastNode {
 
         @Override
         public ArgumentMapper<Object, Object> createMapper(Mapper<?, ?> mapper) {
-            return mapper.accept(this);
+            return mapper.accept(this, null);
         }
 
         @Override
-        public ValuePredicateArgumentMapper<Object, Object> visit(MapToValue<?, ?> mapper) {
+        public ValuePredicateArgumentMapper<Object, Object> visit(MapToValue<?, ?> mapper, ValuePredicateArgumentMapper<Object, Object> previous) {
             final Object value = mapper.getValue();
             return ValuePredicateArgumentMapper.fromLambda(x -> value);
         }
 
         @Override
-        public ValuePredicateArgumentMapper<Object, Object> visit(MapByteToBoolean mapper) {
+        public ValuePredicateArgumentMapper<Object, Object> visit(MapByteToBoolean mapper, ValuePredicateArgumentMapper<Object, Object> previous) {
             return ValuePredicateArgumentMapper.fromLambda(x -> RRuntime.fromLogical((Byte) x));
         }
 
         @Override
-        public ValuePredicateArgumentMapper<Object, Object> visit(MapDoubleToInt mapper) {
+        public ValuePredicateArgumentMapper<Object, Object> visit(MapDoubleToInt mapper, ValuePredicateArgumentMapper<Object, Object> previous) {
             final NACheck naCheck = NACheck.create();
             return ValuePredicateArgumentMapper.fromLambda(x -> {
                 double d = (Double) x;
@@ -810,7 +810,7 @@ public final class PipelineToCastNode {
         }
 
         @Override
-        public ValuePredicateArgumentMapper<Object, Object> visit(MapToCharAt mapper) {
+        public ValuePredicateArgumentMapper<Object, Object> visit(MapToCharAt mapper, ValuePredicateArgumentMapper<Object, Object> previous) {
             final int defaultValue = mapper.getDefaultValue();
             final int index = mapper.getIndex();
             return ValuePredicateArgumentMapper.fromLambda(x -> {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
index ce9b228102..bc78432499 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
@@ -70,7 +70,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
     private ForwardingAnalysisResult altResult = null;
 
     public ForwardingAnalysisResult analyse(PipelineStep<?, ?> firstStep) {
-        firstStep.acceptPipeline(this);
+        firstStep.acceptPipeline(this, null);
         ForwardingAnalysisResult mainRes = result;
         if (altResult != null) {
             mainRes = mainRes.or(altResult);
@@ -87,7 +87,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
     }
 
     @Override
-    public ForwardingAnalysisResult visit(FindFirstStep<?, ?> step) {
+    public ForwardingAnalysisResult visit(FindFirstStep<?, ?> step, ForwardingAnalysisResult previous) {
         ForwardingAnalysisResult localRes = new ForwardingAnalysisResult().blockAll().setForwardedType(step.getElementClass(), FORWARDED);
         if (step.getDefaultValue() == RNull.instance) {
             // see CoercedPhaseBuilder.findFirstOrNull()
@@ -98,7 +98,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
     }
 
     @Override
-    public ForwardingAnalysisResult visit(CoercionStep<?, ?> step) {
+    public ForwardingAnalysisResult visit(CoercionStep<?, ?> step, ForwardingAnalysisResult previous) {
         ForwardingAnalysisResult localRes = new ForwardingAnalysisResult().blockAll().setForwardedType(step.getType(), FORWARDED);
         if (step.preserveNonVector) {
             // i.e. preserve NULL and MISSING
@@ -109,35 +109,35 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
     }
 
     @Override
-    public ForwardingAnalysisResult visit(MapStep<?, ?> step) {
+    public ForwardingAnalysisResult visit(MapStep<?, ?> step, ForwardingAnalysisResult previous) {
         ForwardingAnalysisResult localRes = step.getMapper().accept(new Mapper.MapperVisitor<ForwardingAnalysisResult>() {
 
             @Override
-            public ForwardingAnalysisResult visit(MapToValue<?, ?> mapper) {
+            public ForwardingAnalysisResult visit(MapToValue<?, ?> mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return ForwardingAnalysisResult.INVALID;
             }
 
             @Override
-            public ForwardingAnalysisResult visit(MapByteToBoolean mapper) {
+            public ForwardingAnalysisResult visit(MapByteToBoolean mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return new ForwardingAnalysisResult().blockAll().setForwardedType(RType.Logical, new Forwarded(mapper));
             }
 
             @Override
-            public ForwardingAnalysisResult visit(MapDoubleToInt mapper) {
+            public ForwardingAnalysisResult visit(MapDoubleToInt mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return ForwardingAnalysisResult.INVALID;
             }
 
             @Override
-            public ForwardingAnalysisResult visit(MapToCharAt mapper) {
+            public ForwardingAnalysisResult visit(MapToCharAt mapper, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return ForwardingAnalysisResult.INVALID;
             }
-        });
+        }, previous);
         result = result.and(localRes);
         return result;
     }
 
     @Override
-    public ForwardingAnalysisResult visit(MapIfStep<?, ?> mapIfStep) {
+    public ForwardingAnalysisResult visit(MapIfStep<?, ?> mapIfStep, ForwardingAnalysisResult previous) {
         // analyze the true branch
         ForwardingAnalysisResult trueBranchFwdRes;
         PipelineStep<?, ?> trueBranchFirstStep = new FilterStep<>(mapIfStep.getFilter(), null, false);
@@ -167,11 +167,11 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
     }
 
     @Override
-    public ForwardingAnalysisResult visit(FilterStep<?, ?> step) {
+    public ForwardingAnalysisResult visit(FilterStep<?, ?> step, ForwardingAnalysisResult previous) {
         class ForwardedValuesFilterVisitor implements Filter.FilterVisitor<ForwardingAnalysisResult> {
 
             @Override
-            public ForwardingAnalysisResult visit(TypeFilter<?, ?> filter) {
+            public ForwardingAnalysisResult visit(TypeFilter<?, ?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 ForwardingAnalysisResult res = new ForwardingAnalysisResult().blockAll();
                 if (filter.getExtraCondition() == null) {
                     res = res.setForwardedType(filter.getType1(), FORWARDED);
@@ -182,31 +182,31 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
             }
 
             @Override
-            public ForwardingAnalysisResult visit(RTypeFilter<?> filter) {
+            public ForwardingAnalysisResult visit(RTypeFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return new ForwardingAnalysisResult().blockAll().setForwardedType(filter.getType(), FORWARDED);
             }
 
             @Override
-            public ForwardingAnalysisResult visit(CompareFilter<?> filter) {
+            public ForwardingAnalysisResult visit(CompareFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return filter.getSubject().accept(new Filter.CompareFilter.SubjectVisitor<ForwardingAnalysisResult>() {
 
                     @Override
-                    public ForwardingAnalysisResult visit(ScalarValue scalarValue, byte operation) {
+                    public ForwardingAnalysisResult visit(ScalarValue scalarValue, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                         return new ForwardingAnalysisResult().blockAll().setForwardedType(scalarValue.type, UNKNOWN);
                     }
 
                     @Override
-                    public ForwardingAnalysisResult visit(NATest naTest, byte operation) {
+                    public ForwardingAnalysisResult visit(NATest naTest, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                         return new ForwardingAnalysisResult().blockAll().setForwardedType(naTest.type, UNKNOWN);
                     }
 
                     @Override
-                    public ForwardingAnalysisResult visit(StringLength stringLength, byte operation) {
+                    public ForwardingAnalysisResult visit(StringLength stringLength, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                         return new ForwardingAnalysisResult().blockAll().setForwardedType(RType.Character, UNKNOWN);
                     }
 
                     @Override
-                    public ForwardingAnalysisResult visit(VectorSize vectorSize, byte operation) {
+                    public ForwardingAnalysisResult visit(VectorSize vectorSize, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                         if (vectorSize.size == 0 && operation == CompareFilter.EQ) {
                             return new ForwardingAnalysisResult().blockAll().setNull(FORWARDED);
                         } else if (vectorSize.size == 1 && (operation == CompareFilter.EQ || operation == CompareFilter.GT || operation == CompareFilter.GE)) {
@@ -221,7 +221,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
                     }
 
                     @Override
-                    public ForwardingAnalysisResult visit(ElementAt elementAt, byte operation) {
+                    public ForwardingAnalysisResult visit(ElementAt elementAt, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                         if (elementAt.index == 0) {
                             return new ForwardingAnalysisResult().blockAll().setForwardedType(elementAt.type, UNKNOWN);
                         } else {
@@ -230,86 +230,86 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
                     }
 
                     @Override
-                    public ForwardingAnalysisResult visit(Dim dim, byte operation) {
+                    public ForwardingAnalysisResult visit(Dim dim, byte operation, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                         return new ForwardingAnalysisResult().blockAll();
                     }
-                }, filter.getOperation());
+                }, filter.getOperation(), previous);
             }
 
             @Override
-            public ForwardingAnalysisResult visit(AndFilter<?, ?> filter) {
+            public ForwardingAnalysisResult visit(AndFilter<?, ?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 ForwardedValuesFilterVisitor leftVis = new ForwardedValuesFilterVisitor();
                 ForwardedValuesFilterVisitor rightVis = new ForwardedValuesFilterVisitor();
-                ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis);
-                ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis);
+                ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis, previous);
+                ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis, previous);
                 return leftResult.and(rightResult);
             }
 
             @Override
-            public ForwardingAnalysisResult visit(OrFilter<?> filter) {
+            public ForwardingAnalysisResult visit(OrFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 ForwardedValuesFilterVisitor leftVis = new ForwardedValuesFilterVisitor();
                 ForwardedValuesFilterVisitor rightVis = new ForwardedValuesFilterVisitor();
-                ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis);
-                ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis);
+                ForwardingAnalysisResult leftResult = filter.getLeft().accept(leftVis, previous);
+                ForwardingAnalysisResult rightResult = filter.getRight().accept(rightVis, previous);
                 return leftResult.or(rightResult);
             }
 
             @Override
-            public ForwardingAnalysisResult visit(NotFilter<?> filter) {
+            public ForwardingAnalysisResult visit(NotFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 ForwardedValuesFilterVisitor vis = new ForwardedValuesFilterVisitor();
-                return filter.getFilter().accept(vis).not();
+                return filter.getFilter().accept(vis, previous).not();
             }
 
             @Override
-            public ForwardingAnalysisResult visit(MatrixFilter<?> filter) {
+            public ForwardingAnalysisResult visit(MatrixFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return new ForwardingAnalysisResult().forwardAll();
             }
 
             @Override
-            public ForwardingAnalysisResult visit(DoubleFilter filter) {
+            public ForwardingAnalysisResult visit(DoubleFilter filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return new ForwardingAnalysisResult().blockAll().setForwardedType(RType.Double, UNKNOWN);
             }
 
             @Override
-            public ForwardingAnalysisResult visit(NullFilter filter) {
+            public ForwardingAnalysisResult visit(NullFilter filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return new ForwardingAnalysisResult().blockAll().setNull(FORWARDED);
             }
 
             @Override
-            public ForwardingAnalysisResult visit(MissingFilter filter) {
+            public ForwardingAnalysisResult visit(MissingFilter filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
                 return new ForwardingAnalysisResult().blockAll().setMissing(FORWARDED);
             }
         }
-        ForwardingAnalysisResult localRes = step.getFilter().accept(new ForwardedValuesFilterVisitor());
+        ForwardingAnalysisResult localRes = step.getFilter().accept(new ForwardedValuesFilterVisitor(), previous);
         result = result.and(localRes);
         return result;
     }
 
     @Override
-    public ForwardingAnalysisResult visit(NotNAStep<?> step) {
+    public ForwardingAnalysisResult visit(NotNAStep<?> step, ForwardingAnalysisResult previous) {
         result = result.and(new ForwardingAnalysisResult().unknownAll().setNull(FORWARDED).setMissing(FORWARDED));
         return result;
     }
 
     @Override
-    public ForwardingAnalysisResult visit(DefaultErrorStep<?> step) {
+    public ForwardingAnalysisResult visit(DefaultErrorStep<?> step, ForwardingAnalysisResult previous) {
         return result;
     }
 
     @Override
-    public ForwardingAnalysisResult visit(DefaultWarningStep<?> step) {
+    public ForwardingAnalysisResult visit(DefaultWarningStep<?> step, ForwardingAnalysisResult previous) {
         return result;
     }
 
     @Override
-    public ForwardingAnalysisResult visit(BoxPrimitiveStep<?> step) {
+    public ForwardingAnalysisResult visit(BoxPrimitiveStep<?> step, ForwardingAnalysisResult previous) {
         // TODO
         result = ForwardingAnalysisResult.INVALID;
         return result;
     }
 
     @Override
-    public ForwardingAnalysisResult visit(AttributableCoercionStep<?> step) {
+    public ForwardingAnalysisResult visit(AttributableCoercionStep<?> step, ForwardingAnalysisResult previous) {
         // TODO
         result = ForwardingAnalysisResult.INVALID;
         return result;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
index 58fe88bbdc..57d3ea046e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
@@ -104,22 +104,22 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) {
+    public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, false);
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) {
+    public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, true);
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) {
+    public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper, Mapper<? super T, ?> falseBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, false);
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) {
+    public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper, Mapper<? super T, ?> falseBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, true);
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index c5f4ba8394..c1780b2829 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -146,7 +146,7 @@ public final class PipelineBuilder {
         return pcb;
     }
 
-    private PipelineStep<?, ?> getFirstStep() {
+    public PipelineStep<?, ?> getFirstStep() {
         return chainBuilder != null ? chainBuilder.getFirstStep() : null;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
index 3d8fb9edf3..fcd810bb29 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
@@ -95,6 +96,11 @@ public abstract class CastComplexNode extends CastBaseNode {
         return RNull.instance;
     }
 
+    @Specialization
+    protected RMissing doMissing(@SuppressWarnings("unused") RMissing operand) {
+        return RMissing.instance;
+    }
+
     @Specialization
     protected RComplex doInt(int operand) {
         naCheck.enable(operand);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
index e1cf552841..628447faf3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,10 @@ public abstract class CastNode extends UnaryNode {
         return lastWarning;
     }
 
+    public static void clearLastWarning() {
+        lastWarning = null;
+    }
+
     @TruffleBoundary
     protected static void handleArgumentError(Object arg, RBaseNode callObj, RError.Message message, Object[] messageArgs) {
         if (isTesting) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
index 9471d88d7a..a9d7b0ad36 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
@@ -86,6 +87,11 @@ public abstract class CastRawNode extends CastBaseNode {
         return RNull.instance;
     }
 
+    @Specialization
+    protected RMissing doMissing(@SuppressWarnings("unused") RMissing operand) {
+        return RMissing.instance;
+    }
+
     private RRaw checkOutOfRange(int operand, int intResult) {
         if (intResult != operand) {
             warningBranch.enter();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java
index 790a649b00..9dd87e625f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToAttributableNode.java
@@ -51,14 +51,12 @@ public abstract class CastToAttributableNode extends CastBaseNode {
     }
 
     @Specialization
-    @SuppressWarnings("unused")
-    protected RNull cast(RNull rnull) {
+    protected RNull cast(@SuppressWarnings("unused") RNull rnull) {
         return RNull.instance;
     }
 
     @Specialization
-    @SuppressWarnings("unused")
-    protected RMissing cast(RMissing rmissing) {
+    protected RMissing cast(@SuppressWarnings("unused") RMissing rmissing) {
         return RMissing.instance;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index d12a2ac515..77c0e2875e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -32,7 +32,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
-import java.util.Objects;
 import java.util.zip.GZIPInputStream;
 
 import org.tukaani.xz.XZInputStream;
@@ -43,7 +42,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.TempPathName;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index d4fed1887a..dd24eb9fc1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -28,7 +28,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-public class RExpression extends RListBase implements RAbstractVector {
+public final class RExpression extends RListBase implements RAbstractVector {
 
     private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Expression.getClazz());
 
-- 
GitLab


From 488640dd768838e9067dd865ef959a53c07cfc76 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Wed, 22 Feb 2017 12:08:09 +0100
Subject: [PATCH 041/402] Builtin diagnostics locates the fallback method via
 the generated node class

---
 .../builtin/ResultTypesAnalyserTest.java      |  6 ++
 .../r/nodes/casts/ResultTypesAnalyser.java    | 15 ++---
 .../r/nodes/test/RBuiltinDiagnostics.java     | 62 ++++++++++++++++---
 3 files changed, 67 insertions(+), 16 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
index 8e06ec8734..d22ab4cd4c 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
@@ -433,6 +433,12 @@ public class ResultTypesAnalyserTest {
         assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1"))));
     }
 
+    @Test
+    public void testAllowMissing() {
+        arg.allowMissing().mustBe(stringValue());
+        assertTypes(RMissing.class, String.class, RAbstractStringVector.class);
+    }
+
     @Test
     public void testTwoWildcardTypes() {
         arg.mustBe((instanceOf(String.class).and(mark(length(10), "l10").or(mark(length(20), "l20")))));
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
index 8dcc52367a..ba943022bf 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
@@ -131,6 +131,8 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
 
     }
 
+    private static final TypeExpr NOT_NULL_NOT_MISSING = atom(RNull.class).not().and(atom(RMissing.class).not());
+
     public static TypeExpr analyse(PipelineStep<?, ?> firstStep) {
         return analyse(firstStep, AltTypeExpr.create()).merge();
     }
@@ -222,8 +224,7 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
         if (visitTrueBranch) {
             if (step.isReturns()) {
                 AltTypeExpr returnedType = trueBranchResultTypes(step, inputType, filterRes);
-                inputType.addAlt(returnedType.merge());
-                return inputType;
+                return inputType.addAlt(returnedType.merge());
             } else {
                 return trueBranchResultTypes(step, inputType, filterRes);
             }
@@ -326,7 +327,7 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
         if (filter.getType2() != null) {
             resTp = resTp.or(atom(filter.getType2()));
         }
-        return resTp.and(atom(RNull.class).not().and(atom(RMissing.class).not()));
+        return resTp.and(NOT_NULL_NOT_MISSING);
     }
 
     @Override
@@ -377,7 +378,7 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
 
     @Override
     public TypeExpr visit(MatrixFilter<?> filter, TypeExpr previous) {
-        return previous.lower(filter);
+        return previous.lower(filter).and(NOT_NULL_NOT_MISSING);
     }
 
     @Override
@@ -437,17 +438,17 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
 
     @Override
     public TypeExpr visit(VectorSize vectorSize, byte operation, TypeExpr previous) {
-        return previous;
+        return previous.and(NOT_NULL_NOT_MISSING);
     }
 
     @Override
     public TypeExpr visit(ElementAt elementAt, byte operation, TypeExpr previous) {
-        return previous;
+        return previous.and(NOT_NULL_NOT_MISSING);
     }
 
     @Override
     public TypeExpr visit(Dim dim, byte operation, TypeExpr previous) {
-        return previous;
+        return previous.and(NOT_NULL_NOT_MISSING);
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index 3ec99e591e..c4f1c1b102 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -35,8 +35,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts;
@@ -57,6 +59,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public class RBuiltinDiagnostics {
 
@@ -278,24 +281,29 @@ public class RBuiltinDiagnostics {
         return sb.toString();
     }
 
+    private static String toGenNodeName(String name) {
+        if (name.endsWith("Node")) {
+            return name + "Gen";
+        } else {
+            return name + "NodeGen";
+        }
+    }
+
     private static Class<?> toNodeGenClass(Class<?> nodeCls) throws ClassNotFoundException {
         String nodeGenClsName;
         if (nodeCls.getEnclosingClass() == null) {
-            nodeGenClsName = nodeCls.getName() + "NodeGen";
+            nodeGenClsName = toGenNodeName(nodeCls.getName());
         } else {
+            String enclClsName = nodeCls.getEnclosingClass().getName();
+            String enclosingClsSuffix = RBaseNode.class.isAssignableFrom(nodeCls.getEnclosingClass()) ? (enclClsName.endsWith("Node") ? "Gen" : "NodeGen") : "Factory";
             String[] split = nodeCls.getName().split("\\.");
             StringBuilder sb = new StringBuilder();
             for (int i = 0; i < split.length; i++) {
                 String s = split[i];
                 if (i == split.length - 1) {
                     String[] lastSplit = s.split("\\$");
-                    sb.append(lastSplit[0] + "Factory$");
-                    sb.append(lastSplit[1]);
-                    if (s.endsWith("Node")) {
-                        sb.append("Gen");
-                    } else {
-                        sb.append("NodeGen");
-                    }
+                    sb.append(lastSplit[0] + enclosingClsSuffix + "$");
+                    sb.append(toGenNodeName(lastSplit[1]));
                 } else {
                     sb.append(s);
                 }
@@ -360,7 +368,15 @@ public class RBuiltinDiagnostics {
 
             argResultSets = createArgResultSets();
 
-            this.specMethods = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class);
+            List<Method> specs = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class);
+            this.specMethods = new ArrayList<>(specs);
+            // N.B. The fallback method cannot be found by the Fallback annotation since
+            // this annotation has the CLASS retention policy. Nonetheless, the fallback method can
+            // be determined throught the fallback node in the generated class.
+            Optional<Method> fallback = findFallbackMethod(toNodeGenClass(bltnCls));
+            if (fallback.isPresent()) {
+                this.specMethods.add(fallback.get());
+            }
 
             this.convResultTypePerSpec = createConvResultTypePerSpecialization();
             this.nonCoveredArgsSet = combineArguments();
@@ -581,6 +597,34 @@ public class RBuiltinDiagnostics {
         return typeName(m.getReturnType()) + " " + m.getName() + "(" + sb + ")";
     }
 
+    private static Optional<Method> findFallbackMethod(Class<?> genBltnClass) {
+        Optional<Class<?>> fallbackNodeCls = Arrays.stream(genBltnClass.getDeclaredClasses()).filter(c -> "FallbackNode_".equals(c.getSimpleName())).findFirst();
+        return fallbackNodeCls.flatMap(fc -> findFallbackMethodFromAnnot(fc, genBltnClass.getSuperclass()));
+    }
+
+    private static Optional<Method> findFallbackMethodFromAnnot(Class<?> fallbackNodeClass, Class<?> bltnCls) {
+        GeneratedBy genByAnnot = fallbackNodeClass.getAnnotation(GeneratedBy.class);
+        assert genByAnnot != null;
+        String fallbackName = genByAnnot.methodName();
+
+        return findMethod(bltnCls, dm -> {
+            return dm.getAnnotation(Specialization.class) == null && fallbackName.startsWith(dm.getName() + "(");
+        });
+    }
+
+    private static Optional<Method> findMethod(Class<?> clazz, Predicate<Method> filter) {
+        Optional<Method> res = Arrays.asList(clazz.getDeclaredMethods()).stream().filter(filter).findFirst();
+        if (res.isPresent()) {
+            return res;
+        }
+
+        if (clazz.getSuperclass() != Object.class) {
+            return findMethod(clazz.getSuperclass(), filter);
+        } else {
+            return Optional.empty();
+        }
+    }
+
     public interface RBuiltinDiagFactory {
         String getBuiltinName();
 
-- 
GitLab


From 4f17ec5089ef76fc9cc332dcd0de08440c9d2730 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Wed, 22 Feb 2017 16:32:13 +0100
Subject: [PATCH 042/402] Implemented missing N01type/NormKind random number
 normalization algorithms.

---
 .../truffle/r/runtime/nmath/distr/SNorm.java  | 338 +++++++++++++++++-
 .../truffle/r/test/ExpectedTestOutput.test    |  42 +++
 .../stats/TestRandGenerationFunctions.java    |   8 +-
 3 files changed, 376 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java
index d818315b6d..07ff51a339 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java
@@ -11,31 +11,347 @@
  */
 package com.oracle.truffle.r.runtime.nmath.distr;
 
-import com.oracle.truffle.r.runtime.RError;
+import static java.lang.Math.cos;
+import static java.lang.Math.exp;
+import static java.lang.Math.log;
+import static java.lang.Math.sin;
+import static java.lang.Math.sqrt;
+import static com.oracle.truffle.r.runtime.nmath.MathConstants.DBL_MIN;
+import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI;
+import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs;
+import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2;
+import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
+
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.rng.RRNG.NormKind;
 import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator;
 
 /**
  * Generation of random value from standard normal distribution N(0,1). Corresponds to
  * {@code snorm.c} in GnuR. Some other distributions can be generated by transformations of N(0,1).
- * This is meant as common functinality for those.
+ * This is meant as common functionality for those.
  */
 public final class SNorm {
+
+    /*
+     * REFERENCE
+     *
+     * Ahrens, J.H. and Dieter, U. Extensions of Forsythe's method for random sampling from the
+     * normal distribution. Math. Comput. 27, 927-937.
+     *
+     * The definitions of the constants a[k], d[k], t[k] and h[k] are according to the
+     * abovementioned article
+     */
+
+    private static final double[] a = new double[]{
+                    0.0000000, 0.03917609, 0.07841241, 0.1177699,
+                    0.1573107, 0.19709910, 0.23720210, 0.2776904,
+                    0.3186394, 0.36012990, 0.40225010, 0.4450965,
+                    0.4887764, 0.53340970, 0.57913220, 0.6260990,
+                    0.6744898, 0.72451440, 0.77642180, 0.8305109,
+                    0.8871466, 0.94678180, 1.00999000, 1.0775160,
+                    1.1503490, 1.22985900, 1.31801100, 1.4177970,
+                    1.5341210, 1.67594000, 1.86273200, 2.1538750
+    };
+
+    private static final double[] d = new double[]{
+                    0.0000000, 0.0000000, 0.0000000, 0.0000000,
+                    0.0000000, 0.2636843, 0.2425085, 0.2255674,
+                    0.2116342, 0.1999243, 0.1899108, 0.1812252,
+                    0.1736014, 0.1668419, 0.1607967, 0.1553497,
+                    0.1504094, 0.1459026, 0.1417700, 0.1379632,
+                    0.1344418, 0.1311722, 0.1281260, 0.1252791,
+                    0.1226109, 0.1201036, 0.1177417, 0.1155119,
+                    0.1134023, 0.1114027, 0.1095039
+    };
+
+    private static final double[] t = new double[]{
+                    7.673828e-4, 0.002306870, 0.003860618, 0.005438454,
+                    0.007050699, 0.008708396, 0.010423570, 0.012209530,
+                    0.014081250, 0.016055790, 0.018152900, 0.020395730,
+                    0.022811770, 0.025434070, 0.028302960, 0.031468220,
+                    0.034992330, 0.038954830, 0.043458780, 0.048640350,
+                    0.054683340, 0.061842220, 0.070479830, 0.081131950,
+                    0.094624440, 0.112300100, 0.136498000, 0.171688600,
+                    0.227624100, 0.330498000, 0.584703100
+    };
+
+    private static final double[] h = new double[]{
+                    0.03920617, 0.03932705, 0.03950999, 0.03975703,
+                    0.04007093, 0.04045533, 0.04091481, 0.04145507,
+                    0.04208311, 0.04280748, 0.04363863, 0.04458932,
+                    0.04567523, 0.04691571, 0.04833487, 0.04996298,
+                    0.05183859, 0.05401138, 0.05654656, 0.05953130,
+                    0.06308489, 0.06737503, 0.07264544, 0.07926471,
+                    0.08781922, 0.09930398, 0.11555990, 0.14043440,
+                    0.18361420, 0.27900160, 0.70104740
+    };
+
+    /*----------- Constants and definitions for  Kinderman - Ramage --- */
+    /*
+     * REFERENCE
+     *
+     * Kinderman A. J. and Ramage J. G. (1976). Computer generation of normal random variables. JASA
+     * 71, 893-896.
+     */
+
+    private static final double C1 = 0.398942280401433;
+    private static final double C2 = 0.180025191068563;
+    private static final double A = 2.216035867166471;
+
+    private static double g(double x) {
+        return C1 * exp(-x * x / 2.0) - C2 * (A - x);
+    }
+
+    private static final double BIG = 134217728; /* 2^27 */
+
+    static double BMNormKeep = 0.0;
+
     private SNorm() {
         // only static members
     }
 
-    // TODO: implement other normKinds
+    public static double normRand(RandomNumberGenerator rand, NormKind normKind) {
+        double s;
+        double u1;
+        double w;
+        double y;
+        double u2;
+        double u3;
+        double aa;
+        double tt;
+        double theta;
+        double r;
+        int i;
+
+        switch (normKind) {
+            case BUGGY_KINDERMAN_RAMAGE: /* see Reference above */
+                /*
+                 * note: this has problems, but is retained for reproducibility of older codes.
+                 */
+                /* unif_rand() alone is not of high enough precision */
+                u1 = rand.genrandDouble();
+                if (u1 < 0.884070402298758) {
+                    u2 = rand.genrandDouble();
+                    return A * (1.13113163544180 * u1 + u2 - 1);
+                }
 
-    private static final double BIG = 134217728; /* 2^27 */
+                if (u1 >= 0.973310954173898) { /* tail: */
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = (A * A - 2 * log(u3));
+                        if (u2 * u2 < (A * A) / tt) {
+                            return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt);
+                        }
+                    }
+                }
 
-    public static double normRand(RandomNumberGenerator rand, NormKind normKind) {
-        if (normKind != NormKind.INVERSION) {
-            throw RError.nyi(null, "unifNorm(): no other NormKind than the default INVERSION is implemented");
+                if (u1 >= 0.958720824790463) { /* region3: */
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = A - 0.630834801921960 * fmin2(u2, u3);
+                        if (fmax2(u2, u3) <= 0.755591531667601) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                        if (0.034240503750111 * fabs(u2 - u3) <= g(tt)) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                    }
+                }
+
+                if (u1 >= 0.911312780288703) { /* region2: */
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = 0.479727404222441 + 1.105473661022070 * fmin2(u2, u3);
+                        if (fmax2(u2, u3) <= 0.872834976671790) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                        if (0.049264496373128 * fabs(u2 - u3) <= g(tt)) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                    }
+                }
+
+                /* ELSE region1: */
+                if (true) { // Satisfy foolish style checker requiring "break"
+                            // or "return" after infinite loops
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = 0.479727404222441 - 0.595507138015940 * fmin2(u2, u3);
+                        if (fmax2(u2, u3) <= 0.805577924423817) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                    }
+                }
+                return 0d; // can NEVER reach here (infinite loop ahead)
+
+            case AHRENS_DIETER:
+                /* unif_rand() alone is not of high enough precision */
+                u1 = rand.genrandDouble();
+                s = 0.0;
+                if (u1 > 0.5) {
+                    s = 1.0;
+                }
+                u1 = u1 + u1 - s;
+                u1 *= 32.0;
+                i = (int) u1;
+                if (i == 32) {
+                    i = 31;
+                }
+                if (i != 0) {
+                    u2 = u1 - i;
+                    aa = a[i - 1];
+                    while (u2 <= t[i - 1]) {
+                        u1 = rand.genrandDouble();
+                        w = u1 * (a[i] - aa);
+                        tt = (w * 0.5 + aa) * w;
+                        while (true) {
+                            if (u2 > tt) {
+                                // Original code: goto deliver;
+                                // inlined the code after the label:
+                                y = aa + w;
+                                return (s == 1.0) ? -y : y;
+                            }
+                            u1 = rand.genrandDouble();
+                            if (u2 < u1) {
+                                break;
+                            }
+                            tt = u1;
+                            u2 = rand.genrandDouble();
+                        }
+                        u2 = rand.genrandDouble();
+                    }
+                    w = (u2 - t[i - 1]) * h[i - 1];
+                } else {
+                    i = 6;
+                    aa = a[31];
+                    while (true) {
+                        u1 = u1 + u1;
+                        if (u1 >= 1.0) {
+                            break;
+                        }
+                        aa = aa + d[i - 1];
+                        i = i + 1;
+                    }
+                    u1 = u1 - 1.0;
+                    jump: while (true) {
+                        w = u1 * d[i - 1];
+                        tt = (w * 0.5 + aa) * w;
+                        while (true) {
+                            u2 = rand.genrandDouble();
+                            if (u2 > tt) {
+                                break jump;
+                            }
+                            u1 = rand.genrandDouble();
+                            if (u2 < u1) {
+                                break;
+                            }
+                            tt = u1;
+                        }
+                        u1 = rand.genrandDouble();
+                    }
+                }
+                // deliver:
+                y = aa + w;
+                return (s == 1.0) ? -y : y;
+
+            case BOX_MULLER:
+                if (BMNormKeep != 0.0) { /* An exact test is intentional */
+                    s = BMNormKeep;
+                    BMNormKeep = 0.0;
+                    return s;
+                } else {
+                    theta = 2d * M_PI * rand.genrandDouble();
+                    r = sqrt(-2d * log(rand.genrandDouble())) + 10d * DBL_MIN; /* ensure non-zero */
+                    BMNormKeep = r * sin(theta);
+                    return r * cos(theta);
+                }
+
+            case USER_NORM:
+                // Not implemented yet. C impl: return *((double *) User_norm_fun());
+                throw RInternalError.shouldNotReachHere();
+
+            case INVERSION:
+                /* unif_rand() alone is not of high enough precision */
+                u1 = rand.genrandDouble();
+                u1 = (int) (BIG * u1) + rand.genrandDouble();
+                return Qnorm.qnorm(u1 / BIG, 0.0, 1.0, true, false);
+
+            case KINDERMAN_RAMAGE: /* see Reference above */
+                /*
+                 * corrected version from Josef Leydold
+                 */
+                u1 = rand.genrandDouble();
+                if (u1 < 0.884070402298758) {
+                    u2 = rand.genrandDouble();
+                    return A * (1.131131635444180 * u1 + u2 - 1);
+                }
+
+                if (u1 >= 0.973310954173898) { /* tail: */
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = (A * A - 2 * log(u3));
+                        if (u2 * u2 < (A * A) / tt) {
+                            return (u1 < 0.986655477086949) ? sqrt(tt) : -sqrt(tt);
+                        }
+                    }
+                }
+
+                if (u1 >= 0.958720824790463) { /* region3: */
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = A - 0.630834801921960 * fmin2(u2, u3);
+                        if (fmax2(u2, u3) <= 0.755591531667601) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                        if (0.034240503750111 * fabs(u2 - u3) <= g(tt)) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                    }
+                }
+
+                if (u1 >= 0.911312780288703) { /* region2: */
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = 0.479727404222441 + 1.105473661022070 * fmin2(u2, u3);
+                        if (fmax2(u2, u3) <= 0.872834976671790) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                        if (0.049264496373128 * fabs(u2 - u3) <= g(tt)) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                    }
+                }
+
+                /* ELSE region1: */
+                if (true) { // Satisfy foolish style checker requiring "break"
+                            // or "return" after infinite loops
+                    while (true) {
+                        u2 = rand.genrandDouble();
+                        u3 = rand.genrandDouble();
+                        tt = 0.479727404222441 - 0.595507138015940 * fmin2(u2, u3);
+                        if (tt < 0.) {
+                            continue;
+                        }
+                        if (fmax2(u2, u3) <= 0.805577924423817) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                        if (0.053377549506886 * fabs(u2 - u3) <= g(tt)) {
+                            return (u2 < u3) ? tt : -tt;
+                        }
+                    }
+                }
+                return 0d; // can NEVER reach here (infinite loop ahead)
+
+            default:
+                throw new AssertionError();
         }
-        /* unif_rand() alone is not of high enough precision */
-        double u1 = rand.genrandDouble();
-        u1 = (int) (BIG * u1) + rand.genrandDouble();
-        return Qnorm.qnorm(u1 / BIG, 0.0, 1.0, true, false);
     }
 }
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 3c238793e1..602aa49468 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
@@ -134882,6 +134882,48 @@ In rhyper(1, NA, 5, 20) : NAs produced
 #set.seed(3); rhyper(3, 10, 79e70, 2)
 [1] 0 0 0
 
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testGenerators#
+#for(gen in c("Buggy Kinderman-Ramage", "Ahrens-Dieter", "Box-Muller", "Inversion", "Kinderman-Ramage", "default")) { print(paste0(gen, ":")); RNGkind(NULL,gen); set.seed(42); print(rnorm(30)); }
+[1] "Buggy Kinderman-Ramage:"
+ [1] -0.79604712  1.28771872  0.71745084 -0.42255829  0.56567165  1.65777846
+ [7] -0.55131328  1.00482417 -0.24735845  0.24860615 -0.36036694 -1.73747216
+[13] -0.25369717 -1.04076998  2.23551204 -0.28116912 -0.46380894 -0.16281811
+[19]  1.16178557 -1.20815956  0.57057609  2.45914868  0.33370144  0.29920774
+[25]  0.05462671 -1.79697222 -0.61127365 -0.12708318 -1.36417253 -0.92312656
+[1] "Ahrens-Dieter:"
+ [1] -1.273084700 -1.414657032  0.739312189 -0.893074355 -0.321064732
+ [6] -0.008679202 -0.584610918  0.302830939 -0.361476229 -0.493404872
+[11]  1.546579146 -0.553905239 -1.531588211 -0.112289664 -1.217388818
+[16]  0.313559035 -2.138347829  1.148211398 -1.226981451  1.478797153
+[21] -0.915508892 -0.587726941 -0.825282001  1.137582651 -0.438588414
+[26]  2.420172264  2.565920821  1.405014135  0.054642602 -1.756587679
+[1] "Box-Muller:"
+ [1]  0.31010081 -0.18390356 -0.13723045  0.59392645 -0.72021551 -0.89029361
+ [7] -0.16854514 -1.99536938 -0.46122133 -0.69728478 -0.78362342  0.21309613
+[13]  1.51492034 -0.65927181 -0.34191267  0.08255685  2.05016803 -0.28224116
+[19] -1.06305839  0.16839189  1.63711374 -1.12720712  0.33027271 -0.02308900
+[25]  1.00206928  0.57104929 -0.34322783  0.28320445 -0.56561519  0.19576159
+[1] "Inversion:"
+ [1]  1.37095845 -0.56469817  0.36312841  0.63286260  0.40426832 -0.10612452
+ [7]  1.51152200 -0.09465904  2.01842371 -0.06271410  1.30486965  2.28664539
+[13] -1.38886070 -0.27878877 -0.13332134  0.63595040 -0.28425292 -2.65645542
+[19] -2.44046693  1.32011335 -0.30663859 -1.78130843 -0.17191736  1.21467470
+[25]  1.89519346 -0.43046913 -0.25726938 -1.76316309  0.46009735 -0.63999488
+[1] "Kinderman-Ramage:"
+ [1] -0.79604712  1.28771872  0.71745084 -0.42255829  0.56567165  1.65777846
+ [7] -0.55131328  1.00482417 -0.24735845  0.21355380  1.43016945  0.27516802
+[13] -0.36036694 -1.73747216 -0.25369717 -1.04076998  2.23551204 -0.28116912
+[19] -0.46380894 -0.16281811  1.16178557 -1.20815956  0.57057609  2.45914868
+[25]  0.33370144  0.29920774  0.05462671 -1.79697222 -0.61127365 -0.12708318
+[1] "default:"
+ [1]  1.37095845 -0.56469817  0.36312841  0.63286260  0.40426832 -0.10612452
+ [7]  1.51152200 -0.09465904  2.01842371 -0.06271410  1.30486965  2.28664539
+[13] -1.38886070 -0.27878877 -0.13332134  0.63595040 -0.28425292 -2.65645542
+[19] -2.44046693  1.32011335 -0.30663859 -1.78130843 -0.17191736  1.21467470
+[25]  1.89519346 -0.43046913 -0.25726938 -1.76316309  0.46009735 -0.63999488
+Warning message:
+In RNGkind(NULL, gen) : buggy version of Kinderman-Ramage generator used
+
 ##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testRmultinom#Output.IgnoreErrorContext#Output.IgnoreErrorMessage#
 #rmultinom('string', 1, 0.15)
 Error in rmultinom("string", 1, 0.15) : invalid first argument 'n'
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
index e177706ddf..904c869122 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -96,4 +96,10 @@ public class TestRandGenerationFunctions extends TestBase {
         assertEval("rmultinom(1, NA, 0.2)");
         assertEval("rmultinom(NA, 1, 0.2)");
     }
+
+    @Test
+    public void testGenerators() {
+        assertEval("for(gen in c(\"Buggy Kinderman-Ramage\", \"Ahrens-Dieter\", \"Box-Muller\", \"Inversion\", \"Kinderman-Ramage\", \"default\")) { print(paste0(gen, \":\")); RNGkind(NULL,gen); set.seed(42); print(rnorm(30)); }");
+    }
+
 }
-- 
GitLab


From b48ec8a3890b5432943cad6bdf0a2e7a5034c51f Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Thu, 23 Feb 2017 19:46:33 +0100
Subject: [PATCH 043/402] A couple of fixes in builtin diagnostics

---
 .../builtin/ResultTypesAnalyserTest.java      |  21 ++-
 .../r/nodes/casts/ResultTypesAnalyser.java    | 132 ++++++++----------
 .../builtin/casts/ExecutionPathVisitor.java   |  32 ++++-
 3 files changed, 102 insertions(+), 83 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
index d22ab4cd4c..3c2e35c7e5 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
@@ -167,9 +169,8 @@ public class ResultTypesAnalyserTest {
     @Test
     public void testBoxPrimitive() {
         arg.boxPrimitive();
-        TypeExpr expected = TypeExpr.union(RNull.class, RMissing.class, RInteger.class, RLogical.class,
-                        RDouble.class, RString.class);
-        expected = expected.or(expected.not());
+        TypeExpr expected = TypeExpr.union(RInteger.class, RLogical.class, RDouble.class, RString.class);
+        expected = expected.or((expected.not().and(atom(String.class).not()).and(atom(Double.class).not()).and(atom(Integer.class).not()).and(atom(Byte.class).not())));
         assertTypes(expected);
     }
 
@@ -428,11 +429,23 @@ public class ResultTypesAnalyserTest {
     }
 
     @Test
-    public void testReturnIf() {
+    public void testReturnIf1() {
         arg.mapIf(nullValue(), mark(constant(1), "m1"), mark(constant("abc"), "m2"));
         assertTypes(atom(String.class).lower(m("m2")).or(atom(Integer.class).lower(m("m1"))));
     }
 
+    @Test
+    public void testReturnIf2() {
+        arg.returnIf(nullValue(), emptyIntegerVector()).returnIf(missingValue(), emptyIntegerVector()).asIntegerVector();
+        assertTypes(atom(int.class).or(atom(RIntSequence.class)).or(atom(RIntVector.class)), true);
+    }
+
+    @Test
+    public void testMustNotBeMissingAndBoxPrimitive() {
+        arg.mustNotBeMissing().returnIf(nullValue(), nullConstant()).mustBe(stringValue()).boxPrimitive().asStringVector();
+        assertTypes(atom(RNull.class).or(atom(RStringVector.class)), true);
+    }
+
     @Test
     public void testAllowMissing() {
         arg.allowMissing().mustBe(stringValue());
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
index ba943022bf..5df10cc4e0 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
@@ -65,7 +65,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
-import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser.AltTypeExpr;
 import com.oracle.truffle.r.nodes.unary.CastComplexNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleBaseNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
@@ -98,58 +97,27 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> implements MapperVisitor<TypeExpr>, FilterVisitor<TypeExpr>, SubjectVisitor<TypeExpr> {
-
-    static final class AltTypeExpr {
-        final TypeExpr main;
-        final TypeExpr alt;
-
-        private AltTypeExpr(TypeExpr mainBranch, TypeExpr altBranch) {
-            this.main = mainBranch;
-            this.alt = altBranch;
-        }
-
-        static AltTypeExpr create() {
-            return new AltTypeExpr(TypeExpr.ANYTHING, null);
-        }
-
-        TypeExpr merge() {
-            return alt == null ? main : main.or(alt);
-        }
-
-        AltTypeExpr setMain(TypeExpr newMainType) {
-            return newMainType == null ? this : new AltTypeExpr(newMainType, alt);
-        }
-
-        AltTypeExpr addAlt(TypeExpr newAltType) {
-            return newAltType == null ? this : new AltTypeExpr(main, alt == null ? newAltType : alt.or(newAltType));
-        }
-
-        AltTypeExpr or(AltTypeExpr other) {
-            return setMain(main.or(other.main)).addAlt(other.alt);
-        }
-
-    }
+public class ResultTypesAnalyser extends ExecutionPathVisitor<TypeExpr> implements MapperVisitor<TypeExpr>, FilterVisitor<TypeExpr>, SubjectVisitor<TypeExpr> {
 
     private static final TypeExpr NOT_NULL_NOT_MISSING = atom(RNull.class).not().and(atom(RMissing.class).not());
 
     public static TypeExpr analyse(PipelineStep<?, ?> firstStep) {
-        return analyse(firstStep, AltTypeExpr.create()).merge();
+        return analyse(firstStep, TypeExpr.ANYTHING);
     }
 
-    public static AltTypeExpr analyse(PipelineStep<?, ?> firstStep, AltTypeExpr inputType) {
-        List<AltTypeExpr> pathResults = new ResultTypesAnalyser().visitPaths(firstStep, inputType);
+    public static TypeExpr analyse(PipelineStep<?, ?> firstStep, TypeExpr inputType) {
+        List<TypeExpr> pathResults = new ResultTypesAnalyser().visitPaths(firstStep, inputType);
         return pathResults.stream().reduce((x, y) -> x.or(y)).get();
     }
 
     @Override
-    public AltTypeExpr visit(FindFirstStep<?, ?> step, AltTypeExpr inputType) {
+    public TypeExpr visit(FindFirstStep<?, ?> step, TypeExpr inputType) {
         TypeExpr rt;
         if (step.getElementClass() == null || step.getElementClass() == Object.class) {
-            if (inputType.main.isAnything()) {
+            if (inputType.isAnything()) {
                 rt = atom(RAbstractVector.class).not();
             } else {
-                Set<Type> resTypes = inputType.main.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet());
+                Set<Type> resTypes = inputType.classify().stream().map(c -> CastUtils.elementType(c)).collect(Collectors.toSet());
                 rt = TypeExpr.union(resTypes);
             }
         } else {
@@ -167,7 +135,7 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
             rt = rt.and(atom(RNull.class).not()).and(atom(RMissing.class).not());
         }
 
-        return inputType.setMain(rt);
+        return rt;
     }
 
     private static TypeExpr inferResultTypeFromSpecializations(Class<? extends CastNode> castNodeClass, TypeExpr inputType) {
@@ -175,56 +143,56 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
     }
 
     @Override
-    public AltTypeExpr visit(CoercionStep<?, ?> step, AltTypeExpr inputType) {
+    public TypeExpr visit(CoercionStep<?, ?> step, TypeExpr inputType) {
         RType type = step.getType();
         TypeExpr res;
         switch (type) {
             case Integer:
-                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastIntegerNode.class, inputType.main) : inferResultTypeFromSpecializations(CastIntegerBaseNode.class, inputType.main);
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastIntegerNode.class, inputType) : inferResultTypeFromSpecializations(CastIntegerBaseNode.class, inputType);
                 break;
             case Double:
-                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastDoubleNode.class, inputType.main) : inferResultTypeFromSpecializations(CastDoubleBaseNode.class, inputType.main);
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastDoubleNode.class, inputType) : inferResultTypeFromSpecializations(CastDoubleBaseNode.class, inputType);
                 break;
             case Character:
-                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastStringNode.class, inputType.main) : inferResultTypeFromSpecializations(CastStringBaseNode.class, inputType.main);
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastStringNode.class, inputType) : inferResultTypeFromSpecializations(CastStringBaseNode.class, inputType);
                 break;
             case Logical:
-                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastLogicalNode.class, inputType.main) : inferResultTypeFromSpecializations(CastLogicalBaseNode.class, inputType.main);
+                res = step.vectorCoercion ? inferResultTypeFromSpecializations(CastLogicalNode.class, inputType) : inferResultTypeFromSpecializations(CastLogicalBaseNode.class, inputType);
                 break;
             case Complex:
-                res = inferResultTypeFromSpecializations(CastComplexNode.class, inputType.main);
+                res = inferResultTypeFromSpecializations(CastComplexNode.class, inputType);
                 break;
             case Raw:
-                res = inferResultTypeFromSpecializations(CastRawNode.class, inputType.main);
+                res = inferResultTypeFromSpecializations(CastRawNode.class, inputType);
                 break;
             case Any:
                 TypeExpr funOrVecTp = atom(RFunction.class).or(atom(RAbstractVector.class));
-                res = inputType.main.and(funOrVecTp);
+                res = inputType.and(funOrVecTp);
                 break;
             default:
                 throw RInternalError.shouldNotReachHere(Utils.stringFormat("Unsupported type '%s' in AsVectorStep", type));
         }
 
         if (step.preserveNonVector) {
-            TypeExpr maskedNullMissing = inputType.main.and(atom(RNull.class).or(atom(RMissing.class)));
+            TypeExpr maskedNullMissing = inputType.and(atom(RNull.class).or(atom(RMissing.class)));
             res = res.or(maskedNullMissing);
         }
 
-        return inputType.setMain(res);
+        return res;
     }
 
     @Override
-    public AltTypeExpr visit(MapStep<?, ?> step, AltTypeExpr inputType) {
-        return inputType.setMain(step.getMapper().accept(this, inputType.main));
+    public TypeExpr visit(MapStep<?, ?> step, TypeExpr inputType) {
+        return step.getMapper().accept(this, inputType);
     }
 
     @Override
-    protected AltTypeExpr visitBranch(MapIfStep<?, ?> step, AltTypeExpr inputType, boolean visitTrueBranch) {
-        TypeExpr filterRes = visitFilter(step.getFilter(), inputType.main);
+    protected TypeExpr visitBranch(MapIfStep<?, ?> step, TypeExpr inputType, boolean visitTrueBranch) {
+        TypeExpr filterRes = visitFilter(step.getFilter(), inputType);
         if (visitTrueBranch) {
             if (step.isReturns()) {
-                AltTypeExpr returnedType = trueBranchResultTypes(step, inputType, filterRes);
-                return inputType.addAlt(returnedType.merge());
+                TypeExpr returnedType = trueBranchResultTypes(step, inputType, filterRes);
+                return returnedType;
             } else {
                 return trueBranchResultTypes(step, inputType, filterRes);
             }
@@ -233,64 +201,74 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<AltTypeExpr> imple
         }
     }
 
-    private static AltTypeExpr trueBranchResultTypes(MapIfStep<?, ?> step, AltTypeExpr inputType, TypeExpr filterRes) {
-        TypeExpr filterTrueCaseType = inputType.main.and(filterRes);
+    private static TypeExpr trueBranchResultTypes(MapIfStep<?, ?> step, TypeExpr inputType, TypeExpr filterRes) {
+        TypeExpr filterTrueCaseType = inputType.and(filterRes);
         if (step.getTrueBranch() != null) {
-            return analyse(step.getTrueBranch(), inputType.setMain(filterTrueCaseType));
+            return analyse(step.getTrueBranch(), filterTrueCaseType);
         } else {
-            return inputType.setMain(filterTrueCaseType);
+            return filterTrueCaseType;
         }
     }
 
-    private static AltTypeExpr falseBranchResultTypes(MapIfStep<?, ?> step, AltTypeExpr inputType, TypeExpr filterRes) {
-        TypeExpr filterFalseCaseType = inputType.main.and(filterRes.not());
+    private static TypeExpr falseBranchResultTypes(MapIfStep<?, ?> step, TypeExpr inputType, TypeExpr filterRes) {
+        TypeExpr filterFalseCaseType = inputType.and(filterRes.not());
         if (step.getFalseBranch() != null) {
-            return analyse(step.getFalseBranch(), inputType.setMain(filterFalseCaseType));
+            return analyse(step.getFalseBranch(), filterFalseCaseType);
         } else {
-            return inputType.setMain(filterFalseCaseType);
+            return filterFalseCaseType;
         }
     }
 
     @Override
-    public AltTypeExpr visit(FilterStep<?, ?> step, AltTypeExpr inputType) {
+    public TypeExpr visit(FilterStep<?, ?> step, TypeExpr inputType) {
         if (step.isWarning()) {
             return inputType;
         } else {
-            return inputType.setMain(inputType.main.and(visitFilter(step.getFilter(), inputType.main)));
+            return inputType.and(visitFilter(step.getFilter(), inputType));
         }
     }
 
     @Override
-    public AltTypeExpr visit(NotNAStep<?> step, AltTypeExpr inputType) {
-        Set<Object> naSamples = inputType.main.toNormalizedConjunctionSet().stream().filter(t -> t instanceof Class).map(t -> CastUtils.naValue((Class<?>) t)).filter(x -> x != null).collect(
+    public TypeExpr visit(NotNAStep<?> step, TypeExpr inputType) {
+        Set<Object> naSamples = inputType.toNormalizedConjunctionSet().stream().filter(t -> t instanceof Class).map(t -> CastUtils.naValue((Class<?>) t)).filter(x -> x != null).collect(
                         Collectors.toSet());
-        TypeExpr resType = inputType.main.lower(step);
+        TypeExpr resType = inputType.lower(step);
         resType = resType.negativeSamples(naSamples);
         if (step.getReplacement() != null) {
             resType = resType.positiveSamples(step.getReplacement());
         }
-        return inputType.setMain(resType);
+        return resType;
     }
 
     @Override
-    public AltTypeExpr visit(DefaultErrorStep<?> step, AltTypeExpr inputType) {
+    public TypeExpr visit(DefaultErrorStep<?> step, TypeExpr inputType) {
         return inputType;
     }
 
     @Override
-    public AltTypeExpr visit(DefaultWarningStep<?> step, AltTypeExpr inputType) {
+    public TypeExpr visit(DefaultWarningStep<?> step, TypeExpr inputType) {
         return inputType;
     }
 
     @Override
-    public AltTypeExpr visit(BoxPrimitiveStep<?> step, AltTypeExpr inputType) {
-        TypeExpr res = TypeExpr.union(RNull.class, RMissing.class, RInteger.class, RLogical.class, RDouble.class, RString.class);
-        return inputType.setMain(res.or(res.not()));
+    public TypeExpr visit(BoxPrimitiveStep<?> step, TypeExpr inputType) {
+        TypeExpr noPrimType = atom(Integer.class).not().and(atom(Byte.class).not()).and(atom(Double.class).not()).and(atom(String.class).not());
+        // cancel potential primitive types in the input
+        TypeExpr noPrimInput = inputType.and(noPrimType);
+        // the positive output type union
+        TypeExpr res = TypeExpr.union(RInteger.class, RLogical.class, RDouble.class, RString.class);
+        // intersect the to stop propagating the primitive types, such as String
+        res = res.and(noPrimInput);
+        // the output of the boxing is actually the union of the positive union with its negation
+        // that represents the fallback output for non-vectors
+        TypeExpr negRes = res.not().and(noPrimInput);
+        res = res.or(negRes);
+        return res;
     }
 
     @Override
-    public AltTypeExpr visit(AttributableCoercionStep<?> step, AltTypeExpr inputType) {
-        return inputType.setMain(inferResultTypeFromSpecializations(CastToAttributableNode.class, inputType.main));
+    public TypeExpr visit(AttributableCoercionStep<?> step, TypeExpr inputType) {
+        return inferResultTypeFromSpecializations(CastToAttributableNode.class, inputType);
     }
 
     // MapperVisitor
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
index fc8abb28d8..4c163d8518 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
@@ -39,6 +39,7 @@ public abstract class ExecutionPathVisitor<T> implements PipelineStepVisitor<T>
     private int mapIfCounter;
     private List<T> results = new ArrayList<>();
 
+    @SuppressWarnings("unchecked")
     public List<T> visitPaths(PipelineStep<?, ?> firstStep, T initial) {
         if (firstStep == null) {
             return Collections.singletonList(initial);
@@ -48,7 +49,13 @@ public abstract class ExecutionPathVisitor<T> implements PipelineStepVisitor<T>
         int n = 1 << mapIfStepStatuses.size();
         for (long i = 1; i < n; i++) {
             bs = BitSet.valueOf(new long[]{i});
-            results.add(firstStep.acceptPipeline(this, initial));
+            T res;
+            try {
+                res = firstStep.acceptPipeline(this, initial);
+            } catch (PathBreakException br) {
+                res = (T) br.result;
+            }
+            results.add(res);
         }
         return results;
     }
@@ -62,9 +69,30 @@ public abstract class ExecutionPathVisitor<T> implements PipelineStepVisitor<T>
         } else {
             visitTrueBranch = bs.get(mapIfStepStatuses.get(step));
         }
-        return visitBranch(step, previous, visitTrueBranch);
+        T res = visitBranch(step, previous, visitTrueBranch);
+        if (step.isReturns() && visitTrueBranch) {
+            throw new PathBreakException(res);
+        } else {
+            return res;
+        }
     }
 
     protected abstract T visitBranch(MapIfStep<?, ?> step, T previous, boolean visitTrueBranch);
 
+    @SuppressWarnings("serial")
+    static final class PathBreakException extends RuntimeException {
+
+        private final Object result;
+
+        private PathBreakException(Object result) {
+            this.result = result;
+        }
+
+        @SuppressWarnings("sync-override")
+        @Override
+        public Throwable fillInStackTrace() {
+            return null;
+        }
+    }
+
 }
-- 
GitLab


From 169682ab954cb46198357db6e1bdcbda8f798f9a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 23 Feb 2017 20:26:50 +0100
Subject: [PATCH 044/402] Fixed cast pipeline related issues for functions:
 complex, cummax, cummin, cumprod, cumsum, det_ge_real, diag, digamma,
 file.link, file.show, file.symlink, for, function, gamma, gettext, if

---
 .../builtin/base/BaseGammaFunctions.java      | 16 ++++++--------
 .../truffle/r/nodes/builtin/base/Complex.java |  5 +++--
 .../truffle/r/nodes/builtin/base/CumMax.java  | 11 +++-------
 .../truffle/r/nodes/builtin/base/CumMin.java  | 11 +++-------
 .../truffle/r/nodes/builtin/base/CumProd.java |  9 +++-----
 .../truffle/r/nodes/builtin/base/CumSum.java  |  5 ++++-
 .../truffle/r/nodes/builtin/base/Diag.java    |  5 ++---
 .../r/nodes/builtin/base/FileFunctions.java   | 21 ++++++++++++++++---
 .../truffle/r/nodes/builtin/base/GetText.java |  4 +++-
 .../r/nodes/builtin/base/LaFunctions.java     |  2 +-
 .../nodes/builtin/base/infix/ForBuiltin.java  |  5 +++++
 .../builtin/base/infix/FunctionBuiltin.java   |  5 +++++
 .../r/nodes/builtin/base/infix/IfBuiltin.java |  5 +++++
 .../com/oracle/truffle/r/runtime/RError.java  |  1 +
 14 files changed, 62 insertions(+), 43 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index 005d49ee57..80c3abfefc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -49,6 +49,12 @@ public class BaseGammaFunctions {
 
     @RBuiltin(name = "gamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
     public abstract static class Gamma extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(Gamma.class);
+            casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENTS_PASSED, 0, "'gamma'", 1).mustBe(numericValue(), RError.Message.NON_NUMERIC_MATH).asDoubleVector().findFirst();
+        }
+
         @Specialization
         @TruffleBoundary
         protected RDoubleVector lgamma(@SuppressWarnings("unused") RAbstractDoubleVector x) {
@@ -142,16 +148,6 @@ public class BaseGammaFunctions {
             }
             return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
         }
-
-        @Specialization
-        protected RDoubleVector digamma(RAbstractIntVector x) {
-            return digamma(RClosures.createIntToDoubleVector(x));
-        }
-
-        @Specialization
-        protected RDoubleVector digamma(RAbstractLogicalVector x) {
-            return digamma(RClosures.createLogicalToDoubleVector(x));
-        }
     }
 
     protected abstract static class DpsiFnCalc extends Node {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
index f8826494d7..d79675c636 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -44,8 +45,8 @@ public abstract class Complex extends RBuiltinNode {
     static {
         Casts casts = new Casts(Complex.class);
         casts.arg("length.out").asIntegerVector().findFirst(Message.INVALID_LENGTH);
-        casts.arg("real").mapNull(emptyDoubleVector()).asDoubleVector();
-        casts.arg("imaginary").mapNull(emptyDoubleVector()).asDoubleVector();
+        casts.arg("real").mustNotBeMissing().mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
+        casts.arg("imaginary").mustNotBeMissing().mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
index 236988ed46..b108f85ee4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
@@ -15,6 +15,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVec
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -34,7 +35,6 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -48,8 +48,8 @@ public abstract class CumMax extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(CumMax.class);
-        casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false),
-                        asDoubleVector(true, false, false));
+        casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mustBe(complexValue().not(), RError.Message.CUMMAX_UNDEFINED_FOR_COMPLEX).mapIf(
+                        integerValue().or(logicalValue()), asIntegerVector(true, false, false), asDoubleVector(true, false, false));
     }
 
     @Specialization
@@ -67,11 +67,6 @@ public abstract class CumMax extends RBuiltinNode {
         return RDataFactory.createEmptyDoubleVector();
     }
 
-    @Specialization(guards = "emptyVec.getLength()==0")
-    protected RAbstractVector cumEmpty(RAbstractComplexVector emptyVec) {
-        return RDataFactory.createComplexVector(new double[0], true, emptyVec.getNames());
-    }
-
     @Specialization(guards = "emptyVec.getLength()==0")
     protected RAbstractVector cumEmpty(RAbstractDoubleVector emptyVec) {
         return RDataFactory.createDoubleVector(new double[0], true, emptyVec.getNames());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
index ae28196a60..fe04402556 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
@@ -15,6 +15,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVec
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -34,7 +35,6 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -48,8 +48,8 @@ public abstract class CumMin extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(CumMin.class);
-        casts.arg("x").allowNull().mustBe(complexValue().not(), RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false),
-                        asDoubleVector(true, false, false));
+        casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mustBe(complexValue().not(), RError.Message.CUMMIN_UNDEFINED_FOR_COMPLEX).mapIf(
+                        integerValue().or(logicalValue()), asIntegerVector(true, false, false), asDoubleVector(true, false, false));
     }
 
     @Specialization
@@ -67,11 +67,6 @@ public abstract class CumMin extends RBuiltinNode {
         return RDataFactory.createEmptyDoubleVector();
     }
 
-    @Specialization(guards = "emptyVec.getLength()==0")
-    protected RAbstractVector cumEmpty(RAbstractComplexVector emptyVec) {
-        return RDataFactory.createComplexVector(new double[0], true, emptyVec.getNames());
-    }
-
     @Specialization(guards = "emptyVec.getLength()==0")
     protected RAbstractVector cumEmpty(RAbstractDoubleVector emptyVec) {
         return RDataFactory.createDoubleVector(new double[0], true, emptyVec.getNames());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
index ef609bb011..50a2f53a3b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
@@ -12,6 +12,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -21,6 +22,7 @@ import java.util.Arrays;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -44,12 +46,7 @@ public abstract class CumProd extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(CumProd.class);
-        casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector(true, false, false));
-    }
-
-    @Specialization
-    protected int cumprod(int arg) {
-        return arg;
+        casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mapIf(complexValue().not(), asDoubleVector(true, false, false));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
index 7a1886ac6e..d0aa710798 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
@@ -29,6 +29,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -38,6 +39,7 @@ import java.util.Arrays;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -64,7 +66,8 @@ public abstract class CumSum extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(CumSum.class);
-        casts.arg("x").allowNull().mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false), chain(mapIf(complexValue().not(), asDoubleVector(true, false, false))).end());
+        casts.arg("x").allowNull().mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 0, "cumsum", 1).mapIf(integerValue().or(logicalValue()), asIntegerVector(true, false, false),
+                        chain(mapIf(complexValue().not(), asDoubleVector(true, false, false))).end());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
index 6ddd7cabaf..56e2cae7e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
@@ -14,6 +14,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte0;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
@@ -38,10 +39,8 @@ public abstract class Diag extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Diag.class);
-        casts.arg("x").allowNull().mapIf(complexValue().not(), asDoubleVector());
-
+        casts.arg("x").mustNotBeMissing().returnIf(nullValue()).mapIf(complexValue().not(), asDoubleVector());
         casts.arg("nrow").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "nrow").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "nrow");
-
         casts.arg("ncol").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "ncol").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "ncol");
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index 63faccad5a..8dfde766fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -20,6 +20,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -470,6 +471,13 @@ public class FileFunctions {
 
     @RBuiltin(name = "file.link", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO)
     public abstract static class FileLink extends FileLinkAdaptor {
+
+        static {
+            Casts casts = new Casts(FileLink.class);
+            casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector();
+            casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector();
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object doFileLink(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) {
@@ -479,6 +487,13 @@ public class FileFunctions {
 
     @RBuiltin(name = "file.symlink", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO)
     public abstract static class FileSymLink extends FileLinkAdaptor {
+
+        static {
+            Casts casts = new Casts(FileSymLink.class);
+            casts.arg("from").mustBe(stringValue(), RError.Message.INVALID_FIRST_FILENAME).asStringVector();
+            casts.arg("to").mustBe(stringValue(), RError.Message.INVALID_SECOND_FILENAME).asStringVector();
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object doFileSymLink(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) {
@@ -1017,9 +1032,9 @@ public class FileFunctions {
 
         static {
             Casts casts = new Casts(FileShow.class);
-            casts.arg("files").asStringVector();
-            casts.arg("header").asStringVector();
-            casts.arg("title").asStringVector();
+            casts.arg("files").mustNotBeMissing().mustBe(nullValue().not(), Message.INVALID_FILENAME_SPECIFICATION).asStringVector();
+            casts.arg("header").mustNotBeMissing().mustBe(nullValue().not(), Message.INVALID_ARG, "'headers'").asStringVector();
+            casts.arg("title").mustNotBeMissing().mustBe(nullValue().not(), Message.INVALID_ARG, "'title'").asStringVector();
             casts.arg("delete.file").asLogicalVector().findFirst().map(toBoolean());
             casts.arg("pager").asStringVector().findFirst();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
index 32583e1a76..b9905ce517 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
@@ -22,11 +22,13 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -37,7 +39,7 @@ public abstract class GetText extends RBuiltinNode {
     static {
         Casts casts = new Casts(GetText.class);
         casts.arg("domain").asStringVector().findFirst("");
-        casts.arg("args").asStringVector();
+        casts.arg("args").mustNotBeMissing(SHOW_CALLER, Message.ARGUMENT_EMPTY, 2).asStringVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 3be554555f..f37d5a074c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -399,7 +399,7 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected RList doDetGeReal(RDoubleVector aIn, boolean useLog,
+        protected RList doDetGeReal(RAbstractDoubleVector aIn, boolean useLog,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") LapackRFFI.DgetrfNode dgetrfNode) {
             RDoubleVector a = (RDoubleVector) aIn.copy();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java
index 562c7be2c0..cbb0e5ae48 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java
@@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "for", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class ForBuiltin extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(ForBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
index b1ebcae60c..c81176d2e3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
@@ -32,6 +32,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "function", kind = PRIMITIVE, parameterNames = {"x"}, behavior = READS_FRAME)
 public abstract class FunctionBuiltin extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(FunctionBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java
index 9c6ebc6058..9920963799 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java
@@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "if", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class IfBuiltin extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(IfBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 85a79915a5..dc17e17dbb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -767,6 +767,7 @@ public final class RError extends RuntimeException {
         INVALID_ARG_OF_LENGTH("invalid %s argument of length %d"),
         INVALID_ARG("invalid %s argument"),
         INVALID_FILENAME_PATTERN("invalid filename pattern"),
+        INVALID_FILENAME_SPECIFICATION("invalid filename specification"),
         INVALID_FILE_EXT("invalid file extension"),
         NO("no '%s'"),
         APPLIES_TO_VECTORS("%s applies only to vectors"),
-- 
GitLab


From 99f8af5603efc1f319532e83f1f0c9d5452cfb0c Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Feb 2017 17:21:37 +0100
Subject: [PATCH 045/402] rbdiag warnings fixed for several builtins and
 externals

---
 .../r/library/stats/StatsFunctionsNodes.java  | 66 +++++++++++--------
 .../truffle/r/library/utils/ObjectSize.java   | 12 ++--
 .../builtin/base/BaseGammaFunctions.java      |  5 ++
 .../builtin/base/ConnectionFunctions.java     | 25 +++----
 .../truffle/r/nodes/builtin/base/UnClass.java |  2 +-
 .../truffle/r/nodes/builtin/base/Unique.java  | 41 +++++-------
 .../truffle/r/nodes/builtin/base/VApply.java  | 39 +++++++----
 .../r/nodes/builtin/base/WhichFunctions.java  |  4 +-
 .../builtin/base/foreign/CairoProps.java      |  6 +-
 .../r/nodes/builtin/base/foreign/Fft.java     |  4 +-
 .../builtin/base/foreign/WriteTable.java      | 10 ++-
 .../builtin/base/infix/BraceBuiltin.java      |  6 ++
 .../builtin/base/infix/WhileBuiltin.java      |  7 +-
 .../casts/fluent/CoercedPhaseBuilder.java     |  5 ++
 .../com/oracle/truffle/r/runtime/RError.java  |  1 +
 .../truffle/r/runtime/data/RFunction.java     |  2 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 25 +++++++
 .../r/test/builtins/TestBuiltin_vapply.java   |  4 ++
 .../test/builtins/TestBuiltin_writeChar.java  | 38 +++++++++++
 19 files changed, 208 insertions(+), 94 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
index 11a0662bdf..e3d7bba69b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
@@ -12,6 +12,7 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -30,9 +31,11 @@ import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_2
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_1NodeGen;
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_2NodeGen;
 import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
@@ -137,6 +140,15 @@ public final class StatsFunctionsNodes {
         return resultVec;
     }
 
+    private static void castBoolean(Casts casts, int index, byte defaultValue) {
+        // defensively we map missing to the default values
+        casts.arg(index).asLogicalVector().findFirst(defaultValue).map(toBoolean());
+    }
+
+    private static void castDoubleVec(Casts casts, int index) {
+        casts.arg(index).mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).asDoubleVector();
+    }
+
     public abstract static class Function3_2Node extends RExternalBuiltinNode.Arg5 {
         private final Function3_2 function;
 
@@ -150,11 +162,11 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Function3_2Node.class);
-            casts.arg(0).asDoubleVector();
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asDoubleVector();
-            casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
-            casts.arg(4).asLogicalVector().findFirst().map(toBoolean());
+            castDoubleVec(casts, 0);
+            castDoubleVec(casts, 1);
+            castDoubleVec(casts, 2);
+            castBoolean(casts, 3, RRuntime.LOGICAL_TRUE);
+            castBoolean(casts, 4, RRuntime.LOGICAL_FALSE);
         }
 
         @Specialization
@@ -178,11 +190,11 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Function4_1Node.class);
-            casts.arg(0).asDoubleVector();
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asDoubleVector();
-            casts.arg(3).asDoubleVector();
-            casts.arg(4).asLogicalVector().findFirst().map(toBoolean());
+            castDoubleVec(casts, 0);
+            castDoubleVec(casts, 1);
+            castDoubleVec(casts, 2);
+            castDoubleVec(casts, 3);
+            castBoolean(casts, 4, RRuntime.LOGICAL_TRUE);
         }
 
         @Specialization
@@ -206,12 +218,12 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Function4_2Node.class);
-            casts.arg(0).asDoubleVector();
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asDoubleVector();
-            casts.arg(3).asDoubleVector();
-            casts.arg(4).asLogicalVector().findFirst().map(toBoolean());
-            casts.arg(5).asLogicalVector().findFirst().map(toBoolean());
+            castDoubleVec(casts, 0);
+            castDoubleVec(casts, 1);
+            castDoubleVec(casts, 2);
+            castDoubleVec(casts, 3);
+            castBoolean(casts, 4, RRuntime.LOGICAL_TRUE);
+            castBoolean(casts, 5, RRuntime.LOGICAL_FALSE);
         }
 
         @Specialization
@@ -235,10 +247,10 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Function3_1Node.class);
-            casts.arg(0).asDoubleVector();
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asDoubleVector();
-            casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
+            castDoubleVec(casts, 0);
+            castDoubleVec(casts, 1);
+            castDoubleVec(casts, 2);
+            castBoolean(casts, 3, RRuntime.LOGICAL_TRUE);
         }
 
         @Specialization
@@ -262,9 +274,9 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Function2_1Node.class);
-            casts.arg(0).asDoubleVector();
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asLogicalVector().findFirst().map(toBoolean());
+            castDoubleVec(casts, 0);
+            castDoubleVec(casts, 1);
+            castBoolean(casts, 2, RRuntime.LOGICAL_TRUE);
         }
 
         @Specialization
@@ -288,10 +300,10 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Function2_2Node.class);
-            casts.arg(0).asDoubleVector();
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asLogicalVector().findFirst().map(toBoolean());
-            casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
+            castDoubleVec(casts, 0);
+            castDoubleVec(casts, 1);
+            castBoolean(casts, 2, RRuntime.LOGICAL_TRUE);
+            castBoolean(casts, 3, RRuntime.LOGICAL_FALSE);
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java
index 8c17ea3fb6..6e32b3837a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/ObjectSize.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.library.utils;
 
+import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -37,14 +39,14 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
  */
 public abstract class ObjectSize extends RExternalBuiltinNode.Arg1 {
 
+    static {
+        noCasts(ObjectSize.class);
+    }
+
     private static class MyIgnoreObjectHandler implements RObjectSize.IgnoreObjectHandler {
         @Override
         public boolean ignore(Object rootObject, Object obj) {
-            if (obj == RNull.instance) {
-                return true;
-            } else {
-                return false;
-            }
+            return obj == RNull.instance;
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index 005d49ee57..cd2770c3c1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -58,9 +58,14 @@ public class BaseGammaFunctions {
 
     @RBuiltin(name = "trigamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
     public abstract static class TriGamma extends RBuiltinNode {
+        static {
+            Casts.noCasts(TriGamma.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected RDoubleVector trigamma(@SuppressWarnings("unused") RAbstractDoubleVector x) {
+            // Note: this is actually unimplemented even in GnuR
             throw RError.nyi(this, "trigamma");
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 5357665035..a959470c20 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
@@ -31,6 +32,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalTrue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
@@ -90,6 +92,7 @@ import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -166,7 +169,7 @@ public abstract class ConnectionFunctions {
         }
 
         private static void nchars(Casts casts) {
-            casts.arg("nchars").asIntegerVector().mustBe(notEmpty());
+            casts.arg("nchars").mustNotBeMissing().mapIf(nullValue(), constant(0)).asIntegerVector().mustBe(notEmpty());
         }
 
         private static void useBytes(Casts casts) {
@@ -725,13 +728,16 @@ public abstract class ConnectionFunctions {
     public abstract static class WriteChar extends RBuiltinNode {
 
         static {
+            // @formatter:off
             Casts casts = new Casts(WriteChar.class);
-            casts.arg("object").asStringVector();
-            casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(),
-                            asIntegerVector().setNext(findFirst().integerElement()));
+            casts.arg("object").mustBe(stringValue(), RError.SHOW_CALLER, Message.ONLY_WRITE_CHAR_OBJECTS).asStringVector();
+            casts.arg("con").mustBe(rawValue().not(), Message.GENERIC, "raw connection in writeChar not implemented in FastR yet.").
+                    mustBe(stringValue().not(), Message.GENERIC, "filename as a connection in writeChar not implemented in FastR yet.").
+                    mustBe(integerValue(), RError.SHOW_CALLER, Message.INVALID_CONNECTION).asIntegerVector().findFirst();
             CastsHelper.nchars(casts);
-            casts.arg("sep").allowNull().mustBe(stringValue());
+            casts.arg("sep").mustNotBeMissing().returnIf(nullValue()).mustBe(stringValue()).asStringVector();
             CastsHelper.useBytes(casts);
+            // @formatter:on
         }
 
         @Specialization
@@ -804,7 +810,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected Object readBin(int con, String what, int n, int sizeInput, boolean signed, boolean swap) {
-            RVector<?> result = null;
+            RVector<?> result;
             BaseRConnection connection = RConnection.fromIndex(con);
             try (RConnection openConn = connection.forceOpen("rb")) {
                 if (getBaseConnection(openConn).getOpenMode().isText()) {
@@ -1079,8 +1085,7 @@ public abstract class ConnectionFunctions {
 
         static {
             Casts casts = new Casts(WriteBin.class);
-            // TODO atomic, i.e. not RList or RExpression
-            casts.arg("object").asVector().mustBe(instanceOf(RAbstractVector.class));
+            casts.arg("object").asVector().mustBe(RAbstractAtomicVector.class);
             casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustBe(integerValue().or(rawValue())).mapIf(integerValue(), asIntegerVector().setNext(findFirst().integerElement()));
             CastsHelper.size(casts);
             CastsHelper.swap(casts);
@@ -1111,10 +1116,8 @@ public abstract class ConnectionFunctions {
         }
 
         @Specialization
-        protected RRawVector writeBin(RAbstractVector object, @SuppressWarnings("unused") RAbstractRawVector con, int size, byte swapArg, byte useBytesArg,
+        protected RRawVector writeBin(RAbstractVector object, @SuppressWarnings("unused") RAbstractRawVector con, int size, boolean swap, boolean useBytes,
                         @Cached("create()") WriteDataNode writeData) {
-            boolean swap = RRuntime.fromLogical(swapArg);
-            boolean useBytes = RRuntime.fromLogical(useBytesArg);
             ByteBuffer buffer = writeData.execute(object, size, swap, useBytes);
             buffer.flip();
             return RDataFactory.createRawVector(buffer.array());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
index 04288a4970..8090c363c0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
@@ -35,7 +35,7 @@ public abstract class UnClass extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(UnClass.class);
-        casts.arg("x").asAttributable(true, true, true);
+        casts.arg("x").mustNotBeMissing().asAttributable(true, true, true);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
index 56cad49e98..9b4faf6eaf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
@@ -23,7 +23,8 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalFalse;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -38,6 +39,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSet;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -57,7 +59,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "unique", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE)
 // TODO A more efficient implementation is in order; GNU R uses hash tables so perhaps we should
@@ -77,7 +78,7 @@ public abstract class Unique extends RBuiltinNode {
         // values or a (single) logical value
         // TODO: coercion error must be handled by specialization as it depends on type of x (much
         // like in duplicated)
-        casts.arg("incomparables").mapNull(emptyList()).asVector(true);
+        casts.arg("incomparables").mustBe(logicalValue()).asLogicalVector().findFirst().mustBe(logicalFalse(), Message.GENERIC, "Handling of 'incomparables' parameter in unique is not implemented.");
         casts.arg("fromLast").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         // currently not supported and not tested, but NA is a correct value (the same for empty
         // vectors) whereas 0 is not (throws an error)
@@ -86,13 +87,13 @@ public abstract class Unique extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RNull doUnique(RNull vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RNull doUnique(RNull vec, byte incomparables, byte fromLast, int nmax) {
         return vec;
     }
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RStringVector doUnique(RAbstractStringVector vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RStringVector doUnique(RAbstractStringVector vec, byte incomparables, byte fromLast, int nmax) {
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSet<String> set = new NonRecursiveHashSet<>(vec.getLength());
             String[] data = new String[vec.getLength()];
@@ -145,9 +146,7 @@ public abstract class Unique extends RBuiltinNode {
 
         public int[] toArray() {
             int[] newArray = new int[index];
-            for (int i = 0; i < index; i++) {
-                newArray[i] = backingArray[i];
-            }
+            System.arraycopy(backingArray, 0, newArray, 0, index);
             return newArray;
         }
     }
@@ -176,9 +175,7 @@ public abstract class Unique extends RBuiltinNode {
 
         public double[] toArray() {
             double[] newArray = new double[index];
-            for (int i = 0; i < index; i++) {
-                newArray[i] = backingArray[i];
-            }
+            System.arraycopy(backingArray, 0, newArray, 0, index);
             return newArray;
         }
     }
@@ -208,9 +205,7 @@ public abstract class Unique extends RBuiltinNode {
 
         public double[] toArray() {
             double[] newArray = new double[index];
-            for (int i = 0; i < index; i++) {
-                newArray[i] = backingArray[i];
-            }
+            System.arraycopy(backingArray, 0, newArray, 0, index);
             return newArray;
         }
     }
@@ -239,16 +234,14 @@ public abstract class Unique extends RBuiltinNode {
 
         public byte[] toArray() {
             byte[] newArray = new byte[index];
-            for (int i = 0; i < index; i++) {
-                newArray[i] = backingArray[i];
-            }
+            System.arraycopy(backingArray, 0, newArray, 0, index);
             return newArray;
         }
     }
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RIntVector doUnique(RAbstractIntVector vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RIntVector doUnique(RAbstractIntVector vec, byte incomparables, byte fromLast, int nmax) {
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSetInt set = new NonRecursiveHashSetInt();
             int[] data = new int[16];
@@ -277,7 +270,7 @@ public abstract class Unique extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization(guards = "lengthOne(list)")
-    protected RList doUniqueL1(RList list, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RList doUniqueL1(RList list, byte incomparables, byte fromLast, int nmax) {
         return (RList) list.copyDropAttributes();
     }
 
@@ -294,7 +287,7 @@ public abstract class Unique extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization(guards = "!lengthOne(list)")
     @TruffleBoundary
-    protected RList doUnique(RList list, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RList doUnique(RList list, byte incomparables, byte fromLast, int nmax) {
         /*
          * Brute force, as manual says: Using this for lists is potentially slow, especially if the
          * elements are not atomic vectors (see vector) or differ only in their attributes. In the
@@ -373,7 +366,7 @@ public abstract class Unique extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RDoubleVector doUnique(RAbstractDoubleVector vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RDoubleVector doUnique(RAbstractDoubleVector vec, byte incomparables, byte fromLast, int nmax) {
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSetDouble set = new NonRecursiveHashSetDouble(vec.getLength());
             double[] data = new double[vec.getLength()];
@@ -399,7 +392,7 @@ public abstract class Unique extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RLogicalVector doUnique(RAbstractLogicalVector vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RLogicalVector doUnique(RAbstractLogicalVector vec, byte incomparables, byte fromLast, int nmax) {
         ByteArray dataList = new ByteArray(vec.getLength());
         for (int i = 0; i < vec.getLength(); i++) {
             byte val = vec.getDataAt(i);
@@ -412,7 +405,7 @@ public abstract class Unique extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RComplexVector doUnique(RAbstractComplexVector vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RComplexVector doUnique(RAbstractComplexVector vec, byte incomparables, byte fromLast, int nmax) {
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSet<RComplex> set = new NonRecursiveHashSet<>(vec.getLength());
             double[] data = new double[vec.getLength() * 2];
@@ -439,7 +432,7 @@ public abstract class Unique extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RRawVector doUnique(RAbstractRawVector vec, RAbstractVector incomparables, byte fromLast, int nmax) {
+    protected RRawVector doUnique(RAbstractRawVector vec, byte incomparables, byte fromLast, int nmax) {
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSet<RRaw> set = new NonRecursiveHashSet<>(vec.getLength());
             byte[] data = new byte[vec.getLength()];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index b8d5a7b81f..033f63f94e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -23,8 +23,11 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notLogicalNA;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -95,14 +98,14 @@ public abstract class VApply extends RBuiltinNode {
     @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
     static {
+        // @formatter:off
         Casts casts = new Casts(VApply.class);
-        casts.arg("X").asVector();
+        casts.arg("X").mapNull(emptyList());
         casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION);
-        // casts.arg("FUN.VALUE").mapIf(anyValue(),
-        // chain(asVector(true)).with(mustBe(abstractVectorValue(), RError.SHOW_CALLER, true,
-        // RError.Message.MUST_BE_VECTOR, "FUN.VALUE")).end());
-        casts.arg("FUN.VALUE").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR, "FUN.VALUE").asVector(true).mustBe(abstractVectorValue());
-        casts.arg("USE.NAMES").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "USE.NAMES").mustBe(stringValue().not()).asLogicalVector().findFirst();
+        casts.arg("FUN.VALUE").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR, "FUN.VALUE").mustBe(abstractVectorValue()).asVector(true);
+        casts.arg("USE.NAMES").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "USE.NAMES").
+                mustBe(numericValue()).asLogicalVector().findFirst().mustBe(notLogicalNA()).map(toBoolean());
+        // @formatter:on
     }
 
     private Object castComplex(Object operand, boolean preserveAllAttr) {
@@ -146,13 +149,21 @@ public abstract class VApply extends RBuiltinNode {
     }
 
     @Specialization
-    protected Object vapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValue, byte useNames) {
-        RVector<?> result = delegateToLapply(frame, vec, fun, funValue, useNames);
-        // set here else it gets overridden by the iterator evaluation
-        return result;
+    protected Object vapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValue, boolean useNames) {
+        return delegateToLapply(frame, vec, fun, funValue, useNames);
+    }
+
+    @Specialization(guards = "isNotAbstractVector(obj)")
+    protected Object vapplyNonVector(VirtualFrame frame, Object obj, RFunction fun, RAbstractVector funValue, boolean useNames) {
+        // wrap the single value into a list and use normal vapply algorithm
+        return vapply(frame, RDataFactory.createList(new Object[]{obj}), fun, funValue, useNames);
+    }
+
+    static boolean isNotAbstractVector(Object obj) {
+        return !(obj instanceof RAbstractVector);
     }
 
-    private RVector<?> delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValueVec, byte useNames) {
+    private RVector<?> delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, RAbstractVector funValueVec, boolean useNames) {
         /*
          * The implementation is complicated by the existence of scalar length 1 vectors (e.g.
          * Integer) and concrete length 1 vectors (e.g. RIntVector), as either form can occur in
@@ -164,7 +175,7 @@ public abstract class VApply extends RBuiltinNode {
         RVector<?> vecMat = vec.materialize();
         Object[] applyResult = doApply.execute(frame, vecMat, fun);
 
-        RVector<?> result = null;
+        RVector<?> result;
         boolean applyResultZeroLength = applyResult.length == 0;
 
         naCheck.enable(true);
@@ -197,7 +208,7 @@ public abstract class VApply extends RBuiltinNode {
         }
 
         // TODO: handle names in case of matrices
-        if (useNamesProfile.profile(RRuntime.fromLogical(useNames))) {
+        if (useNamesProfile.profile(useNames)) {
             RStringVector names = getNamesNode.getNames(vecMat);
             RStringVector newNames = null;
             if (names != null) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
index 1a7797de13..2345f49d0f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
@@ -110,9 +110,9 @@ public class WhichFunctions {
             this.isMax = isMax;
         }
 
-        protected static Casts createCasts(Class<? extends WhichMinMax> extCls) {
+        static Casts createCasts(Class<? extends WhichMinMax> extCls) {
             Casts casts = new Casts(extCls);
-            casts.arg(0, "x").asDoubleVector(true, false, false);
+            casts.arg(0, "x").mustNotBeMissing().asDoubleVector(true, false, false);
             return casts;
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java
index 4f9d28cfb2..f0dcad3ee3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java
@@ -11,6 +11,10 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.foreign;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -20,7 +24,7 @@ public abstract class CairoProps extends RExternalBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(CairoProps.class);
-        casts.arg(0).asIntegerVector();
+        casts.arg(0).returnIf(nullValue().or(missingValue()), emptyIntegerVector()).asIntegerVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
index aeb884a611..9ccae9e8ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
@@ -11,6 +11,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.foreign;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -29,7 +31,7 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(Fft.class);
-        casts.arg(0).mustNotBeNull().asComplexVector(false, true, false);
+        casts.arg(0).mustNotBeMissing().mustBe(nullValue().not()).asComplexVector(false, true, false);
         casts.arg(1).mustNotBeNull().asLogicalVector().findFirst().map(Predef.toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
index 53cbadf9d4..3dda72b068 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.foreign;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
@@ -68,7 +69,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         // dec
         casts.arg(8).mustBe(stringValue()).asStringVector().findFirst().mustBe(Predef.length(1), RError.Message.GENERIC, "'dec' must be a single character");
         // quote
-        casts.arg(9).mustNotBeNull().asIntegerVector();
+        casts.arg(9).mustNotBeMissing().mustBe(nullValue().not()).asIntegerVector();
         // qmethod
         casts.arg(10).mustNotBeNull().asLogicalVector().findFirst().notNA().map(toBoolean());
     }
@@ -105,9 +106,6 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
                 }
 
                 for (int i = 0; i < nr; i++) {
-                    if (i % 1000 == 999) {
-                        // R_CheckUserInterrupt();
-                    }
                     if (!(rnames instanceof RNull)) {
                         con.writeString(encodeElement2((RAbstractStringVector) rnames, i, quoteRn, qmethod, cdec), false);
                         con.writeString(csep, false);
@@ -195,7 +193,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         if (!quote) {
             return p0;
         }
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append('"');
         for (int i = 0; i < p0.length(); i++) {
             char p = p0.charAt(i);
@@ -234,7 +232,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         } else if (o instanceof String) {
             String v = (String) o;
             return RRuntime.isNA(v) ? cna : encodeStringElement(v, quote, qmethod);
-        } else if (o instanceof Double) {
+        } else if (o instanceof RComplex) {
             RComplex v = (RComplex) o;
             return RRuntime.isNA(v) ? cna : ComplexVectorPrinter.encodeComplex(v);
         } else if (o instanceof RRaw) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java
index 80ff682034..67c223259e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
+import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts;
 import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -33,6 +34,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "{", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class BraceBuiltin extends RBuiltinNode {
+
+    static {
+        noCasts(BraceBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java
index 9512dd07b5..405853e771 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
+import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -33,6 +34,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "while", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class WhileBuiltin extends RBuiltinNode {
+    static {
+        noCasts(WhileBuiltin.class);
+    }
+
     @SuppressWarnings("unused")
     @Specialization
     protected Object doIt(Object x) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
index 5ced98be0f..15df4300f2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -108,4 +109,8 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg
     public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter) {
         return mustBe(argFilter, null, null, (Object[]) null);
     }
+
+    public <R extends T> CoercedPhaseBuilder<R, S> mustBe(Class<R> cls) {
+        return new CoercedPhaseBuilder<R, S>(pipelineBuilder(), elementClass).mustBe(Predef.instanceOf(cls));
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 85a79915a5..bd4161d20a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -333,6 +333,7 @@ public final class RError extends RuntimeException {
         CONN_XDR("cannot save XDR format to a text-mode connection"),
         ONLY_READ_BINARY_CONNECTION("can only read from a binary connection"),
         ONLY_WRITE_BINARY_CONNECTION("can only write to a binary connection"),
+        ONLY_WRITE_CHAR_OBJECTS("can only write character objects"),
         NOT_A_TEXT_CONNECTION("'con' is not a textConnection"),
         UNSEEKABLE_CONNECTION("'con' is not seekable"),
         MUST_BE_STRING_OR_CONNECTION("'%s' must be a character string or a connection"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
index 52144392a9..d85a2c5f4f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
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 cc6bb9e24d..f791916836 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
@@ -68526,6 +68526,10 @@ Error in vapply(c("foo", "bar"), function(x) FALSE, function() 42) :
 #{ vapply(c("hello", "goodbye", "up", "down"), function(x) x, c("a"), USE.NAMES = FALSE) }
 [1] "hello"   "goodbye" "up"      "down"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply#
+#{ vapply(c(1,2,3), 42, 1); }
+Error in match.fun(FUN) : '42' is not a function, character or symbol
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply#
 #{ vapply(c(10, 20, 30, 40), function(x) x/2, c(1)) }
 [1]  5 10 15 20
@@ -68550,6 +68554,15 @@ Error in vapply(c("foo", "bar"), function(x) FALSE, function() 42) :
 #{ vapply(c(TRUE, FALSE, TRUE), function(x) x, c(TRUE)) }
 [1]  TRUE FALSE  TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply#
+#{ vapply(quote(a), function(x) 42, 1); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapply#Output.IgnoreErrorContext#
+#{ vapply(quote(a), function(x) quote(b), quote(a)); }
+Error in vapply(quote(a), function(x) quote(b), quote(a)) :
+  'FUN.VALUE' must be a vector
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor#
 #{  vector("numeric", c(7, 42)) }
 Error in vector("numeric", c(7, 42)) : invalid 'length' argument
@@ -68934,6 +68947,18 @@ $visible
 #argv <- structure(list(data = structure(list(a = 1:5, b = 2:6,     c = 3:7), .Names = c('a', 'b', 'c'), row.names = c(NA, -5L),     class = 'data.frame')), .Names = 'data');do.call('within', argv)
 Error in eval(expr, envir, enclos) : argument is missing, with no default
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_writeChar.testwriteCharArgumentsValidation#
+#writeChar(42, 1)
+Error in writeChar(42, 1) : can only write character objects
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_writeChar.testwriteCharArgumentsValidation#
+#writeChar(NULL, 1)
+Error in writeChar(NULL, 1) : can only write character objects
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_writeChar.testwriteCharArgumentsValidation#
+#writeChar(list(), 1)
+Error in writeChar(list(), 1) : can only write character objects
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_writeLines.testwriteLines1#Ignored.SideEffects#
 #argv <- structure(list(text = ' \'  A  \'; \'B\' ;\'C\';\' D \';\'E \';  F  ;G  ',     con = 'foo'), .Names = c('text', 'con'));do.call('writeLines', argv)
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java
index 3bbd8e7428..931015c407 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java
@@ -42,6 +42,10 @@ public class TestBuiltin_vapply extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, c(TRUE), USE.NAMES=logical()) }");
         assertEval(Output.IgnoreErrorContext, "{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, c(TRUE), USE.NAMES=\"42\") }");
         assertEval("{ vapply(c(\"foo\", \"bar\"), function(x) FALSE, c(TRUE), USE.NAMES=42) }");
+
+        assertEval("{ vapply(quote(a), function(x) 42, 1); }");
+        assertEval(Output.IgnoreErrorContext, "{ vapply(quote(a), function(x) quote(b), quote(a)); }");
+        assertEval("{ vapply(c(1,2,3), 42, 1); }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java
new file mode 100644
index 0000000000..3f3cde5a17
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_writeChar.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+
+public class TestBuiltin_writeChar extends TestBase {
+    @Test
+    public void testwriteCharArgumentsValidation() {
+        assertEval("writeChar(NULL, 1)");
+        assertEval("writeChar(list(), 1)");
+        assertEval("writeChar(42, 1)");
+    }
+}
-- 
GitLab


From 2e567cdb7727c25d857410ab6b8166c7f212c1e6 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Feb 2017 16:05:09 +0100
Subject: [PATCH 046/402] implement deparsing or raw vectors

---
 .../oracle/truffle/r/runtime/RDeparse.java    | 29 ++++++++++++++-----
 .../truffle/r/test/ExpectedTestOutput.test    |  6 +++-
 .../r/test/builtins/TestBuiltin_deparse.java  |  2 ++
 3 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 40b677b713..c2591fed09 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -791,15 +792,25 @@ public class RDeparse {
                     return;
                 } else {
                     // TODO COMPAT?
-                    append("c(");
-                    for (int i = 0; i < len; i++) {
-                        Object element = vec.getDataAtAsObject(i);
-                        vecElement2buff(type, element, false);
-                        if (i < len - 1) {
-                            append(", ");
+                    if (type == SEXPTYPE.RAWSXP) {
+                        append("as.raw(c(");
+                        for (int i = 0; i < len; i++) {
+                            if (i > 0) {
+                                append(", ");
+                            }
+                            vecElement2buff(type, vec.getDataAtAsObject(i), false);
+                        }
+                        append("))");
+                    } else {
+                        append("c(");
+                        for (int i = 0; i < len; i++) {
+                            if (i > 0) {
+                                append(", ");
+                            }
+                            vecElement2buff(type, vec.getDataAtAsObject(i), false);
                         }
+                        append(')');
                     }
-                    append(')');
                 }
             }
         }
@@ -858,6 +869,10 @@ public class RDeparse {
                         append(RContext.getRRuntimeASTAccess().encodeComplex(c));
                     }
                     break;
+                case RAWSXP:
+                    RRaw r = (RRaw) element;
+                    append(String.format("0x%02x", r.getValue()));
+                    break;
                 default:
                     throw RInternalError.shouldNotReachHere("unexpected SEXPTYPE: " + type);
             }
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 f30f60d55a..3329251470 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
@@ -16706,6 +16706,10 @@ Error in print(x, y) :
 #deparse(quote(cat(c(T, F))))
 [1] "cat(c(T, F))"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#
+#e <- quote(a <- 1); e[[3]] <- as.raw(c(1,6,9,254)); e
+a <- as.raw(c(0x01, 0x06, 0x09, 0xfe))
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#
 #unserialize(serialize(quote(!(a <- TRUE)), NULL))
 !(a <- TRUE)
@@ -19327,7 +19331,7 @@ Error in (function (x)  : object 'y' not found
 #argv <- list();do.call('double', argv)
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dput.testdput#Output.IgnoreWhitespace#
 #x <- structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor'), C = structure(c(1L, 1L), .Label = c('G', 'D'), class = 'factor')), .Names = c('A', 'B', 'C'), row.names = 1:2, class = 'data.frame'); dput(x)
 structure(list(A = c(1L, 1L), B = structure(c(1L, 1L), .Label = c("G",
 "D"), class = "factor"), C = structure(c(1L, 1L), .Label = c("G",
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
index c06c60fb9a..5c62b28cce 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
@@ -311,6 +311,8 @@ public class TestBuiltin_deparse extends TestBase {
         assertEval("{ x<-c(a=42, b=7); deparse(x) }");
 
         assertEval("deparse(quote(1/0))");
+
+        assertEval("e <- quote(a <- 1); e[[3]] <- as.raw(c(1,6,9,254)); e");
     }
 
     @Test
-- 
GitLab


From 1a9d2899598f0d97fd64a330db6697b956b721e9 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Thu, 23 Feb 2017 19:32:53 +0100
Subject: [PATCH 047/402] Cast pipeline related issues fixed in a batch of
 builtins

---
 .../truffle/r/library/grid/GridFunctions.java |   7 +
 .../truffle/r/library/stats/BinDist.java      |   7 +-
 .../oracle/truffle/r/library/stats/Cdist.java |  20 ++-
 .../truffle/r/library/stats/Covcor.java       |   5 +-
 .../truffle/r/library/stats/Cutree.java       |   7 +-
 .../truffle/r/library/stats/DoubleCentre.java |   6 +-
 .../r/library/stats/RMultinomNode.java        |   5 +-
 .../r/library/stats/RandFunctionsNodes.java   |  14 +-
 .../r/library/stats/SplineFunctions.java      |   4 +-
 .../r/library/stats/StatsFunctionsNodes.java  |  10 +-
 .../casts/fluent/HeadPhaseBuilder.java        |   2 +-
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../truffle/r/test/ExpectedTestOutput.test    |  53 +++++++
 .../test/builtins/TestBuiltin_SplineCoef.java |  40 +++++
 .../r/test/builtins/TestBuiltin_rhyper.java   |  41 +++++
 .../test/builtins/TestBuiltin_rmultinom.java  |  41 +++++
 documentation/dev/casts.md                    | 143 ++++++++++--------
 17 files changed, 315 insertions(+), 93 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
index 6623a2c7ca..35dc425469 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
@@ -17,7 +17,9 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.stats.Cdist;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -36,6 +38,11 @@ public class GridFunctions {
     public abstract static class InitGrid extends RExternalBuiltinNode.Arg1 {
         @Child GridRFFI.InitGridNode initGridNode = RFFIFactory.getRFFI().getGridRFFI().createInitGridNode();
 
+        static {
+            Casts casts = new Casts(InitGrid.class);
+            casts.arg(0).mustBe(REnvironment.class);
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object initGrid(REnvironment gridEvalEnv) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
index a5b037c384..fa604b7662 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
@@ -15,6 +15,9 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
 import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
@@ -39,8 +42,8 @@ public abstract class BinDist extends RExternalBuiltinNode.Arg5 {
 
     static {
         Casts casts = new Casts(BinDist.class);
-        casts.arg(0).asDoubleVector();
-        casts.arg(1).asDoubleVector();
+        casts.arg(0).mustBe(missingValue().not()).returnIf(nullValue(), emptyDoubleVector()).asDoubleVector();
+        casts.arg(1).mustBe(missingValue().not()).returnIf(nullValue(), emptyDoubleVector()).asDoubleVector();
         casts.arg(2).asDoubleVector().findFirst();
         casts.arg(3).asDoubleVector().findFirst();
         casts.arg(4).asIntegerVector().findFirst().mustBe(gt0().and(intNA().not()), NO_CALLER, Message.INVALID_ARGUMENT, "n");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
index be4422e729..a06533fff0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
@@ -12,6 +12,8 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.runtime.nmath.MathConstants.DBL_MIN;
 
@@ -39,7 +41,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(Cdist.class);
-        casts.arg(0).asDoubleVector();
+        casts.arg(0).mustBe(nullValue().not(), RError.Message.VECTOR_IS_TOO_LARGE).mustBe(missingValue().not()).asDoubleVector();
         casts.arg(1).asIntegerVector().findFirst();
         casts.arg(2).mustBe(instanceOf(RList.class));
         casts.arg(3).asDoubleVector().findFirst();
@@ -61,13 +63,15 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 {
         DynamicObject resultAttrs = result.initAttributes();
 
         RStringVector names = (RStringVector) getNamesAttrNode.execute(list);
-        for (int i = 0; i < names.getLength(); i++) {
-            String name = names.getDataAt(i);
-            Object listValue = list.getDataAt(i);
-            if (name.equals(RRuntime.CLASS_ATTR_KEY)) {
-                setClassAttrNode.execute(result, listValue instanceof RStringVector ? (RStringVector) listValue : RDataFactory.createStringVectorFromScalar((String) listValue));
-            } else {
-                setAttrNode.execute(resultAttrs, name, listValue);
+        if (names != null) {
+            for (int i = 0; i < names.getLength(); i++) {
+                String name = names.getDataAt(i);
+                Object listValue = list.getDataAt(i);
+                if (name.equals(RRuntime.CLASS_ATTR_KEY)) {
+                    setClassAttrNode.execute(result, listValue instanceof RStringVector ? (RStringVector) listValue : RDataFactory.createStringVectorFromScalar((String) listValue));
+                } else {
+                    setAttrNode.execute(resultAttrs, name, listValue);
+                }
             }
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index 05fc0538c7..011ee2add3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
@@ -48,8 +49,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(Covcor.class);
-        casts.arg(0).mustNotBeNull(SHOW_CALLER, Message.IS_NULL, "x").asDoubleVector();
-        casts.arg(1).asDoubleVector();
+        casts.arg(0).mustNotBeMissing().mustBe(nullValue().not(), SHOW_CALLER, Message.IS_NULL, "x").asDoubleVector();
+        casts.arg(1).mustNotBeMissing().asDoubleVector();
         casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), Message.NYI, "covcor: other method than 4 not implemented.");
         casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java
index a2de828f38..d4f616e70c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java
@@ -10,6 +10,9 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
+
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
@@ -24,8 +27,8 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(Cutree.class);
-        casts.arg(0).asIntegerVector();
-        casts.arg(1).asIntegerVector();
+        casts.arg(0).mustNotBeMissing().mapIf(nullValue(), emptyIntegerVector()).asIntegerVector();
+        casts.arg(1).mustNotBeMissing().mapIf(nullValue(), emptyIntegerVector()).asIntegerVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
index 0eb3928748..34bfd0b02d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
@@ -10,10 +10,14 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
@@ -21,7 +25,7 @@ public abstract class DoubleCentre extends RExternalBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(DoubleCentre.class);
-        casts.arg(0).asDoubleVector();
+        casts.arg(0).mustBe(missingValue().not()).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "REAL()", "numeric", "NULL").asDoubleVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
index c1ea604e1f..dedf931e57 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
@@ -12,6 +12,9 @@
  */
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA;
 import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.NA_IN_PROB_VECTOR;
@@ -52,7 +55,7 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 {
         Casts casts = new Casts(RMultinomNode.class);
         casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_FIRST_ARGUMENT_NAME, "n");
         casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_SECOND_ARGUMENT_NAME, "size");
-        casts.arg(2).asDoubleVector();
+        casts.arg(2).mustBe(missingValue().not(), SHOW_CALLER, Message.ARGUMENT_MISSING, "prob").mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index d365281f27..1a5d082b10 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -13,6 +13,8 @@
 
 package com.oracle.truffle.r.library.stats;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_UNNAMED_ARGUMENTS;
@@ -260,9 +262,9 @@ public final class RandFunctionsNodes {
         static {
             Casts casts = new Casts(RandFunction3Node.class);
             ConvertToLength.addLengthCast(casts);
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asDoubleVector();
-            casts.arg(3).asDoubleVector();
+            casts.arg(1).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
+            casts.arg(2).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector();
+            casts.arg(3).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "c").asDoubleVector();
         }
 
         @Specialization
@@ -290,8 +292,8 @@ public final class RandFunctionsNodes {
         static {
             Casts casts = new Casts(RandFunction2Node.class);
             ConvertToLength.addLengthCast(casts);
-            casts.arg(1).asDoubleVector();
-            casts.arg(2).asDoubleVector();
+            casts.arg(1).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
+            casts.arg(2).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector();
         }
 
         @Specialization
@@ -319,7 +321,7 @@ public final class RandFunctionsNodes {
         static {
             Casts casts = new Casts(RandFunction1Node.class);
             ConvertToLength.addLengthCast(casts);
-            casts.arg(1).asDoubleVector();
+            casts.arg(1).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
index ac97fefd9b..3a33af53fc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
@@ -50,8 +50,8 @@ public class SplineFunctions {
                             chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).end(),
                             chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).with(
                                             Predef.shouldBe(integerValue(), NO_CALLER, NA_INTRODUCED_COERCION)).end());
-            casts.arg(1).allowMissing().asDoubleVector();
-            casts.arg(2).allowMissing().asDoubleVector();
+            casts.arg(1).mustNotBeMissing().asDoubleVector();
+            casts.arg(2).mustNotBeMissing().asDoubleVector();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
index e3d7bba69b..9798af5abb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
@@ -13,6 +13,10 @@
 package com.oracle.truffle.r.library.stats;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -359,7 +363,9 @@ public final class StatsFunctionsNodes {
 
         static {
             Casts casts = new Casts(Approx.class);
-            casts.arg(2).asDoubleVector();
+            casts.arg(0).mustBe(instanceOf(RDoubleVector.class));
+            casts.arg(1).mustBe(instanceOf(RDoubleVector.class));
+            casts.arg(2).mustBe(missingValue().not()).mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
             casts.arg(3).asIntegerVector().findFirst();
             casts.arg(4).asDoubleVector().findFirst();
             casts.arg(5).asDoubleVector().findFirst();
@@ -367,7 +373,7 @@ public final class StatsFunctionsNodes {
         }
 
         @Specialization
-        protected RDoubleVector approx(RDoubleVector x, RDoubleVector y, RDoubleVector v, int method, double yl, double yr, double f) {
+        protected RDoubleVector approx(RDoubleVector x, RDoubleVector y, RAbstractDoubleVector v, int method, double yl, double yr, double f) {
             int nx = x.getLength();
             int nout = v.getLength();
             double[] yout = new double[nout];
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
index 6d0d72eb97..54e31bfbf8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
@@ -56,7 +56,7 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) {
+    public <S extends T, R> HeadPhaseBuilder<T> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, true);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 7cb1afe159..9ec55327d1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -792,7 +792,8 @@ public final class RError extends RuntimeException {
         UNIMPLEMENTED_TYPE_IN_R("type \"%s\" unimplemented in R"),
         NOT_AN_OUTPUT_RAW_CONNECTION("'con' is not an output rawConnection"),
         NOT_A_RAW_CONNECTION("'con' is not a rawConnection"),
-        SEEK_OUTSITE_RAW_CONNECTION("attempt to seek outside the range of the raw connection");
+        SEEK_OUTSITE_RAW_CONNECTION("attempt to seek outside the range of the raw connection"),
+        VECTOR_IS_TOO_LARGE("vector is too large");
 
         public final String message;
         final boolean hasArgs;
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 9a22b902f0..735f194785 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
@@ -1366,6 +1366,34 @@ Error in Recall(10) : 'Recall' called from outside a closure
 #argv <- structure(list(f = function(f, ...) f(...), x = list(.Primitive('log'),     .Primitive('exp'), .Primitive('acos'), .Primitive('cos')),     init = 0, right = TRUE), .Names = c('f', 'x', 'init', 'right'));do.call('Reduce', argv)
 [1] 0
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_SplineCoef.testNull#
+#.Call(stats:::C_SplineCoef, 0, 0, NULL)
+Error: inputs of different lengths
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_SplineCoef.testSimple#
+#.Call(stats:::C_SplineCoef, 0, 0, 0)
+$method
+[1] 0
+
+$n
+[1] 1
+
+$x
+[1] 0
+
+$y
+[1] 0
+
+$b
+[1] 0
+
+$c
+[1] 0
+
+$d
+[1] 0
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syschmod.testSyschmod1#Ignored.SideEffects#
 #argv <- list(character(0), structure(integer(0), class = 'octmode'), TRUE); .Internal(Sys.chmod(argv[[1]], argv[[2]], argv[[3]]))
 
@@ -44522,6 +44550,18 @@ logical(0)
 #argv <- structure(list(x = c('#FF0000FF', '#FFFF00FF', '#00FF00FF')),     .Names = 'x');do.call('rev', argv)
 [1] "#00FF00FF" "#FFFF00FF" "#FF0000FF"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rhyper.testNullAndMissing#
+#rmultinom(0,0,0)
+Error in rmultinom(0, 0, 0) : no positive probabilities
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rhyper.testNullAndMissing#
+#rmultinom(0,0,0,NULL)
+Error in rmultinom(0, 0, 0, NULL) : unused argument (NULL)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rhyper.testSimple#
+#rhyper(0,0,0,0)
+integer(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rm.basicTests#
 # e <- new.env(); e$a <- 42; rm(list='a', envir=e); e$a
 NULL
@@ -44554,6 +44594,19 @@ Error in rm(tmp, envir = NULL) : use of NULL environment is defunct
 #tmp <- 42; rm(tmp, inherits='asd')
 Error in rm(tmp, inherits = "asd") : invalid 'inherits' argument
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rmultinom.testNullAndMissing#
+#rmultinom(1, 1)
+Error in rmultinom(1, 1) : argument "prob" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rmultinom.testNullAndMissing#
+#rmultinom(1, 1, NULL)
+Error in rmultinom(1, 1, NULL) : no positive probabilities
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rmultinom.testSimple#
+#rmultinom(1,1,1)
+     [,1]
+[1,]    1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_round.testRound#
 #{ round(-1.5) }
 [1] -2
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java
new file mode 100644
index 0000000000..07f495341c
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_SplineCoef.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestBuiltin_SplineCoef extends TestBase {
+
+    @Test
+    public void testSimple() {
+        assertEval(".Call(stats:::C_SplineCoef, 0, 0, 0)");
+    }
+
+    @Test
+    public void testNull() {
+        assertEval(".Call(stats:::C_SplineCoef, 0, 0, NULL)");
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java
new file mode 100644
index 0000000000..dbe91a4bc2
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rhyper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestBuiltin_rhyper extends TestBase {
+
+    @Test
+    public void testSimple() {
+        assertEval("rhyper(0,0,0,0)");
+    }
+
+    @Test
+    public void testNullAndMissing() {
+        assertEval("rmultinom(0,0,0,NULL)");
+        assertEval("rmultinom(0,0,0)");
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java
new file mode 100644
index 0000000000..caa8e9c018
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rmultinom.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestBuiltin_rmultinom extends TestBase {
+
+    @Test
+    public void testSimple() {
+        assertEval("rmultinom(1,1,1)");
+    }
+
+    @Test
+    public void testNullAndMissing() {
+        assertEval("rmultinom(1, 1, NULL)");
+        assertEval("rmultinom(1, 1)");
+    }
+}
diff --git a/documentation/dev/casts.md b/documentation/dev/casts.md
index a343943853..0ec57e6e9f 100644
--- a/documentation/dev/casts.md
+++ b/documentation/dev/casts.md
@@ -1,8 +1,8 @@
 ## Introduction
 
-Cast Pipelines (CP) are used to convert, validate and analyse input arguments of FastR builtins. The aim is to make the code in builtin specializations cleaner by relieving them from the burden of repeated argument handling that often leads to duplicate boilerplate code. Ideally, all argument handling code should be concentrated in a single method in a builtin. However, in certain situations, e.g. when a validation code evaluates more than one argument, the validation code cannot be moved to that single method.
+Cast Pipelines (CP) are used to convert, validate and analyze input arguments of FastR builtins. The aim is to make the code in builtin specializations cleaner by relieving them from the burden of repeated argument handling that often leads to duplicate boilerplate code. Besides that, the declarative nature of CP allows for static analysis of pipelines, which is used to diagnose builtins by a special tool (mx rbdiag).
 
-CP provides an API through which a _pipeline_ can be constructed declaratively for each builtin argument. This pipeline consists of one or more steps representing specific operations with the given argument. Because of the declarative character of the argument processing pipelines it is possible to retrieve additional information from the pipelines, which may be further used in tests or code analysis. For instance, each pipeline provides a set of output types, which may be used for coverage analysis of the builtin specializations, i.e. to check if no specialization is missing or unused. Also, in many cases it is possible to determine specific argument values from pipelines, such as default values, limit values of value intervals, and allowed or forbidden values (i.e. corner-case argument values). These specific values may be collected as argument samples and used to create automated tests of builtins. The argument samples are naturally divided into the positive and negative sample sets. The positive samples can be used to test the builtin's functionality and compare the result with the result of the builtin's GnuR counterpart. On the the other hand, the negative samples, which are assumed to cause an error in the FastR builtin, can be used to determine if the GnuR version fails too and produces the same error; if not, the pipeline must be redesigned to reflect the original.
+CP provides an API through which a _pipeline_ can be constructed declaratively for each builtin argument. This pipeline consists of one or more steps representing specific operations with the given argument. Because of the declarative character of the argument processing pipelines it is possible to retrieve additional information from the pipelines, which may be further used in tests or code analysis. For instance, each pipeline provides a set of output types, which may be used for coverage analysis of the builtin specializations, i.e. to check if no specialization is missing or unused. Also, in many cases it is possible to determine specific argument values from pipelines, such as default values, limit values of value intervals, and allowed or forbidden values (a.k.a. corner-case argument values). These specific values may be collected as argument samples and used to create automated tests of builtins (a.k.a. chimney-sweeping). The argument samples are naturally divided into the positive and negative sample sets. The positive samples can be used to test the builtin's functionality and compare the result with the result of the builtin's GnuR counterpart. On the the other hand, the negative samples, which are assumed to cause an error in the FastR builtin, can be used to determine if the GnuR version fails too and produces the same error; if not, the pipeline must be redesigned to reflect the original.
 
 The following sections deal with the description of the CP API and with some implementation details.
 
@@ -10,13 +10,15 @@ The following sections deal with the description of the CP API and with some imp
 
 ### Basics: usage in builtins
 
-CP API is an extension of the `CastBuilder` class, whose instance is passed as the argument of the `createCasts` method that can be overridden in a builtin class to define custom argument conversions for the builtin. The body of the `createCasts` method is the place where the cast pipelines are constructed for every argument of the builtin requiring some conversion or validation, as shown in the following listing.
+CP API is available through the `NodeWithArgumentCasts.Casts` class. For every builtin there is one instance of that class instantiated in the static block of the builtin class. The static block is also the place where the cast pipelines are constructed for every argument of the builtin requiring some conversion or validation, as shown in the following listing:
 
 ```java
-    @Override
-    protected void createCasts(CastBuilder casts) {
+    // in MyBuiltin class
+    static {
+    	Casts casts = new Casts(MyBuiltin.class);
+    	
         casts.arg("X").mustBe(numericValue(), RError.Message.X_NUMERIC);
-
+        
         casts.arg("m").asIntegerVector().
                         findFirst().
                         notNA();
@@ -31,15 +33,24 @@ CP API is an extension of the `CastBuilder` class, whose instance is passed as t
     }
 ```
 
-The CP API part for the pipeline construction is designed in the fluent-builder style. A new pipeline for an argument is initialized by calling the `arg` method on the `CastBuilder` instance. The `arg` method accepts either the index of the argument or the name of the argument, while the latter case is preffered. Following the `arg` method is a series of steps, each inserting a special Truffle node (`CastNode`) into the cast pipeline of the argument. The flow of a pipeline can be divided into four phases: _pre-initial_, _initial_, _coerced_ and _head_, while the last three are optional and each phase may consist of zero or more steps.
+In case the builtin does not declare any cast pipeline from any reason, it should declare this fact as follows:
+
+```java
+    // in MyBuiltin class
+	static {
+		Casts.noCasts(MyBuiltin.class);
+	}
+```
+
+The CP API for the pipeline construction is designed in the fluent-builder style. A new pipeline for an argument is initialized by calling the `arg` method on the `Casts` instance. The `arg` method accepts either the index of the argument or the name of the argument, while the latter case is preffered. Following the `arg` method is a series of steps, in which each step inserts, behind the scenes, a special Truffle nodes (`CastNode`) into the cast pipeline. The flow of a pipeline can be divided into four phases: _pre-initial_, _initial_, _coerced_ and _head_, while the last three are optional and each phase may consist of zero or more steps.
 
-In the **pre-initial** phase one can configure the overall behavior of the pipeline. Currently, only the default handling of `RNull` and `RMissing` values can be overridden (the default behavior is explained below). The pipeline can be configured using `PreinitialPhaseBuilder.conf(Consumer)` or any other method of the `PreinitialPhaseBuilder` class, e.g. `PreinitialPhaseBuilder.allowNull()`.
+In the **pre-initial** phase, in addition to the **initial** phase, one can configure the overall properties and behaviour of the pipeline (see `PipelineConfigBuilder`). The pipeline can be configured using the `conf(Consumer)` step (declared in `PreinitialPhaseBuilder`).
 
-An argument enters the **initial** phase as a generic object, which may be subjected to various assertions and conversions. The argument may, but may not, exit the initial phase as an instance of a specific type. The pipeline declared in the following listing specifies the default error of the pipeline and inserts one assertion node checking whether the argument is a non-null string. The argument exits this pipeline as a string represented by the `RAbstractStringVector` class. If any of the two conditions fails, the default error is raised.
+The **initial** and **pre-initial** phases handle the input argument as a generic object, which may be subjected to various assertions and conversions. The argument may, but may not, exit the initial phase as an instance of a specific type. The pipeline declared in the following listing specifies the default error of the pipeline and inserts one assertion node checking whether the argument is a non-null string. The argument exits this pipeline as a string represented by the `RAbstractStringVector` class. If any of the two conditions fails, the default error is raised.
 
 ```java
   casts.arg("m").defaultError(RError.Message.MUST_BE_STRING, "msg1").
-  mustBe(notNull().and(stringValue()));
+  mustBe(nullValue().not().and(stringValue()));
 ```
 
 The argument enters the **coerced** phase after having been processed by a node inserted by one of the `as_X_Vector` pipeline steps, where `X` is the type of the resulting vector. The input type of the argument corresponds to the used `as_X_Vector` step. The following example illustrates a pipeline, where the initial phase consists of one step (`asIntegerVector`) and the coerced phase has no step.
@@ -58,15 +69,15 @@ The next listing shows a pipeline having two steps belonging to the initial phas
   findFirst();
 ```
 
-The `singleElement()` condition requires that the string vector contain exactly one element. The `findFirst()` step retrieves the first element (the head) while exiting the coerced phase and entering the head phase.
+The `singleElement()` condition requires that the string vector contain exactly one element. The `findFirst()` step retrieves the first element of the vector argument (the head) while exiting the coerced phase and entering the head phase.
 
-In the **head** phase, the argument value corresponds to the first element of the vector processed in the preceding coerced phase and may be handled basically by the same steps as in the initial phase, except the `as_X_Vector` steps. The head phase in the following example consists of two steps - `mustBe(notLogicalNA())` and `map(toBoolean())` - where the former asserts that the head of the logical vector argument must not be `NA` and the latter converts the logical value from the vector's head to the corresponding `boolean` value. The `findFirst` step in the coerced phase picks the head of the vector or returns the `RRuntime.LOGICAL_FALSE` in case the vector is empty.
+In the **head** phase, the argument value corresponds to the first element of the vector processed in the preceding coerced phase and may be handled basically by the same steps as in the initial phase, except the `as_X_Vector` steps. The head phase in the following example consists of two steps - `mustBe(logicalNA().not())` and `map(toBoolean())` - where the former asserts that the head of the logical vector argument must not be `NA` and the latter converts the logical value from the vector's head to the corresponding `boolean` value. The `findFirst` step in the coerced phase picks the head of the vector or returns the `RRuntime.LOGICAL_FALSE` in case the vector is empty.
 
 ```java
   casts.arg("na.encode").
   asLogicalVector().
   findFirst(RRuntime.LOGICAL_FALSE).
-  mustBe(notLogicalNA()).
+  mustBe(logicalNA().not()).
   map(toBoolean());
 ```
 
@@ -80,6 +91,14 @@ import com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBu
 CastNode myCastNode = newCastBuilder().asStringVector().findFirst("default").buildCastNode();
 ```
 
+### Class `Predef`
+
+The `CastBuilder.Predef` class defines the `cast pipelines` DSL. By importing statically its content, all language elements, such as filters and mappers, become available.
+
+```java
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*
+```
+
 ### Steps
 
 The following subsections are dealing with the specific types of pipeline steps.
@@ -92,16 +111,12 @@ There are two steps that actually insert no node into the pipeline. The `default
 
 There are two modal steps - `mustBe` and `shouldBe` - that establish assertions on the argument value. If the assertion fails, the former raises an error, while the latter outputs a warning. If no message is specified, the default one is used. These steps may be used in all phases.
 
-The assertion conditions are passed as the first argument of those steps and must match the context argument type, which is `java.lang.Object` initially and may be made more specific further in the pipeline by certain steps, among which is also the `mustBe` one. The conditions are objects implementing the `ArgumentFilter<T, R extends T>` interface. Under normal circumstances, the user is not supposed to implement custom conditions. Instead, there is a set of predefined conditions in the `CastBuilder.Predef` class, which should contain all conditions occuring in the original GnuR code, although some may be missing.
-
-```java
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*
-```
+The assertion conditions are passed as the first argument of those steps and must match the context argument type, which is `java.lang.Object` initially and may be made more specific further in the pipeline by certain steps, among which is also the `mustBe` one. The conditions are objects implementing the `ArgumentFilter<T, R extends T>` interface. Under normal circumstances, the user is not supposed to implement custom conditions. Instead, there is a set of predefined conditions in the `CastBuilder.Predef` class, which should contain all conditions occuring in the original GnuR code, although some may be missing, while others may be added.
 
 The `ArgumentFilter<T, R extends T>` contains the logical operators `and`, `or` and `not`, which allows constructing more complex assertions from the elementary building blocks, as shown in the following listing. The expression asserts that the argument value must be a non-null string or logical value.
 
 ```java
-casts.arg("msg1").mustBe(notNull().and(stringValue().or(logicalValue())));
+casts.arg("msg1").mustBe(nullValue().not().and(stringValue().or(logicalValue())));
 ```
 
 The `mustBe` step changes the context argument type of the argument in the following steps accordingly to the used filter expression. For example, in the following pipeline the `mustBe` step asserts that the argument must be a vector. This assertion narrows the context argument type in the following steps to `RAbstractVector`. Therefore, the conditions requiring a vector as the input value, such as `size`, may be used in the subsequent `shouldBe` step.
@@ -112,18 +127,30 @@ casts.arg("x").mustBe(abstractVectorValue()).shouldBe(size(2));
 
 #### Mapping Steps
 
-The mapping steps allow converting the argument from one type to another using the so-called mappers passed as the argument of those steps. There are two mapping steps: `map` and `mapIf`. The former always converts the argument using the mapper object passed as the first argument, while the latter converts the argument only if the condition passed as the first argument is `true`. The mapper object implements the `ArgumentMapper<S, R>` interface, nevertheless, just as in the case of the filter conditions, the user is not expected to implement custom ones, since the `CastBuilder.Predef` class should contain all necessary mappers.
+The mapping steps allow converting the argument from one type to another using the so-called mappers passed as the argument of those steps. There are three mapping steps: `map`, `mapIf` and `returnIf`. The first one always converts the argument using the mapper object passed as the first argument, while the second converts the argument only if the condition passed as the first argument is `true`. Both converted and non-converted arguments then proceed to the next step in the pipeline. The third one works as the second one, except that the converted value exits the pipeline without further processing.
+Both `mapIf` and `returnIf` allow specifying the false mapping branch too. Interestingly, the `returnIf` can be specified with no mapping branch at all, which results in exiting the pipeline with the input argument if it matches the filter condition (it is equivalent to the true branch being the identity mapper).
+The following pipeling returns NULL immediately without propagating it further in the pipeline:
+
+```java
+casts.arg("x").returnIf(nullValue()).asIntegerVector().findFirst();
+```
+
+The mapper object implements the `ArgumentMapper<S, R>` interface, nevertheless, just as in the case of the filter conditions, the user is not expected to implement custom ones, since the `CastBuilder.Predef` class should contain all necessary mappers.
 
 The mapping steps may be used in all phases except the coerced phase, for the time being.
 
 The signatures of the mapping steps are:
 
 ```java
-map(ArgumentMapper<T, S> mapFn)
-mapIf(ArgumentFilter<? super T, ? extends S> argFilter, ArgumentMapper<S, R> mapFn)
+map(Mapper<T, S> mapFn)
+mapIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper)
+mapIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<S, R> falseBranchMapper)
+returnIf(Filter<? super T, ? extends S> argFilter)
+returnIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper)
+returnIf(Filter<? super T, ? extends S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<S, R> falseBranchMapper)
 ```
 
-A usage of the unconditional is illustrated in the following listing, where a logical value is mapped to a boolean value using the `toBoolean()` mapper. Since the unconditional mapping changes the context argument type according to the output type of the used mapper, it is possible to append the `shouldBe` modal step with the `trueValue()` filter requiring a boolean value on its input.
+A usage of the unconditional map step is illustrated in the following listing, where a logical value is mapped to a boolean value using the `toBoolean()` mapper. Since the unconditional mapping changes the context argument type according to the output type of the used mapper, it is possible to append the `shouldBe` modal step with the `trueValue()` filter requiring a boolean value on its input.
 
 ```java
   casts.arg("na.rm").
@@ -133,7 +160,7 @@ A usage of the unconditional is illustrated in the following listing, where a lo
   shouldBe(trueValue());
 ```
 
-In the following pipeline **only** null values are converted to the empty string in the initial phase. In contrast to the unconditional mapping, the conditional mapping does not change the context type.
+In the following pipeline **only** null values are converted to the empty string in the initial phase. In contrast to the unconditional mapping, the conditional mapping reduces the context type to `Object`.
 
 ```java
 casts.arg("quote").mapIf(nullValue(), constant(""));
@@ -143,11 +170,13 @@ casts.arg("quote").mapIf(nullValue(), constant(""));
 
 The vector coercion steps coerce the input argument value to the specified vector type. These steps can be used in the initial phase only. There are the following steps available:
 
-*   `asIntegerVector()`: coerces the input value to `RAbstractIntVector`
-*   `asDoubleVector()`: coerces the input value to `RAbstractDoubleVector`
-*   `asLogicalVector()`: coerces the input value to `RAbstractLogicalVector`
-*   `asStringVector()`: coerces the input value to `RAbstractStringVector`
-*   `asVector()`: coerces the input value to `RAbstractVector`
+*   `asIntegerVector()`: coerces the input value to `RAbstractIntVector` (see `CastIntegerNode`)
+*   `asDoubleVector()`: coerces the input value to `RAbstractDoubleVector` (see `CastDoubleNode`)
+*   `asLogicalVector()`: coerces the input value to `RAbstractLogicalVector` (see `CastLogicalNode`)
+*   `asStringVector()`: coerces the input value to `RAbstractStringVector` (see `CastStringNode`)
+*   `asComplexVector()`: coerces the input value to `RAbstractComplexVector` (see `CastComplexNode`)
+*   `asRawVector()`: coerces the input value to `RAbstractRawVector` (see `CastRawNode`)
+*   `asVector()`: coerces the input value to `RAbstractVector` (see `CastToVectorNode`)
 
 All these steps terminate the initial phase and start the coerced phase.
 
@@ -162,9 +191,10 @@ findFirst()
 findFirst(RError.Message message, Object... messageArgs)
 <E>findFirst(E defaultValue)
 <E>findFirst(E defaultValue, RError.Message message, Object... messageArgs)
+findFirstOrNull()
 ```
 
-The first variant raises the default error of the pipeline as long as the vector is empty, the second variant throws the error specified in its arguments, the third one returns the default value instead of raising an error and the fourth one returns the default value and prints the warning specified in its arguments.
+The first variant raises the default error of the pipeline as long as the vector is empty, the second variant throws the error specified in its arguments, the third one returns the default value instead of raising an error and the fourth one returns the default value and prints the warning specified in its arguments. The fifth one returns NULL if the vector argument is empty.
 
 #### notNA
 
@@ -177,20 +207,20 @@ notNA(T naReplacement)
 notNA(T naReplacement, RError.Message message, Object... messageArgs)
 ```
 
-Analogously to the findFirst step, the no-arg version throws the default error if the argument value is NA, while the second version throws the specified error. The next two versions return the `naReplacement` value, instead of raising an exception, while the last version prints the specified warning.
+Analogously to the findFirst step, the no-arg version throws the default error if the argument value is an NA, while the second version throws the specified error. The next two versions return the `naReplacement` value, instead of raising an exception, while the last version prints the specified warning.
 
 The notNA step does not change the context argument type.
 
 ### Handling of RNull and RMissing values
 
-By default, `RNull` and `RMissing` argument values are sent to the pipeline. While most of the pipeline cast nodes ignore those values and let them pass through, there are some nodes that may perform some transformation of those values. For example, the `FindFirstNode` node replaces both `RNull` and `RMissing` by the replacement values specified in the corresponding `findFirst(repl)` pipeline step. Also the `CastToVectorNode` coercion node replaces those values by an empty list provided that the `isPreserveNonVector` flag is set.
+By default, `RNull` and `RMissing` argument values __are sent to the pipeline__. While most of the pipeline cast nodes ignore those values and let them pass through, there are some nodes that may perform some transformation of those values. For example, the `FindFirstNode` node replaces both `RNull` and `RMissing` by the replacement values specified in the corresponding `findFirst(repl)` pipeline step. Also the `CastToVectorNode` coercion node replaces those values by an empty list provided that the `isPreserveNonVector` flag is set  (i.e. `asVector(true)`) .
 
 The following list summarizes the behavior of a couple of pipeline steps with regard to the special values:
 
-*   `as<TYPE>()` coercions: RNull/RMissing passing through
+*   `as<TYPE>()` coercions: RNull/RMissing pass through, except `asVector(true)`, which converts null to the empty list
 *   `findFirst`: RNull/RMissing treated as an empty vector, i.e. if the default value is specified it is used as a replacement for the special value, otherwise an error is raised.
-*   `notNA`: RNull/RMissing passing through
-*   `mustBe`, `shouldBe`: the filter condition determines whether RNull/RMissing is let through, e.g. `mustBe(stringValue())` blocks NULL since it is obviously not a string value. On the other hand, `shouldBe(stringValue())` lets the NULL through.
+*   `notNA`: RNull/RMissing pass through
+*   `mustBe`, `shouldBe`: the filter condition determines whether RNull/RMissing is let through, e.g. `mustBe(stringValue())` blocks NULL since it is obviously not a string value. On the other hand, `shouldBe(stringValue())` lets the NULL through. On the other hand, `mustBe(nullValue().or(stringValue))` lets NULL pass.
 *   `mapIf`: the condition behaves accordingly to the used filter (in the 1st parameter). For example, step `mapIf(stringValue(), constant(0), constant(1))` maps NULL to 1.
 
 The following cast pipeline examples aim to elucidate the behavior concerning the special values.
@@ -213,16 +243,13 @@ Both NULL and MISSING pass through the pipeline:
     cb.arg("x").mustBe(stringValue().not());
 ```
 
-NULL does not pass through the pipeline. MISSING passes through.
-
-```java
-    cb.arg("x").mustNotBeNull().mustBe(stringValue().not());
-```
-
-The same as above:
+NULL does not pass through the pipeline. MISSING passes through. All the following pipelines are equivalent:
 
 ```java
+    cb.arg("x").mustBe(nullValue().not()).mustBe(stringValue().not());
     cb.arg("x").mustBe(nullValue().not().and(stringValue().not()));
+    cb.arg("x").mustBe((nullValue().or(stringValue())).not());
+    cb.arg("x").mustNotBeNull().mustBe(stringValue().not());
 ```
 
 Neither NULL nor MISSING pass through the pipeline:
@@ -231,20 +258,6 @@ Neither NULL nor MISSING pass through the pipeline:
     cb.arg("x").asStringVector().mustBe(singleElement());
 ```
 
-#### Overriding the default behavior
-
-A cast pipeline can be configured not to send `RNull` and/or `RMissing` to the cast nodes forming the cast pipeline. Then those values either bypass the pipeline, being eventually transformed to some constant, or an error is raised. One can use the following steps in the pre-initial phase to override the default behavior:
-
-*   `allowNull` - RNull bypasses the pipeline
-*   `mustNotBeNull(errorMsg)` - the error with errorMsg is raised when the input argument is `RNull`
-*   `mapNull(mapper)` - `RNull` is transformed using the mapper. The `RNull` replacement bypasses the pipeline.
-
-Analogous methods exist for `RMissing`.
-
-#### Optimizing the default behavior
-
-The above-mentioned overriding configurations may also be applied behind-the-scenes as optimization of the pipelines with certain structure. For instance, `allowNull()` may be activated if the pipeline contains no `RNull/RMissing` handling cast node, such as `FindFirstNode` or `CastToVectorNode`. The `mustNotBeNull` configuration may optimize pipelines containing cast nodes raising an error for `RNull/RMissing`, such as the nodes produced by steps `findFirst()`, `findFirst(error)` or `mustBe(singleElement())`. Or the `mapNull(x)` configuration may be applied provided that the pipeline's last step is `findFirst(x)`.
-
 ### Cast Pipeline Optimizations
 
 The declarative character of cast pipelines allows for a number of optimizations done during the pipeline construction (some of them are mentioned in the previous section).
@@ -257,6 +270,8 @@ Provided that the pipeline contains the `findFirst(x)` step specifying the repla
 
 String, double and integer argument values are routed directly after the `FindFirstNode`. On the other hand, logical values bypass the whole pipeline provided that the pipeline ends by the pattern `asLogicalVector()...findFirst().map(toBoolean())`.
 
+For more details see `BypassNode`.
+
 ### Sample Builtins Using Cast Pipelines
 
 * [Scan.java](../../com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java)
@@ -264,13 +279,13 @@ String, double and integer argument values are routed directly after the `FindFi
 
 ### Using `rbdiag` tool
 
-The `mx rbdiag` tool implements the functionality of the static and dynamic stages of the chimney sweeping. This command prints a brief report for each cast pipeline defined in a given builtin.
+The `mx rbdiag` tool diagnoses a given builtin or all builtins. This command prints a brief report for each cast pipeline defined in a given builtin including a summary of the diagnosis.
 
-#### Static stage
+#### Result type analysis
 
-In the case of the static diagnostics the tool provides information about all possible result types of each argument and how those result types are bound to the corresponding arguments of the builtin's specializations. Importantly, the report can reveal unbound argument types that can potentially cause the missing specialization error.
+This analysis provides information about all possible result types of each argument and how those result types are bound to the corresponding arguments of the builtin's specializations. Importantly, the report can reveal unbound argument types that can potentially cause the missing specialization error. Further, it can reveal the so-called __dead__ specializations, i.e. specializations that are never invoked.
 
-It can be illustrated on the `rowsum_matrix` builtin. The `mx` command is then as follows:
+This analyis can be illustrated on the `rowsum_matrix` builtin. The `mx` command is then as follows:
 
 ```bash
 mx rbdiag rowsum_matrix
@@ -280,13 +295,13 @@ It prints a rather lengthy report, of which the following snippet shows the diag
 
 ```bash
  Pipeline for 'x' (arg[0]):  
+  Warning: Unbound types:  
+   [Integer, Double]  
   Result types union:  
    [Integer, RAbstractIntVector, RAbstractDoubleVector, Double]  
   Bound result types:  
    potential (RAbstractIntVector->RVector) in Object rowsum(*RVector*,RVector,RVector,boolean,RStringVector)  
    potential (RAbstractDoubleVector->RVector) in Object rowsum(*RVector*,RVector,RVector,boolean,RStringVector)  
-  Unbound types:  
-   [Integer, Double]  
 ```
 
 The `Result types union` section lists all result types possibly produced by the pipeline. The `Bound result types` section outlines all bound type; i.e. the argument types for which there is a corresponding specialization in the builtin. In this case, only two argument types - `RAbstractIntVector` and `RAbstractDoubleVector` - are bound to the `rowsum(RVector,RVector,RVector,boolean,RStringVector)` specialization. (The asterisks surrounding the first argument in the specialization indicate the argument to which the type in question is bound). The `potential` flag indicates here that there is an underlying implicit conversion between the type produced by the cast pipeline and the argument type in the specialization.
@@ -302,15 +317,13 @@ Nevertheless, there are two arguments left unbound - `Integer` and `Double`. Thi
    potential (Double->RAbstractVector) in Object rowsum(*RAbstractVector*,RAbstractVector,RAbstractVector,boolean,RAbstractStringVector)  
    full (RAbstractDoubleVector->RAbstractVector) in Object rowsum(*RAbstractVector*,RAbstractVector,RAbstractVector,boolean,RAbstractStringVector)  
    potential (Integer->RAbstractVector) in Object rowsum(*RAbstractVector*,RAbstractVector,RAbstractVector,boolean,RAbstractStringVector)  
-  Unbound types:  
-   []
 ```
 
 The produced result types are naturally the same ones, but now all of them are bound. In conclusion, using the abstract types resulted in the binding of the previously unbound types.
 
 Note: The `full` flag indicates that the pipeline's type is a subtype of the specialization's argument type. The `partial` flag, which is not seen here, indicates that the pipeline's type is a supertype of the specialization's argument type. The `potential` flag indicates an implicit conversion or a potentially non-empty intersection between the two types, typically if they are both interfaces.
 
-#### Dynamic stage
+#### Chimney-sweeping
 
 In the dynamic stage, the tool uses the samples inferred from the cast pipelines of a given builtin along with some 'springboard' list of valid arguments to construct a number of argument combinations. These argument lists are then used to invoke both the FastR builtin and its GnuR counterpart. The tool uses the test output file (ExpectedTestOutput.test) to obtain the 'springboard' argument lists for a given builtin. These valid argument lists are reproduced by substituting combinations of generated samples. The varied arguments are then used against both GnuR and FastR. If the two outputs differ, the tool reports the command and the corresponding outputs.
 
-- 
GitLab


From 8ec4560d9b7e2631440e1ad2867646ffe9e5a629 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 24 Feb 2017 15:04:46 +0100
Subject: [PATCH 048/402] use curio.ssw.jku.at to have valid URL in snapshots
 repo

---
 mx.fastr/suite.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 527fa89155..b75272efb6 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -40,7 +40,7 @@ suite = {
 
   "repositories" : {
     "snapshots" : {
-        "url" : "https://FASTR_SNAPSHOT_HOST/nexus/content/repositories/snapshots",
+        "url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots",
         "licenses" : ["GPLv2"]
     }
   },
-- 
GitLab


From f4054d35a1bb4014793a6808765007ba9ad3a192 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 27 Feb 2017 15:31:48 +0100
Subject: [PATCH 049/402] fix several builtin cast pipelines

---
 .../builtin/base/ConditionFunctions.java      |  5 +++++
 .../builtin/base/DatePOSIXFunctions.java      |  3 ++-
 .../r/nodes/builtin/base/Internal.java        |  6 ++++-
 .../r/nodes/builtin/base/LaFunctions.java     | 22 ++++++++-----------
 .../builtin/base/infix/AssignBuiltin.java     |  5 +++++
 .../builtin/base/infix/AssignBuiltinEq.java   |  5 +++++
 .../base/infix/AssignOuterBuiltin.java        |  5 +++++
 .../r/nodes/builtin/fastr/FastRContext.java   |  9 +-------
 .../r/nodes/builtin/fastr/FastRDebug.java     | 21 ++++++++++++++----
 .../r/nodes/builtin/fastr/FastRPkgSource.java |  5 ++++-
 .../r/nodes/builtin/fastr/FastRTrace.java     |  4 ++++
 .../r/nodes/builtin/fastr/FastRTreeStats.java | 10 ++++-----
 12 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
index b56352f791..5c745baf5c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
@@ -101,6 +101,11 @@ public class ConditionFunctions {
 
     @RBuiltin(name = ".resetCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"stack"}, behavior = COMPLEX)
     public abstract static class ResetCondHands extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(ResetCondHands.class);
+        }
+
         @SuppressWarnings("unused")
         @Specialization
         protected RNull resetCondHands(Object stack) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
index f5ea8c6b09..be7cba0797 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
@@ -14,6 +14,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
@@ -141,7 +142,7 @@ public class DatePOSIXFunctions {
 
         static {
             Casts casts = new Casts(Date2POSIXlt.class);
-            casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector();
+            casts.arg("x").mustNotBeMissing().mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java
index 4a50c81280..5b684d04ab 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = ".Internal", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"call"}, nonEvalArgs = 0, behavior = COMPLEX)
 public abstract class Internal extends RBuiltinNode {
 
+    static {
+        Casts.noCasts(Internal.class);
+    }
+
     @Specialization
     protected Object doInternal(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index f37d5a074c..571d2efef2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -102,13 +102,13 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected Object doRg(RDoubleVector matrix, boolean onlyValues,
+        protected Object doRg(RAbstractDoubleVector matrix, boolean onlyValues,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") LapackRFFI.DgeevNode dgeevNode) {
             int[] dims = getDimsNode.getDimensions(matrix);
             // copy array component of matrix as Lapack destroys it
             int n = dims[0];
-            double[] a = matrix.getDataCopy();
+            double[] a = matrix.materialize().getDataCopy();
             char jobVL = 'N';
             char jobVR = 'N';
             boolean vectors = !onlyValues;
@@ -202,7 +202,7 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected Object doRs(RDoubleVector matrix, boolean onlyValues,
+        protected Object doRs(RAbstractDoubleVector matrix, boolean onlyValues,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") LapackRFFI.DsyevrNode dsyevrNode) {
             int[] dims = getDimsNode.getDimensions(matrix);
@@ -215,7 +215,7 @@ public class LaFunctions {
             int il = 0;
             int iu = 0;
             double abstol = 0.0;
-            double[] x = matrix.getDataCopy();
+            double[] x = matrix.materialize().getDataCopy();
 
             double[] values = new double[n];
 
@@ -275,15 +275,11 @@ public class LaFunctions {
                         @Cached("create()") SetDimAttributeNode setDimsNode,
                         @Cached("create()") LapackRFFI.Dgeqp3Node dgeqp3Node) {
             // This implementation is sufficient for B25 matcal-5.
-            if (!(aIn instanceof RDoubleVector)) {
-                RError.nyi(this, "non-real vectors not supported (yet)");
-            }
-            RDoubleVector daIn = (RDoubleVector) aIn;
-            int[] dims = getDimsNode.getDimensions(daIn);
+            int[] dims = getDimsNode.getDimensions(aIn);
             // copy array component of matrix as Lapack destroys it
             int n = dims[0];
             int m = dims[1];
-            double[] a = daIn.getDataCopy();
+            double[] a = aIn.materialize().getDataCopy();
             int[] jpvt = new int[n];
             double[] tau = new double[m < n ? m : n];
             double[] work = new double[1];
@@ -328,7 +324,7 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected RDoubleVector doQrCoefReal(RList qIn, RDoubleVector bIn,
+        protected RDoubleVector doQrCoefReal(RList qIn, RAbstractDoubleVector bIn,
                         @Cached("create()") GetDimAttributeNode getBDimsNode,
                         @Cached("create()") GetDimAttributeNode getQDimsNode,
                         @Cached("create()") LapackRFFI.DormqrNode dormqrNode,
@@ -481,7 +477,7 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected RDoubleVector doDetGeReal(RDoubleVector aIn, boolean piv, double tol,
+        protected RDoubleVector doDetGeReal(RAbstractDoubleVector aIn, boolean piv, double tol,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
                         @Cached("create()") GetDimNamesAttributeNode getDimNamesNode,
@@ -551,7 +547,7 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected RDoubleVector laSolve(RAbstractVector a, RDoubleVector bin, double tol,
+        protected RDoubleVector laSolve(RAbstractVector a, RAbstractDoubleVector bin, double tol,
                         @Cached("create()") GetDimAttributeNode getADimsNode,
                         @Cached("create()") GetDimAttributeNode getBinDimsNode,
                         @Cached("create()") SetDimAttributeNode setBDimsNode,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java
index 48c2028bde..0a795bc055 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java
@@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME)
 public abstract class AssignBuiltin extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(AssignBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object i) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java
index 26185da3e6..bf68624ef5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java
@@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "=", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME)
 public abstract class AssignBuiltinEq extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(AssignBuiltinEq.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object i) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java
index fd990f8ec4..3ef3d4676c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java
@@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "<<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = COMPLEX)
 public abstract class AssignOuterBuiltin extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(AssignOuterBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x, @SuppressWarnings("unused") Object i) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 2b3370bbb8..4086dcad74 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -274,8 +274,7 @@ public class FastRContext {
         @Specialization
         @TruffleBoundary
         protected Object rscript(RAbstractStringVector args, RAbstractStringVector env, boolean intern) {
-            Object rc = RContext.getRRuntimeASTAccess().rscriptMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern);
-            return rc;
+            return RContext.getRRuntimeASTAccess().rscriptMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern);
         }
 
         @Specialization
@@ -283,12 +282,6 @@ public class FastRContext {
         protected Object rscript(RAbstractStringVector args, @SuppressWarnings("unused") RMissing env, boolean intern) {
             return rscript(args, RDataFactory.createEmptyStringVector(), intern);
         }
-
-        @Specialization
-        @TruffleBoundary
-        protected Object rscript(@SuppressWarnings("unused") RMissing args, RAbstractStringVector env, boolean intern) {
-            return rscript(RDataFactory.createEmptyStringVector(), env, intern);
-        }
     }
 
     private static ContextInfo createContextInfo(RContext.ContextKind contextKind) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
index 6dd3870946..6c4ea7922d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -39,15 +40,27 @@ public abstract class FastRDebug extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(FastRDebug.class);
-        casts.arg("values").asStringVector();
+        casts.arg("values").allowNullAndMissing().asStringVector();
     }
 
     @Specialization
     @TruffleBoundary
-    protected RNull debug(RAbstractStringVector vec) {
-        for (int i = 0; i < vec.getLength(); i++) {
-            FastROptions.debugUpdate(vec.getDataAt(i));
+    protected RNull debug(RAbstractStringVector values) {
+        for (int i = 0; i < values.getLength(); i++) {
+            FastROptions.debugUpdate(values.getDataAt(i));
         }
         return RNull.instance;
     }
+
+    @Specialization
+    @TruffleBoundary
+    protected RNull debug(@SuppressWarnings("unused") RNull values) {
+        return RNull.instance;
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected RNull debug(@SuppressWarnings("unused") RMissing values) {
+        return RNull.instance;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
index 0306c6dc7a..0a1b33acec 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
@@ -34,6 +34,7 @@ import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -71,12 +72,13 @@ public abstract class FastRPkgSource extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(FastRPkgSource.class);
-        casts.arg("pkgs").mustBe(stringValue());
+        casts.arg("pkgs").allowNull().mustBe(stringValue());
         casts.arg("verbose").asLogicalVector().findFirst().notNA().map(toBoolean());
     }
 
     @Specialization
     public RNull pkgSource(VirtualFrame frame, @SuppressWarnings("unused") RNull pkgs, boolean verbose) {
+        CompilerDirectives.transferToInterpreter();
         String[] searchPath = REnvironment.searchPath();
         for (String s : searchPath) {
             REnvironment env = REnvironment.lookupOnSearchPath(s);
@@ -90,6 +92,7 @@ public abstract class FastRPkgSource extends RBuiltinNode {
 
     @Specialization
     public RNull pkgSource(VirtualFrame frame, RAbstractStringVector pkgs, boolean verbose) {
+        CompilerDirectives.transferToInterpreter();
         for (int i = 0; i < pkgs.getLength(); i++) {
             String pkg = pkgs.getDataAt(i);
             REnvironment env = REnvironment.getRegisteredNamespace(pkg);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index 96eec41e23..d29aa74c9b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -182,6 +182,10 @@ public class FastRTrace {
 
         @Child private TraceFunctions.PrimUnTrace primUnTrace;
 
+        static {
+            Casts.noCasts(Untrace.class);
+        }
+
         @Specialization
         protected Object untrace(VirtualFrame frame, Object whatObj, Object signature, Object whereObj) {
             Object what = whatObj;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java
index 968cf379a3..e40645a046 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.fastr;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -38,7 +39,6 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -50,9 +50,9 @@ public abstract class FastRTreeStats extends RBuiltinNode {
 
     private static final RStringVector COLNAMES = RDataFactory.createStringVector(new String[]{"Total", "Syntax", "Non-Syntax"}, RDataFactory.COMPLETE_VECTOR);
 
-    @Override
-    public Object[] getDefaultParameterValues() {
-        return new Object[]{RMissing.instance};
+    static {
+        Casts casts = new Casts(FastRTreeStats.class);
+        casts.arg("obj").allowNull().mustBe(instanceOf(REnvironment.class).or(instanceOf(RFunction.class)));
     }
 
     @Specialization
-- 
GitLab


From 79ef398fd1ce23f55dfabe214d9e3d8cf2183105 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Sat, 25 Feb 2017 16:51:02 -0800
Subject: [PATCH 050/402] [GR-2982] Remove temporary directory on context exit;
 share parent tempdir for SHARED_PARENT_RW contexts.

---
 .../oracle/truffle/r/runtime/RCleanUp.java    |  3 +-
 .../truffle/r/runtime/TempPathName.java       | 44 ++++++++++++++++++-
 .../truffle/r/runtime/context/RContext.java   |  3 +-
 3 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
index 3e303f3c0e..436e252e5d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
@@ -104,8 +104,7 @@ public class RCleanUp {
                 RInternalError.reportError(t);
             }
         }
-        // TODO run exit finalizers (FFI)
-        // TODO clean tmpdir
+        // TODO run exit finalizers (FFI) (this should happen in the FFI context beforeDestroy)
         throw new ExitException(status);
 
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
index d0783f13cf..0975c771c1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
@@ -23,8 +23,14 @@
 package com.oracle.truffle.r.runtime;
 
 import java.io.File;
+import java.io.IOException;
 import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.Random;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -47,6 +53,11 @@ public class TempPathName implements RContext.ContextState {
 
     @Override
     public RContext.ContextState initialize(RContext context) {
+        if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
+            // share tempdir with parent
+            tempDirPath = context.getParent().stateTempPath.tempDirPath;
+            return this;
+        }
         final String[] envVars = new String[]{"TMPDIR", "TMP", "TEMP"};
         String startingTempDir = null;
         for (String envVar : envVars) {
@@ -72,13 +83,26 @@ public class TempPathName implements RContext.ContextState {
         return this;
     }
 
+    @Override
+    public void beforeDestroy(RContext context) {
+        if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
+            return;
+        }
+        try {
+            Files.walkFileTree(Paths.get(tempDirPath), new DeleteVisitor());
+        } catch (Throwable e) {
+            // unexpected and we are exiting anyway
+        }
+    }
+
     private static boolean isWriteableDirectory(String path) {
         File f = new File(path);
         return f.exists() && f.isDirectory() && f.canWrite();
     }
 
     public static String tempDirPath() {
-        return RContext.getInstance().stateTempPath.tempDirPath;
+        String result = RContext.getInstance().stateTempPath.tempDirPath;
+        return result;
     }
 
     public static TempPathName newContextState() {
@@ -107,4 +131,22 @@ public class TempPathName implements RContext.ContextState {
             sb.append(RANDOM_CHARACTERS.charAt(rand.nextInt(RANDOM_CHARACTERS_LENGTH)));
         }
     }
+
+    private static final class DeleteVisitor extends SimpleFileVisitor<Path> {
+
+        @Override
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+            return del(file);
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+            return del(dir);
+        }
+
+        private static FileVisitResult del(Path p) throws IOException {
+            Files.delete(p);
+            return FileVisitResult.CONTINUE;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 36710352d1..7edb1892a2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -424,7 +424,8 @@ public final class RContext extends ExecutionContext implements TruffleObject {
     public final WeakHashMap<Source, REnvironment> sourceRefEnvironments = new WeakHashMap<>();
 
     private ContextState[] contextStates() {
-        return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize,
+        return new ContextState[]{stateREnvVars, stateRProfile, stateTempPath, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI,
+                        stateRSerialize,
                         stateLazyDBCache, stateInstrumentation, stateDLL};
     }
 
-- 
GitLab


From 3b59aeeda75adb7f4380052967204670e7646032 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Feb 2017 10:50:20 +0100
Subject: [PATCH 051/402] update Truffle dependency

---
 mx.fastr/suite.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index b75272efb6..72888b9907 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -28,7 +28,7 @@ suite = {
     "suites" : [
             {
                "name" : "truffle",
-               "version" : "0a9e88293bf90fe485999b26b0969e71509a64aa",
+               "version" : "c02973969fb144b533ae0e53187674cb04c2aacc",
                "urls" : [
                     {"url" : "https://github.com/graalvm/truffle", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From 91b486d6da0a94d137e5597f1aee8ba115b99b23 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 27 Feb 2017 15:29:17 +0100
Subject: [PATCH 052/402] additional verification on result types

---
 .../truffle/r/nodes/function/CallArgumentsNode.java      | 9 +++++++--
 .../truffle/r/nodes/function/ClassHierarchyNode.java     | 1 +
 .../truffle/r/nodes/function/FunctionDefinitionNode.java | 3 +++
 .../src/com/oracle/truffle/r/runtime/nodes/RNode.java    | 8 +++++++-
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
index fb29d87e3e..0d54c7a623 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperN
 import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RMissing;
@@ -233,7 +234,11 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
                 index = flattenVarArgsObject(frame, varArgs, values, index);
                 vargsSymbolsIndex++;
             } else {
-                values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame);
+                Object result = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame);
+                if (CompilerDirectives.inInterpreter() && result == null) {
+                    throw RInternalError.shouldNotReachHere("invalid null in arguments");
+                }
+                values[index] = result;
                 index++;
             }
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index 55b43d1f3f..dd4a98c595 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -162,6 +162,7 @@ public abstract class ClassHierarchyNode extends UnaryNode {
 
     @Fallback
     protected RStringVector getClassHr(Object obj) {
+        CompilerDirectives.transferToInterpreter();
         throw RInternalError.shouldNotReachHere("type: " + (obj == null ? "null" : obj.getClass().getSimpleName()));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 3d5bd7b6d2..1ac435c5d9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -253,6 +253,9 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
             saveArguments.execute(frame);
             Object result = body.visibleExecute(frame);
             normalExit.enter();
+            if (CompilerDirectives.inInterpreter() && result == null) {
+                throw RInternalError.shouldNotReachHere("invalid null in result of " + this);
+            }
             return result;
         } catch (ReturnException ex) {
             if (returnTopLevelProfile.profile(ex.getTarget() == RArguments.getCall(frame))) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
index 43eda05cbd..76d4203238 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
@@ -22,10 +22,12 @@
  */
 package com.oracle.truffle.r.runtime.nodes;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrumentation.Instrumentable;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.RTypesGen;
 import com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory;
@@ -53,7 +55,11 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode {
      * does not start with "execute" so that the DSL does not treat it like an execute function.
      */
     public Object visibleExecute(VirtualFrame frame) {
-        return execute(frame);
+        Object result = execute(frame);
+        if (CompilerDirectives.inInterpreter() && result == null) {
+            throw RInternalError.shouldNotReachHere("null result in " + this.getClass().getSimpleName());
+        }
+        return result;
     }
 
     /*
-- 
GitLab


From 528907263ce5443d94a1fbe132c17ebd6633a5f4 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 24 Feb 2017 16:02:52 +0100
Subject: [PATCH 053/402] Remove obsolete BypassNode & handle
 PipelineReturnException

---
 .../truffle/r/nodes/builtin/base/Repeat.java  |   6 +-
 .../r/nodes/test/PipelineToCastNodeTests.java |  64 +----
 .../r/nodes/builtin/casts/PipelineStep.java   |   7 +
 .../builtin/casts/PipelineToCastNode.java     | 183 +------------
 .../truffle/r/nodes/unary/BypassNode.java     | 250 ------------------
 .../r/nodes/unary/ChainedCastNode.java        |  28 +-
 6 files changed, 39 insertions(+), 499 deletions(-)
 delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index 5d1bd20567..27948929a0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -75,8 +75,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "times", "length.out", "each"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class Repeat extends RBuiltinNode {
 
-    protected abstract Object execute(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each);
-
     private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
     private final BranchProfile errorBranch = BranchProfile.create();
     private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
@@ -92,7 +90,7 @@ public abstract class Repeat extends RBuiltinNode {
         Casts casts = new Casts(Repeat.class);
         casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName());
         casts.arg("times").defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector();
-        casts.arg("length.out").mustNotBeNull().asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA,
+        casts.arg("length.out").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA,
                         RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0)));
         casts.arg("each").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each").notNA(
                         1).mustBe(gte(0));
@@ -224,7 +222,7 @@ public abstract class Repeat extends RBuiltinNode {
             // times is a vector with several elements
             if (x.getLength() != times.getLength()) {
                 errorBranch.enter();
-                invalidTimes();
+                throw invalidTimes();
             }
             // iterate once over the times vector to determine result vector size
             int resultLength = 0;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
index 11c58387f4..a719c9d363 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
@@ -29,20 +29,13 @@ import java.util.Optional;
 
 import org.junit.Test;
 
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder;
-import com.oracle.truffle.r.nodes.unary.BypassNode;
-import com.oracle.truffle.r.nodes.unary.BypassNode.BypassIntegerNode;
-import com.oracle.truffle.r.nodes.unary.BypassNode.BypassLogicalMapToBooleanNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNode;
 import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -60,66 +53,29 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 public class PipelineToCastNodeTests {
     @Test
     public void asLogicalVector() {
-        CastNode pipeline = createPipeline(new CoercionStep<>(RType.Logical, false));
-        CastNode castNode = assertBypassNode(pipeline);
-        assertTrue(castNode instanceof CastLogicalBaseNode);
+        assertTrue(createPipeline(new CoercionStep<>(RType.Logical, false)) instanceof CastLogicalBaseNode);
     }
 
     @Test
     public void asStringVectorFindFirst() {
-        CastNode pipeline = createPipeline(new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null)));
-        CastNode chain = assertBypassNode(pipeline);
-        assertChainedCast(chain, CastStringBaseNode.class, FindFirstNode.class);
-        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) chain).getSecondCast();
+        assertChainedCast(createPipeline(new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null))), CastStringBaseNode.class, FindFirstNode.class);
+        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) createPipeline(
+                        new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null)))).getSecondCast();
         assertEquals("hello", findFirst.getDefaultValue());
     }
 
-    @Test
-    public void optimizeForSingleInteger() {
-        // should be equivalent of mustBe(integerValue()).asIntegerVector().findFirst()
-        CastNode pipeline = createPipeline(
-                        new FilterStep<>(new RTypeFilter<>(RType.Integer), null, false).setNext(new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>(null, Integer.class, null))));
-        assertBypassNode(pipeline, BypassIntegerNode.class);
-    }
-
-    @Test
-    public void optimizeForSingleIntegerWhenNumericFilterIsUsed() {
-        // should be close to mustBe(numericValue()).asIntegerVector().findFirst()
-        OrFilter<Object> filter = new OrFilter<>(new RTypeFilter<>(RType.Integer), new RTypeFilter<>(RType.Double));
-        CastNode pipeline = createPipeline(
-                        new FilterStep<>(filter, null, false).setNext(new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>(null, Integer.class, null))));
-        assertBypassNode(pipeline, BypassIntegerNode.class);
-    }
-
-    @Test
-    public void optimizeMapSingleByteToBoolean() {
-        // should be equivalent of mustBe(integerValue()).asIntegerVector().findFirst()
-        CastNode pipeline = createPipeline(new CoercionStep<>(RType.Logical, false).setNext(new FindFirstStep<>(null, Byte.class, null).setNext(new MapStep<>(MapByteToBoolean.INSTANCE))));
-        assertBypassNode(pipeline, BypassLogicalMapToBooleanNode.class);
-    }
-
     @Test
     public void mustBeREnvironmentAsIntegerVectorFindFirst() {
-        CastNode pipeline = createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
-                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))));
-        CastNode chain = assertBypassNode(pipeline);
-        assertChainedCast(chain, ChainedCastNode.class, FindFirstNode.class);
-        CastNode next = ((ChainedCastNode) chain).getFirstCast();
+        assertChainedCast(createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
+                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null)))), ChainedCastNode.class, FindFirstNode.class);
+        CastNode next = ((ChainedCastNode) createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
+                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))))).getFirstCast();
         assertChainedCast(next, FilterNode.class, CastIntegerBaseNode.class);
-        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) chain).getSecondCast();
+        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
+                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))))).getSecondCast();
         assertEquals("hello", findFirst.getDefaultValue());
     }
 
-    private static CastNode assertBypassNode(CastNode node) {
-        assertTrue(node instanceof BypassNode);
-        return ((BypassNode) node).getWrappedHead();
-    }
-
-    private static CastNode assertBypassNode(CastNode node, Class<?> expectedClass) {
-        assertTrue(expectedClass.isInstance(node));
-        return ((BypassNode) node).getWrappedHead();
-    }
-
     private static void assertChainedCast(CastNode node, Class<?> expectedFirst, Class<?> expectedSecond) {
         assertTrue(node instanceof ChainedCastNode);
         assertTrue(expectedFirst.isInstance(((ChainedCastNode) node).getFirstCast()));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index d692458bf9..e5481ded2c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -324,6 +324,13 @@ public abstract class PipelineStep<T, R> {
         public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
             return visitor.visit(this, previous);
         }
+
+        public MapIfStep<T, R> withoutReturns() {
+            if (!returns) {
+                return this;
+            }
+            return new MapIfStep<T, R>(filter, trueBranch, falseBranch, false);
+        }
     }
 
     /**
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 4256f4575c..815b34ee45 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -65,11 +65,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.NotNAStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.PipelineStepVisitor;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
-import com.oracle.truffle.r.nodes.unary.BypassNode;
-import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassDoubleNodeGen;
-import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassIntegerNodeGen;
-import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassLogicalMapToBooleanNodeGen;
-import com.oracle.truffle.r.nodes.unary.BypassNodeGen.BypassStringNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleBaseNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
@@ -117,18 +112,18 @@ public final class PipelineToCastNode {
         return convert(config, firstStep, PipelineConfig.getFilterFactory(), PipelineConfig.getMapperFactory(), fwdAnalysisResult);
     }
 
-    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory,
+    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStepIn, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory,
                     Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
-        if (firstStep == null) {
-            return BypassNode.create(config, null, mapperFactory, null);
+        if (firstStepIn == null) {
+            return null;
         }
 
-        Supplier<CastNode> originalPipelineFactory = () -> {
-            CastNodeFactory nodeFactory = new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultDefaultMessage());
-            SinglePrimitiveOptimization singleOptVisitor = new SinglePrimitiveOptimization(nodeFactory);
-            CastNode headNode = convert(firstStep, singleOptVisitor);
-            return singleOptVisitor.createBypassNode(config, headNode, mapperFactory);
-        };
+        // if the pipeline is only single return, we change it to map to avoid needing to catch
+        // the PipelineReturnException, otherwise the exception is caught by ChainedCastNode
+        boolean singleMapStep = firstStepIn.getNext() == null && firstStepIn instanceof MapIfStep;
+        PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep) firstStepIn).withoutReturns() : firstStepIn;
+
+        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultDefaultMessage()));
 
         if (!config.getValueForwarding()) {
             return originalPipelineFactory.get();
@@ -159,7 +154,7 @@ public final class PipelineToCastNode {
                     prevCastNode = node;
                 } else {
                     CastNode finalPrevCastNode = prevCastNode;
-                    prevCastNode = new ChainedCastNode(() -> finalPrevCastNode, () -> node);
+                    prevCastNode = new ChainedCastNode(finalPrevCastNode, node);
                 }
             }
 
@@ -168,164 +163,6 @@ public final class PipelineToCastNode {
         return prevCastNode;
     }
 
-    /**
-     * Visitor that is capable of recognizing patterns that permit to bypass single primitive value
-     * directly to any casts after find first step or directly to the built-in if there is nothing
-     * after find first step.
-     */
-    private static final class SinglePrimitiveOptimization implements PipelineStepVisitor<CastNode> {
-        // Any destructive step or step we cannot analyze changes this to false
-        private boolean canBeOptimized = true;
-        // Any coercion or check step initialize this or check the existing value, if it does not
-        // match -> canBeOptimized = false
-        private RType targetType = null;
-        // We remember this step so that we can construct another copy of its cast node
-        private FindFirstStep<?, ?> findFirstStep = null;
-        private final PipelineStepVisitor<CastNode> inner;
-
-        private SinglePrimitiveOptimization(PipelineStepVisitor<CastNode> inner) {
-            this.inner = inner;
-        }
-
-        /**
-         * Creates {@link BypassNode} if there is no optimization opportunity, or creates more
-         * specialized child class if the cast pipeline follows the required pattern.
-         */
-        public CastNode createBypassNode(PipelineConfig pipelineConfig, CastNode wrappedHead, ArgumentMapperFactory mapperFactory) {
-            if (canBeOptimized && findFirstStep != null) {
-                if (targetType == RType.Integer) {
-                    return BypassIntegerNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode());
-                } else if (targetType == RType.Double) {
-                    return BypassDoubleNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode());
-                } else if (targetType == RType.Logical && isNextMapToBoolean(findFirstStep)) {
-                    return BypassLogicalMapToBooleanNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode());
-                } else if (targetType == RType.Character) {
-                    return BypassStringNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault(), getAfterFindFirstNode());
-                }
-            }
-            return BypassNode.create(pipelineConfig, wrappedHead, mapperFactory, getFindFirstWithDefault());
-        }
-
-        @Override
-        public CastNode visit(FindFirstStep<?, ?> step, CastNode previous) {
-            assert !canBeOptimized || targetType != null : "There must be a coercion step before find first";
-            findFirstStep = step;
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(CoercionStep<?, ?> step, CastNode previous) {
-            canBeOptimized(step.type);
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(MapStep<?, ?> step, CastNode previous) {
-            cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(MapIfStep<?, ?> step, CastNode previous) {
-            cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(FilterStep<?, ?> step, CastNode previous) {
-            targetType = checkFilter(step.getFilter());
-            if (targetType == null) {
-                canBeOptimized = false;
-            }
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(NotNAStep<?> step, CastNode previous) {
-            // TODO: we can remember that we saw not NA and do this check in the BypassNode
-            canBeOptimized = false;
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(DefaultErrorStep<?> step, CastNode previous) {
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(DefaultWarningStep<?> step, CastNode previous) {
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(BoxPrimitiveStep<?> step, CastNode previous) {
-            canBeOptimized = false;
-            return inner.visit(step, previous);
-        }
-
-        @Override
-        public CastNode visit(AttributableCoercionStep<?> step, CastNode previous) {
-            cannotBeOptimizedBeforeFindFirst();
-            return inner.visit(step, previous);
-        }
-
-        private void cannotBeOptimizedBeforeFindFirst() {
-            if (findFirstStep == null) {
-                canBeOptimized = false;
-            }
-        }
-
-        private void canBeOptimized(RType newType) {
-            if (targetType == null) {
-                targetType = newType;
-            } else if (targetType != newType) {
-                canBeOptimized = false;
-            }
-        }
-
-        /**
-         * Returns null if the filter does not conform to expected type or does not produce some
-         * concrete type if there is no expected type.
-         */
-        private RType checkFilter(Filter<?, ?> filter) {
-            if (filter instanceof RTypeFilter) {
-                RType type = ((RTypeFilter<?>) filter).getType();
-                if (targetType == null) {
-                    return type;
-                }
-                return type == targetType ? type : null;
-            } else if (filter instanceof OrFilter) {
-                OrFilter<?> or = (OrFilter<?>) filter;
-                RType leftType = checkFilter(or.getLeft());
-                if (targetType == null) {
-                    return leftType;
-                }
-                RType rightType = checkFilter(or.getRight());
-                return rightType == targetType || leftType == targetType ? targetType : null;
-            }
-            return null;
-        }
-
-        private CastNode getFindFirstWithDefault() {
-            if (findFirstStep != null && findFirstStep.getDefaultValue() != null) {
-                return convert(findFirstStep, inner);
-            }
-            return null;
-        }
-
-        private CastNode getAfterFindFirstNode() {
-            if (findFirstStep.getNext() != null) {
-                return convert(findFirstStep.getNext(), inner);
-            }
-            return null;
-        }
-
-        private static boolean isNextMapToBoolean(FindFirstStep<?, ?> findFirst) {
-            PipelineStep<?, ?> next = findFirst.getNext();
-            return next != null && next instanceof MapStep && ((MapStep<?, ?>) next).getMapper() instanceof MapByteToBoolean;
-        }
-    }
-
     private static final class CastNodeFactory implements PipelineStepVisitor<CastNode> {
         private final ArgumentFilterFactory filterFactory;
         private final ArgumentMapperFactory mapperFactory;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java
deleted file mode 100644
index 59ae7e9a2c..0000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/BypassNode.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.unary;
-
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.builtin.ArgumentMapper;
-import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactory;
-import com.oracle.truffle.r.nodes.unary.ConditionalMapNode.PipelineReturnException;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
-
-/**
- * The node wraps the cast node created for a cast pipeline and handles {@code RNull} and
- * {@code RMissing} according to {@link PipelineConfig}. Those values are either blocked or sent
- * directly to either the 'find first' node with default value if there is any 'find first' node
- * with default value in the pipeline or to directly to the builtin.
- *
- * There are several specialization capable of, on top of handling RNull/RMissing, sending a
- * primitive value, e.g. integer, directly the first node after the 'find first' thus bypassing any
- * other logic in between.
- */
-@SuppressWarnings({"rawtypes", "unchecked"})
-public abstract class BypassNode extends CastNode {
-
-    private final boolean isRNullBypassed;
-    private final MessageData nullMsg;
-    private final ArgumentMapper nullMapFn;
-
-    private final boolean isRMissingBypassed;
-    private final MessageData missingMsg;
-    private final ArgumentMapper missingMapFn;
-    private final boolean noHead;
-
-    /**
-     * This is the cast pipeline itself.
-     */
-    @Child private CastNode wrappedHead;
-
-    /**
-     * If there is a {@link FindFirstNode} in the pipeline with a default value, this will hold copy
-     * of it.
-     */
-    @Child private CastNode directFindFirstNodeWithDefault;
-
-    /**
-     * If there are some steps after the {@link FindFirstNode} in the cast pipeline, then this will
-     * hold copy of its first node (which can be chained to following nodes).
-     */
-    @Child private CastNode afterFindFirst;
-
-    protected BypassNode(PipelineConfig conf, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNodeWithDefault,
-                    CastNode afterFindFirst) {
-        this.nullMapFn = conf.getNullMapper() == null ? null : mapperFactory.createMapper(conf.getNullMapper());
-        this.isRNullBypassed = this.nullMapFn != null;
-        this.nullMsg = getMessage(isRNullBypassed, conf.getNullMessage(), conf);
-
-        this.missingMapFn = conf.getMissingMapper() == null ? null : mapperFactory.createMapper(conf.getMissingMapper());
-        this.isRMissingBypassed = this.missingMapFn != null;
-        this.missingMsg = getMessage(isRMissingBypassed, conf.getMissingMessage(), conf);
-
-        this.wrappedHead = wrappedHead;
-        this.noHead = wrappedHead == null;
-
-        this.directFindFirstNodeWithDefault = insertIfNotNull(directFindFirstNodeWithDefault);
-        this.afterFindFirst = insertIfNotNull(afterFindFirst);
-    }
-
-    public final CastNode getWrappedHead() {
-        return wrappedHead;
-    }
-
-    public final ArgumentMapper getNullMapper() {
-        return nullMapFn;
-    }
-
-    public final ArgumentMapper getMissingMapper() {
-        return missingMapFn;
-    }
-
-    protected final Object executeAfterFindFirst(Object value) {
-        if (afterFindFirst != null) {
-            try {
-                return afterFindFirst.execute(value);
-            } catch (PipelineReturnException ret) {
-                return ret.getResult();
-            }
-        } else {
-            return value;
-        }
-    }
-
-    private <T extends Node> T insertIfNotNull(T child) {
-        return child != null ? insert(child) : child;
-    }
-
-    private MessageData getMessage(boolean isWarning, MessageData msg, PipelineConfig config) {
-        if (msg == null) {
-            return null;
-        }
-
-        MessageData defaultValue = isWarning ? config.getDefaultWarning() : config.getDefaultError();
-        MessageData result = isWarning ? msg : MessageData.getFirstNonNull(null, msg, defaultValue);
-        return result != null ? result.fixCallObj(this) : null;
-    }
-
-    @Specialization
-    public Object bypassRNull(RNull x) {
-        if (isRNullBypassed) {
-            if (nullMsg != null) {
-                handleArgumentWarning(x, nullMsg.getCallObj(), nullMsg.getMessage(), nullMsg.getMessageArgs());
-            }
-            return nullMapFn.map(x);
-        } else if (directFindFirstNodeWithDefault != null) {
-            return directFindFirstNodeWithDefault.execute(x);
-        } else if (nullMsg == null) {
-            // go to the pipeline
-            return handleOthers(x);
-        } else {
-            handleArgumentError(x, nullMsg.getCallObj(), nullMsg.getMessage(), nullMsg.getMessageArgs());
-            return x;
-        }
-    }
-
-    @Specialization
-    public Object bypassRMissing(RMissing x) {
-        if (isRMissingBypassed) {
-            if (missingMsg != null) {
-                handleArgumentWarning(x, missingMsg.getCallObj(), missingMsg.getMessage(), missingMsg.getMessageArgs());
-            }
-            return missingMapFn.map(x);
-        } else if (directFindFirstNodeWithDefault != null) {
-            return directFindFirstNodeWithDefault.execute(x);
-        } else if (missingMsg == null) {
-            // go to the pipeline
-            return handleOthers(x);
-        } else {
-            handleArgumentError(x, missingMsg.getCallObj(), missingMsg.getMessage(), missingMsg.getMessageArgs());
-            return x;
-        }
-    }
-
-    @Specialization(guards = "isNotHandled(x)")
-    public Object handleOthers(Object x) {
-        try {
-            return noHead ? x : wrappedHead.execute(x);
-        } catch (PipelineReturnException ret) {
-            return ret.getResult();
-        }
-    }
-
-    protected boolean isNotHandled(Object x) {
-        return x != RNull.instance && x != RMissing.instance;
-    }
-
-    public static CastNode create(PipelineConfig pipelineConfig, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNodeWithDefault) {
-        return BypassNodeGen.create(pipelineConfig, wrappedHead, mapperFactory, directFindFirstNodeWithDefault, null);
-    }
-
-    public abstract static class BypassIntegerNode extends BypassNode {
-        public BypassIntegerNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode,
-                        CastNode afterFindFirst) {
-            super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst);
-        }
-
-        @Specialization
-        protected Object bypassInteger(int x) {
-            return executeAfterFindFirst(x);
-        }
-
-        @Override
-        protected boolean isNotHandled(Object x) {
-            return super.isNotHandled(x) && !(x instanceof Integer);
-        }
-    }
-
-    public abstract static class BypassDoubleNode extends BypassNode {
-        public BypassDoubleNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode,
-                        CastNode afterFindFirst) {
-            super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst);
-        }
-
-        @Specialization
-        public Object bypassDouble(double x) {
-            return executeAfterFindFirst(x);
-        }
-
-        @Override
-        protected boolean isNotHandled(Object x) {
-            return super.isNotHandled(x) && !(x instanceof Integer);
-        }
-    }
-
-    public abstract static class BypassStringNode extends BypassNode {
-        public BypassStringNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode,
-                        CastNode afterFindFirst) {
-            super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst);
-        }
-
-        @Specialization
-        public Object bypassString(String x) {
-            return executeAfterFindFirst(x);
-        }
-
-        @Override
-        protected boolean isNotHandled(Object x) {
-            return super.isNotHandled(x) && !(x instanceof String);
-        }
-    }
-
-    public abstract static class BypassLogicalMapToBooleanNode extends BypassNode {
-        public BypassLogicalMapToBooleanNode(PipelineConfig pcb, CastNode wrappedHead, ArgumentMapperFactory mapperFactory, CastNode directFindFirstNode,
-                        CastNode afterFindFirst) {
-            super(pcb, wrappedHead, mapperFactory, directFindFirstNode, afterFindFirst);
-        }
-
-        @Specialization
-        public boolean bypassLogical(byte x) {
-            return RRuntime.fromLogical(x);
-        }
-
-        @Override
-        protected boolean isNotHandled(Object x) {
-            return super.isNotHandled(x) && !(x instanceof Byte);
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
index f57e27e31b..fb0da67ec9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.r.nodes.unary.ConditionalMapNode.PipelineReturnException;
 
 @NodeInfo(cost = NodeCost.NONE)
 public final class ChainedCastNode extends CastNode {
@@ -33,22 +34,21 @@ public final class ChainedCastNode extends CastNode {
         CastNode create();
     }
 
-    private final CastNodeFactory firstCastFact;
-    private final CastNodeFactory secondCastFact;
-
     @Child private CastNode firstCast;
     @Child private CastNode secondCast;
 
-    public ChainedCastNode(CastNodeFactory firstCastFact, CastNodeFactory secondCastFact) {
-        this.firstCastFact = firstCastFact;
-        this.secondCastFact = secondCastFact;
-        this.firstCast = firstCastFact.create();
-        this.secondCast = secondCastFact.create();
+    public ChainedCastNode(CastNode firstCast, CastNode secondCast) {
+        this.firstCast = firstCast;
+        this.secondCast = secondCast;
     }
 
     @Override
     public Object execute(Object value) {
-        return secondCast.execute(firstCast.execute(value));
+        try {
+            return secondCast.execute(firstCast.execute(value));
+        } catch (PipelineReturnException ex) {
+            return ex.getResult();
+        }
     }
 
     public CastNode getFirstCast() {
@@ -58,12 +58,4 @@ public final class ChainedCastNode extends CastNode {
     public CastNode getSecondCast() {
         return secondCast;
     }
-
-    public CastNodeFactory getFirstCastFact() {
-        return firstCastFact;
-    }
-
-    public CastNodeFactory getSecondCastFact() {
-        return secondCastFact;
-    }
 }
-- 
GitLab


From 95e140f5832c5109ed5fe5b7512f888428c1cf14 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Feb 2017 11:24:31 +0100
Subject: [PATCH 054/402] cleanups in cast API

---
 .../truffle/r/nodes/builtin/base/Sample.java  |  4 +-
 .../truffle/r/nodes/builtin/base/Sample2.java |  4 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |  2 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |  9 +--
 .../r/nodes/builtin/base/Substitute.java      |  2 +-
 .../r/nodes/builtin/CastBuilderTest.java      |  2 +-
 .../truffle/r/nodes/casts/MarkLookup.java     | 12 ----
 .../r/nodes/casts/ResultTypesAnalyser.java    | 12 ----
 .../r/nodes/casts/SamplesCollector.java       | 16 -----
 .../r/nodes/binary/BoxPrimitiveNode.java      |  2 -
 .../truffle/r/nodes/builtin/CastBuilder.java  | 10 +--
 .../truffle/r/nodes/builtin/casts/Filter.java |  2 +-
 .../r/nodes/builtin/casts/MessageData.java    | 22 +++---
 .../r/nodes/builtin/casts/PipelineStep.java   | 48 +------------
 .../builtin/casts/PipelineToCastNode.java     | 57 +++++-----------
 .../analysis/ForwardedValuesAnalyser.java     | 12 ----
 .../builtin/casts/fluent/ArgCastBuilder.java  | 15 -----
 .../casts/fluent/FindFirstNodeBuilder.java    | 12 +---
 .../builtin/casts/fluent/PipelineBuilder.java | 10 ---
 .../casts/fluent/PreinitialPhaseBuilder.java  |  7 +-
 .../truffle/r/nodes/unary/CastNode.java       | 46 +++++++------
 .../r/nodes/unary/ConditionalMapNode.java     | 67 +++++--------------
 .../truffle/r/nodes/unary/FilterNode.java     | 51 +++++---------
 .../truffle/r/nodes/unary/FindFirstNode.java  | 22 +++---
 .../truffle/r/nodes/unary/NonNANode.java      | 19 ++----
 25 files changed, 119 insertions(+), 346 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
index 961dd4dfee..995836e400 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
@@ -58,8 +58,8 @@ public abstract class Sample extends RBuiltinNode {
         casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, VECTOR_SIZE_NA_NAN).mapIf(doubleValue(),
                         chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), SHOW_CALLER, VECTOR_SIZE_NA_NAN)).with(
                                         mustBe(lt(4.5e15), SHOW_CALLER, VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0());
-        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().defaultError(SHOW_CALLER,
-                        INVALID_ARGUMENT, "size").notNA().mustBe(gte0());
+        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().notNA(SHOW_CALLER,
+                        INVALID_ARGUMENT, "size").mustBe(gte0(), SHOW_CALLER, INVALID_ARGUMENT, "size");
         casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().notNA().map(toBoolean());
         casts.arg("prob").asDoubleVector();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
index 57c65861aa..647d0c919f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
@@ -50,8 +50,8 @@ public abstract class Sample2 extends RBuiltinNode {
         Casts casts = new Casts(Sample2.class);
         casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER,
                         INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(gte(0.0)).mustBe(isFinite());
-        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().defaultError(SHOW_CALLER, INVALID_ARGUMENT,
-                        "size").notNA().mustBe(gte0());
+        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().notNA(SHOW_CALLER, INVALID_ARGUMENT,
+                        "size").mustBe(gte0(), SHOW_CALLER, INVALID_ARGUMENT, "size");
     }
 
     @Specialization(guards = "x > MAX_INT")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index d80ec47fd7..760cde6682 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -110,7 +110,7 @@ public abstract class Scan extends RBuiltinNode {
 
         casts.arg("sep").allowNull().mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value");
 
-        casts.arg("dec").allowNull().defaultError(RError.Message.INVALID_DECIMAL_SEP).mustBe(stringValue()).asStringVector().findFirst(".").mustBe(length(1),
+        casts.arg("dec").defaultError(RError.Message.INVALID_DECIMAL_SEP).allowNull().mustBe(stringValue()).asStringVector().findFirst(".").mustBe(length(1),
                         RError.Message.MUST_BE_ONE_BYTE, "'sep' value");
 
         casts.arg("quote").defaultError(RError.Message.INVALID_QUOTE_SYMBOL).mapNull(constant("")).mustBe(stringValue()).asStringVector().findFirst("");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 15e86c28fb..9ab484de26 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -357,13 +357,8 @@ public final class SeqFunctions {
         }
 
         CastNode createLengthResultCast() {
-            // @formatter:off
-            return newCastBuilder().asIntegerVector(false, false, false).
-                    defaultError(NO_CALLER, Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).
-                    findFirst().
-                    mustBe(gte(0).and(notIntNA())).
-                    buildCastNode();
-            // @formatter:on
+            return newCastBuilder().defaultError(NO_CALLER, Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).asIntegerVector(false, false, false).findFirst().mustBe(
+                            gte(0).and(notIntNA())).buildCastNode();
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
index af511fd6c2..936b647364 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
@@ -54,7 +54,7 @@ public abstract class Substitute extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Substitute.class);
-        casts.arg(1).allowNullAndMissing().defaultError(INVALID_ENVIRONMENT_SPECIFIED).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class)));
+        casts.arg(1).defaultError(INVALID_ENVIRONMENT_SPECIFIED).allowNullAndMissing().mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class)));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
index 9e37d05542..a51b5f5d90 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
@@ -324,7 +324,7 @@ public class CastBuilderTest {
     @Test
     public void testFindFirstWithDefaultError() {
         // findFirst takes the explicitly specified default error from pipeline
-        arg.asIntegerVector().defaultError(SHOW_CALLER, RError.Message.SEED_NOT_VALID_INT).findFirst();
+        arg.defaultError(SHOW_CALLER, RError.Message.SEED_NOT_VALID_INT).asIntegerVector().findFirst();
         assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message);
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
index 2e6b1af9bb..f68d4c1331 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
@@ -50,8 +50,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -135,16 +133,6 @@ public final class MarkLookup implements PipelineStepVisitor<Map<String, Object>
         return foundMarks;
     }
 
-    @Override
-    public Map<String, Object> visit(DefaultErrorStep<?> step, Map<String, Object> foundMarks) {
-        return foundMarks;
-    }
-
-    @Override
-    public Map<String, Object> visit(DefaultWarningStep<?> step, Map<String, Object> foundMarks) {
-        return foundMarks;
-    }
-
     @Override
     public Map<String, Object> visit(BoxPrimitiveStep<?> step, Map<String, Object> foundMarks) {
         return foundMarks;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
index 5df10cc4e0..782929e761 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
@@ -58,8 +58,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -240,16 +238,6 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<TypeExpr> implemen
         return resType;
     }
 
-    @Override
-    public TypeExpr visit(DefaultErrorStep<?> step, TypeExpr inputType) {
-        return inputType;
-    }
-
-    @Override
-    public TypeExpr visit(DefaultWarningStep<?> step, TypeExpr inputType) {
-        return inputType;
-    }
-
     @Override
     public TypeExpr visit(BoxPrimitiveStep<?> step, TypeExpr inputType) {
         TypeExpr noPrimType = atom(Integer.class).not().and(atom(Byte.class).not()).and(atom(Double.class).not()).and(atom(String.class).not());
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
index ed55cf5d82..e4a2b528cb 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
@@ -55,8 +55,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -170,20 +168,6 @@ public class SamplesCollector extends ExecutionPathVisitor<Consumer<Object>>
         };
     }
 
-    @Override
-    public Consumer<Object> visit(DefaultErrorStep<?> step, Consumer<Object> previous) {
-        return s -> {
-            previous.accept(s);
-        };
-    }
-
-    @Override
-    public Consumer<Object> visit(DefaultWarningStep<?> step, Consumer<Object> previous) {
-        return s -> {
-            previous.accept(s);
-        };
-    }
-
     @Override
     public Consumer<Object> visit(BoxPrimitiveStep<?> step, Consumer<Object> previous) {
         previous.accept(0);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java
index 944c3574d9..b00a944834 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BoxPrimitiveNode.java
@@ -28,8 +28,6 @@ import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 976a9281b7..c511166d15 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -292,7 +292,7 @@ public final class CastBuilder {
         }
 
         public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter) {
-            return mustBe(argFilter, null, null);
+            return new FilterStep<>(argFilter, null, false);
         }
 
         public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
@@ -300,7 +300,7 @@ public final class CastBuilder {
         }
 
         public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter) {
-            return shouldBe(argFilter, null, null);
+            return new FilterStep<>(argFilter, null, true);
         }
 
         public static <T, R> PipelineStep<T, R> map(Mapper<T, R> mapper) {
@@ -440,7 +440,7 @@ public final class CastBuilder {
          * call for {@code xyzElement()}.
          */
         public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) {
-            return new FindFirstNodeBuilder(callObj, message, messageArgs);
+            return new FindFirstNodeBuilder(new MessageData(callObj, message, messageArgs));
         }
 
         /**
@@ -448,7 +448,7 @@ public final class CastBuilder {
          * call for {@code xyzElement()}.
          */
         public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RError.Message message, Object... messageArgs) {
-            return new FindFirstNodeBuilder(null, message, messageArgs);
+            return new FindFirstNodeBuilder(new MessageData(null, message, messageArgs));
         }
 
         /**
@@ -456,7 +456,7 @@ public final class CastBuilder {
          * call for {@code xyzElement()}.
          */
         public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst() {
-            return new FindFirstNodeBuilder(null, null, null);
+            return new FindFirstNodeBuilder(null);
         }
 
         public static <T> PipelineStep<T, T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
index 4771b0097c..d9234e2354 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
@@ -574,7 +574,7 @@ public abstract class Filter<T, R extends T> {
      * The <code>FALSE</code>, resp. <code>TRUE</code>, indicates that the filter will always return
      * <code>false</code>, resp. <code>true</code>, for the given input value.
      * <p>
-     * The <code>UNSUPPORTED</code> indicates that the the given input value is out of the filter's
+     * The <code>UNDEFINED</code> indicates that the the given input value is out of the filter's
      * domain.
      *
      * @see Filter#resultForNull()
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
index d82b22e6c4..1639997b9f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
@@ -22,15 +22,14 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts;
 
-import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Value type that holds data necessary for error/warning message from a cast pipeline.
  */
-@ValueType
 public final class MessageData {
     private final RBaseNode callObj;
     private final RError.Message message;
@@ -40,6 +39,7 @@ public final class MessageData {
         this.callObj = callObj;
         this.message = message;
         this.messageArgs = messageArgs;
+        assert message != null;
     }
 
     public RBaseNode getCallObj() {
@@ -54,19 +54,15 @@ public final class MessageData {
         return messageArgs;
     }
 
-    public MessageData fixCallObj(RBaseNode callObjFix) {
-        if (callObj == null) {
-            return new MessageData(callObjFix, message, messageArgs);
-        } else {
-            return this;
-        }
-    }
-
     /**
      * Helper method for operation that is often performed with {@link MessageData}.
      */
-    public static MessageData getFirstNonNull(MessageData first, MessageData second, MessageData third) {
-        assert third != null : "at least the last one must not be null";
-        return first != null && first.getMessage() != null ? first : second != null && second.getMessage() != null ? second : third;
+    public static MessageData getFirstNonNull(MessageData... messages) {
+        for (MessageData message : messages) {
+            if (message != null) {
+                return message;
+            }
+        }
+        throw RInternalError.shouldNotReachHere("at least the last message must not be null");
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index e5481ded2c..cf58d823b6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -73,55 +73,11 @@ public abstract class PipelineStep<T, R> {
 
         T visit(NotNAStep<?> step, T previous);
 
-        T visit(DefaultErrorStep<?> step, T previous);
-
-        T visit(DefaultWarningStep<?> step, T previous);
-
         T visit(BoxPrimitiveStep<?> step, T previous);
 
         T visit(AttributableCoercionStep<?> step, T previous);
     }
 
-    /**
-     * Changes the current default error, which is used by steps/filters that do not have error
-     * message set explicitly.
-     */
-    public abstract static class DefaultMessageStep<T> extends PipelineStep<T, T> {
-        private final MessageData defaultMessage;
-
-        public DefaultMessageStep(MessageData defaultMessage) {
-            this.defaultMessage = defaultMessage;
-        }
-
-        public MessageData getDefaultMessage() {
-            return defaultMessage;
-        }
-    }
-
-    public static final class DefaultErrorStep<T> extends DefaultMessageStep<T> {
-
-        public DefaultErrorStep(MessageData defaultMessage) {
-            super(defaultMessage);
-        }
-
-        @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
-            return visitor.visit(this, previous);
-        }
-    }
-
-    public static final class DefaultWarningStep<T> extends DefaultMessageStep<T> {
-
-        public DefaultWarningStep(MessageData defaultMessage) {
-            super(defaultMessage);
-        }
-
-        @Override
-        public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
-            return visitor.visit(this, previous);
-        }
-    }
-
     /**
      * Boxes all primitive types (integer, string, double, byte) to {@link RAbstractVector}.
      */
@@ -165,8 +121,8 @@ public abstract class PipelineStep<T, R> {
      * the vector is empty, the message is used as a warning. If only default value is provided,
      * then if the vector is empty, the default value is returned without any warning. If the
      * default value is not provided, then error is raised if the vector is empty, the error message
-     * chosen in the following order: provided message, explicitly set default error message using
-     * {@link PipelineStep.DefaultErrorStep}, default find first message.
+     * chosen in the following order: provided message, explicitly set default error message,
+     * default find first message.
      */
     public static final class FindFirstStep<V, E> extends PipelineStep<V, E> {
         private final MessageData error;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 815b34ee45..728e2bd70d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -56,8 +56,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapperVisitor;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -123,7 +121,7 @@ public final class PipelineToCastNode {
         boolean singleMapStep = firstStepIn.getNext() == null && firstStepIn instanceof MapIfStep;
         PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep) firstStepIn).withoutReturns() : firstStepIn;
 
-        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultDefaultMessage()));
+        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage()));
 
         if (!config.getValueForwarding()) {
             return originalPipelineFactory.get();
@@ -168,36 +166,15 @@ public final class PipelineToCastNode {
         private final ArgumentMapperFactory mapperFactory;
         private boolean boxPrimitives = false;
 
-        /**
-         * Should be used when {@link #defaultError} or {@link #defaultWarning} are not explicitly
-         * set by visiting {@link DefaultErrorStep}.
-         */
-        private final MessageData defaultMessage;
+        private final MessageData defaultError;
+        private final MessageData defaultWarning;
 
-        /**
-         * Use {@link #getDefaultErrorIfNull} and {@link #getDefaultWarningIfNull} to always get a
-         * non-null message - they supply {@link #defaultMessage} if there is no explicitly set.
-         */
-        private MessageData defaultError;
-        private MessageData defaultWarning;
-
-        CastNodeFactory(ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory, MessageData defaultMessage) {
+        CastNodeFactory(ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory, MessageData defaultError, MessageData defaultWarning, MessageData defaultMessage) {
             assert defaultMessage != null : "defaultMessage is null";
             this.filterFactory = filterFactory;
             this.mapperFactory = mapperFactory;
-            this.defaultMessage = defaultMessage;
-        }
-
-        @Override
-        public CastNode visit(DefaultErrorStep<?> step, CastNode previous) {
-            defaultError = step.getDefaultMessage();
-            return null;
-        }
-
-        @Override
-        public CastNode visit(DefaultWarningStep<?> step, CastNode previous) {
-            defaultWarning = step.getDefaultMessage();
-            return null;
+            this.defaultError = MessageData.getFirstNonNull(defaultError, defaultMessage);
+            this.defaultWarning = MessageData.getFirstNonNull(defaultWarning, defaultMessage);
         }
 
         @Override
@@ -216,22 +193,23 @@ public final class PipelineToCastNode {
                     // Note: intentional direct use of defaultError
                     msg = defaultError != null ? defaultError : new MessageData(null, RError.Message.LENGTH_ZERO);
                 }
-                return FindFirstNodeGen.create(step.getElementClass(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getDefaultValue());
+                return FindFirstNodeGen.create(step.getElementClass(), msg, step.getDefaultValue());
             } else {
                 MessageData warning = step.getError();
                 if (warning == null) {
                     return FindFirstNodeGen.create(step.getElementClass(), step.getDefaultValue());
                 } else {
-                    return FindFirstNodeGen.create(step.getElementClass(), warning.getCallObj(), warning.getMessage(), warning.getMessageArgs(), step.getDefaultValue());
+                    return FindFirstNodeGen.create(step.getElementClass(), warning, step.getDefaultValue());
                 }
             }
         }
 
         @Override
         public CastNode visit(FilterStep<?, ?> step, CastNode previous) {
-            ArgumentFilter<?, ?> filter = filterFactory.createFilter(step.getFilter());
+            @SuppressWarnings("unchecked")
+            ArgumentFilter<Object, Object> filter = (ArgumentFilter<Object, Object>) filterFactory.createFilter(step.getFilter());
             MessageData msg = getDefaultIfNull(step.getMessage(), step.isWarning());
-            return FilterNode.create(filter, step.isWarning(), msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), boxPrimitives, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
+            return FilterNode.create(filter, step.isWarning(), msg, boxPrimitives, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
                             ResultForArg.TRUE.equals(step.getFilter().resultForMissing()));
         }
 
@@ -239,13 +217,13 @@ public final class PipelineToCastNode {
         public CastNode visit(NotNAStep<?> step, CastNode previous) {
             if (step.getReplacement() == null) {
                 MessageData msg = getDefaultErrorIfNull(step.getMessage());
-                return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement());
+                return NonNANodeGen.create(msg, step.getReplacement());
             } else {
                 MessageData msg = step.getMessage();
                 if (msg == null) {
-                    return NonNANodeGen.create(null, null, null, step.getReplacement());
+                    return NonNANodeGen.create(null, step.getReplacement());
                 } else {
-                    return NonNANodeGen.create(msg.getCallObj(), msg.getMessage(), msg.getMessageArgs(), step.getReplacement());
+                    return NonNANodeGen.create(msg, step.getReplacement());
                 }
             }
         }
@@ -291,7 +269,8 @@ public final class PipelineToCastNode {
 
         @Override
         public CastNode visit(MapIfStep<?, ?> step, CastNode previous) {
-            ArgumentFilter<?, ?> condition = filterFactory.createFilter(step.getFilter());
+            @SuppressWarnings("unchecked")
+            ArgumentFilter<Object, Object> condition = (ArgumentFilter<Object, Object>) filterFactory.createFilter(step.getFilter());
             CastNode trueCastNode = PipelineToCastNode.convert(step.getTrueBranch(), this);
             CastNode falseCastNode = PipelineToCastNode.convert(step.getFalseBranch(), this);
             return ConditionalMapNode.create(condition, trueCastNode, falseCastNode, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
@@ -299,11 +278,11 @@ public final class PipelineToCastNode {
         }
 
         private MessageData getDefaultErrorIfNull(MessageData message) {
-            return MessageData.getFirstNonNull(message, defaultError, defaultMessage);
+            return MessageData.getFirstNonNull(message, defaultError);
         }
 
         private MessageData getDefaultWarningIfNull(MessageData message) {
-            return MessageData.getFirstNonNull(message, defaultWarning, defaultMessage);
+            return MessageData.getFirstNonNull(message, defaultWarning);
         }
 
         private MessageData getDefaultIfNull(MessageData message, boolean isWarning) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
index bc78432499..e85a6f5363 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
@@ -52,8 +52,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.BoxPrimitiveStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -291,16 +289,6 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
         return result;
     }
 
-    @Override
-    public ForwardingAnalysisResult visit(DefaultErrorStep<?> step, ForwardingAnalysisResult previous) {
-        return result;
-    }
-
-    @Override
-    public ForwardingAnalysisResult visit(DefaultWarningStep<?> step, ForwardingAnalysisResult previous) {
-        return result;
-    }
-
     @Override
     public ForwardingAnalysisResult visit(BoxPrimitiveStep<?> step, ForwardingAnalysisResult previous) {
         // TODO
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
index 4d2390aeb5..739b5aafc7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
@@ -46,21 +46,6 @@ public class ArgCastBuilder<T, THIS> {
         return builder;
     }
 
-    public THIS defaultError(RBaseNode callObj, RError.Message message, Object... args) {
-        pipelineBuilder().appendDefaultErrorStep(callObj, message, args);
-        return (THIS) this;
-    }
-
-    public THIS defaultError(RError.Message message, Object... args) {
-        defaultError(null, message, args);
-        return (THIS) this;
-    }
-
-    public THIS defaultWarning(RBaseNode callObj, RError.Message message, Object... args) {
-        pipelineBuilder().appendDefaultWarningStep(callObj, message, args);
-        return (THIS) this;
-    }
-
     public THIS shouldBe(Filter<? super T, ?> argFilter, RError.Message message, Object... messageArgs) {
         pipelineBuilder().appendShouldBeStep(argFilter, message, messageArgs);
         return (THIS) this;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java
index 28c5619018..359c638900 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
-import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -33,25 +32,20 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Allows to convert find first into a valid step when used in {@code chain}, for example
  * {@code chain(findFirst().stringElement())}.
  */
 public final class FindFirstNodeBuilder {
-    private final RBaseNode callObj;
-    private final Message message;
-    private final Object[] messageArgs;
+    private final MessageData message;
 
-    public FindFirstNodeBuilder(RBaseNode callObj, Message message, Object[] messageArgs) {
-        this.callObj = callObj;
+    public FindFirstNodeBuilder(MessageData message) {
         this.message = message;
-        this.messageArgs = messageArgs;
     }
 
     private <V, E> PipelineStep<V, E> create(Class<?> elementClass, Object defaultValue) {
-        return new FindFirstStep<>(defaultValue, elementClass, new MessageData(callObj, message, messageArgs));
+        return new FindFirstStep<>(defaultValue, elementClass, message);
     }
 
     public PipelineStep<RAbstractLogicalVector, Byte> logicalElement() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index c1780b2829..2d98ed5f3f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -31,8 +31,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.AttributableCoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultErrorStep;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.DefaultWarningStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
@@ -130,14 +128,6 @@ public final class PipelineBuilder {
         append(new FilterStep<>(argFilter, createMessage(callObj, message, messageArgs), true));
     }
 
-    public void appendDefaultWarningStep(RBaseNode callObj, Message message, Object[] args) {
-        append(new DefaultWarningStep<>(createMessage(callObj, message, args)));
-    }
-
-    public void appendDefaultErrorStep(RBaseNode callObj, Message message, Object[] args) {
-        append(new DefaultErrorStep<>(createMessage(callObj, message, args)));
-    }
-
     private static MessageData createMessage(RBaseNode callObj, Message message, Object[] messageArgs) {
         return message == null ? null : new MessageData(callObj, message, messageArgs);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
index 8cd3486523..3f06baa1eb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Adds methods to {@link InitialPhaseBuilder} that allow to set up the pipeline configuration.
- * Invocation of some methods means that the pre-initilization phase has been finishes, i.e.
+ * Invocation of some methods means that the pre-initialization phase has been finishes, i.e.
  * pipeline fully configured, those methods return this object cast to {@link InitialPhaseBuilder}
  * so that user then cannot invoke methods that change the pipeline configuration. Any method from
  * {@link InitialPhaseBuilder} returns that type, so once the user steps outside the configuration,
@@ -98,23 +98,18 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> {
         return returnIf(nullValue().or(missingValue()));
     }
 
-    @Override
     public PreinitialPhaseBuilder defaultError(RBaseNode callObj, RError.Message message, Object... args) {
         pipelineBuilder().getPipelineConfig().setDefaultError(new MessageData(callObj, message, args));
-        pipelineBuilder().appendDefaultErrorStep(callObj, message, args);
         return this;
     }
 
-    @Override
     public PreinitialPhaseBuilder defaultError(Message message, Object... args) {
         defaultError(null, message, args);
         return this;
     }
 
-    @Override
     public PreinitialPhaseBuilder defaultWarning(RBaseNode callObj, Message message, Object... args) {
         pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(callObj, message, args));
-        pipelineBuilder().appendDefaultWarningStep(callObj, message, args);
         return this;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
index 628447faf3..3bcca2434f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -54,39 +55,42 @@ public abstract class CastNode extends UnaryNode {
         lastWarning = null;
     }
 
+    @SuppressWarnings({"unchecked"})
+    private static Object[] substituteArgs(Object arg, MessageData message) {
+        Object[] messageArgs = message.getMessageArgs();
+        Object[] newMsgArgs = Arrays.copyOf(messageArgs, messageArgs.length);
+
+        for (int i = 0; i < messageArgs.length; i++) {
+            final Object msgArg = messageArgs[i];
+            if (msgArg instanceof Function) {
+                newMsgArgs[i] = ((Function<Object, Object>) msgArg).apply(arg);
+            }
+        }
+        return newMsgArgs;
+    }
+
+    private RBaseNode getCallObj(MessageData message) {
+        return message.getCallObj() == null ? this : message.getCallObj();
+    }
+
     @TruffleBoundary
-    protected static void handleArgumentError(Object arg, RBaseNode callObj, RError.Message message, Object[] messageArgs) {
+    protected RuntimeException handleArgumentError(Object arg, MessageData message) {
         if (isTesting) {
-            throw new IllegalArgumentException(String.format(message.message, substituteArgPlaceholder(arg, messageArgs)));
+            throw new IllegalArgumentException(String.format(message.getMessage().message, substituteArgs(arg, message)));
         } else {
-            throw RError.error(callObj, message, substituteArgPlaceholder(arg, messageArgs));
+            throw RError.error(getCallObj(message), message.getMessage(), substituteArgs(arg, message));
         }
     }
 
     @TruffleBoundary
-    protected static void handleArgumentWarning(Object arg, RBaseNode callObj, RError.Message message, Object[] messageArgs) {
+    protected void handleArgumentWarning(Object arg, MessageData message) {
         if (message == null) {
             return;
         }
-
         if (isTesting) {
-            lastWarning = String.format(message.message, substituteArgPlaceholder(arg, messageArgs));
+            lastWarning = String.format(message.getMessage().message, substituteArgs(arg, message));
         } else {
-            RError.warning(callObj, message, substituteArgPlaceholder(arg, messageArgs));
-        }
-    }
-
-    @SuppressWarnings({"unchecked"})
-    public static Object[] substituteArgPlaceholder(Object arg, Object[] messageArgs) {
-        Object[] newMsgArgs = Arrays.copyOf(messageArgs, messageArgs.length);
-
-        for (int i = 0; i < messageArgs.length; i++) {
-            final Object msgArg = messageArgs[i];
-            if (msgArg instanceof Function) {
-                newMsgArgs[i] = ((Function<Object, Object>) msgArg).apply(arg);
-            }
+            RError.warning(getCallObj(message), message.getMessage(), substituteArgs(arg, message));
         }
-
-        return newMsgArgs;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java
index 081b1bc06a..862aff020d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConditionalMapNode.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ControlFlowException;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -31,8 +32,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 public abstract class ConditionalMapNode extends CastNode {
 
-    private final ArgumentFilter<?, ?> argFilter;
-    private final ConditionProfile conditionProfile = ConditionProfile.createBinaryProfile();
+    private final ArgumentFilter<Object, Object> argFilter;
     private final boolean resultForNull;
     private final boolean resultForMissing;
     private final boolean returns;
@@ -40,8 +40,7 @@ public abstract class ConditionalMapNode extends CastNode {
     @Child private CastNode trueBranch;
     @Child private CastNode falseBranch;
 
-    protected ConditionalMapNode(ArgumentFilter<?, ?> argFilter, CastNode trueBranch, CastNode falseBranch, boolean resultForNull,
-                    boolean resultForMissing, boolean returns) {
+    protected ConditionalMapNode(ArgumentFilter<Object, Object> argFilter, CastNode trueBranch, CastNode falseBranch, boolean resultForNull, boolean resultForMissing, boolean returns) {
         this.argFilter = argFilter;
         this.trueBranch = trueBranch;
         this.falseBranch = falseBranch;
@@ -50,31 +49,12 @@ public abstract class ConditionalMapNode extends CastNode {
         this.returns = returns;
     }
 
-    public static ConditionalMapNode create(ArgumentFilter<?, ?> argFilter, CastNode trueBranch,
-                    CastNode falseBranch, boolean resultForNull,
-                    boolean resultForMissing, boolean returns) {
+    public static ConditionalMapNode create(ArgumentFilter<Object, Object> argFilter, CastNode trueBranch, CastNode falseBranch, boolean resultForNull, boolean resultForMissing, boolean returns) {
         return ConditionalMapNodeGen.create(argFilter, trueBranch, falseBranch, resultForNull, resultForMissing, returns);
     }
 
-    public boolean isReturns() {
-        return returns;
-    }
-
-    public ArgumentFilter<?, ?> getFilter() {
-        return argFilter;
-    }
-
-    public CastNode getTrueBranch() {
-        return trueBranch;
-    }
-
-    public CastNode getFalseBranch() {
-        return falseBranch;
-    }
-
-    @Specialization
-    protected Object executeNull(RNull x) {
-        if (resultForNull) {
+    private Object executeConditional(boolean isTrue, Object x) {
+        if (isTrue) {
             Object result = trueBranch == null ? x : trueBranch.execute(x);
             if (returns) {
                 throw new PipelineReturnException(result);
@@ -87,36 +67,19 @@ public abstract class ConditionalMapNode extends CastNode {
     }
 
     @Specialization
-    protected Object executeMissing(RMissing x) {
-        if (resultForMissing) {
-            Object result = trueBranch == null ? x : trueBranch.execute(x);
-            if (returns) {
-                throw new PipelineReturnException(result);
-            } else {
-                return result;
-            }
-        } else {
-            return falseBranch == null ? x : falseBranch.execute(x);
-        }
+    protected Object executeNull(RNull x) {
+        return executeConditional(resultForNull, x);
     }
 
-    protected static boolean isNotNullOrMissing(Object x) {
-        return x != RNull.instance && x != RMissing.instance;
+    @Specialization
+    protected Object executeMissing(RMissing x) {
+        return executeConditional(resultForMissing, x);
     }
 
-    @Specialization(guards = "isNotNullOrMissing(x)")
-    @SuppressWarnings("unchecked")
-    protected Object executeRest(Object x) {
-        if (conditionProfile.profile(((ArgumentFilter<Object, Object>) argFilter).test(x))) {
-            Object result = trueBranch == null ? x : trueBranch.execute(x);
-            if (returns) {
-                throw new PipelineReturnException(result);
-            } else {
-                return result;
-            }
-        } else {
-            return falseBranch == null ? x : falseBranch.execute(x);
-        }
+    @Specialization(guards = {"!isRNull(x)", "!isRMissing(x)"})
+    protected Object executeRest(Object x,
+                    @Cached("createBinaryProfile()") ConditionProfile conditionProfile) {
+        return executeConditional(conditionProfile.profile(argFilter.test(x)), x);
     }
 
     @SuppressWarnings("serial")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java
index 779c4f1477..cc825844e8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FilterNode.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -29,62 +30,45 @@ import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
 import com.oracle.truffle.r.nodes.builtin.ArgumentFilter;
-import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-@SuppressWarnings({"rawtypes", "unchecked"})
 public abstract class FilterNode extends CastNode {
 
-    private final ArgumentFilter filter;
-    private final RError.Message message;
-    private final RBaseNode callObj;
-    private final Object[] messageArgs;
-    private final boolean boxPrimitives;
+    private final ArgumentFilter<Object, Object> filter;
+    private final MessageData message;
     private final boolean isWarning;
     private final boolean resultForNull;
     private final boolean resultForMissing;
 
     private final BranchProfile warningProfile = BranchProfile.create();
-    private final ConditionProfile conditionProfile = ConditionProfile.createBinaryProfile();
     private final ValueProfile valueProfile = ValueProfile.createClassProfile();
 
-    @Child private BoxPrimitiveNode boxPrimitiveNode = BoxPrimitiveNodeGen.create();
+    @Child private BoxPrimitiveNode boxPrimitiveNode;
 
-    protected FilterNode(ArgumentFilter<?, ?> filter, boolean isWarning, RBaseNode callObj, RError.Message message, Object[] messageArgs, boolean boxPrimitives, boolean resultForNull,
-                    boolean resultForMissing) {
+    protected FilterNode(ArgumentFilter<Object, Object> filter, boolean isWarning, MessageData message, boolean boxPrimitives, boolean resultForNull, boolean resultForMissing) {
         this.filter = filter;
         this.isWarning = isWarning;
-        this.callObj = callObj == null ? this : callObj;
+        assert message != null;
         this.message = message;
-        this.messageArgs = messageArgs;
-        this.boxPrimitives = boxPrimitives;
+        this.boxPrimitiveNode = boxPrimitives ? BoxPrimitiveNodeGen.create() : null;
         this.resultForNull = resultForNull;
         this.resultForMissing = resultForMissing;
     }
 
-    public static FilterNode create(ArgumentFilter<?, ?> filter, boolean isWarning, RBaseNode callObj, RError.Message message, Object[] messageArgs, boolean boxPrimitives, boolean resultForNull,
-                    boolean resultForMissing) {
-        return FilterNodeGen.create(filter, isWarning, callObj, message, messageArgs, boxPrimitives, resultForNull, resultForMissing);
-    }
-
-    public ArgumentFilter getFilter() {
-        return filter;
-    }
-
-    public boolean isWarning() {
-        return isWarning;
+    public static FilterNode create(ArgumentFilter<Object, Object> filter, boolean isWarning, MessageData message, boolean boxPrimitives, boolean resultForNull, boolean resultForMissing) {
+        return FilterNodeGen.create(filter, isWarning, message, boxPrimitives, resultForNull, resultForMissing);
     }
 
     private void handleMessage(Object x) {
         if (isWarning) {
             if (message != null) {
                 warningProfile.enter();
-                handleArgumentWarning(x, callObj, message, messageArgs);
+                handleArgumentWarning(x, message);
             }
         } else {
-            handleArgumentError(x, callObj, message, messageArgs);
+            throw handleArgumentError(x, message);
         }
     }
 
@@ -104,12 +88,9 @@ public abstract class FilterNode extends CastNode {
         return x;
     }
 
-    protected static boolean isNotNullOrMissing(Object x) {
-        return x != RNull.instance && x != RMissing.instance;
-    }
-
-    @Specialization(guards = "isNotNullOrMissing(x)")
-    public Object executeRest(Object x) {
+    @Specialization(guards = {"!isRNull(x)", "!isRMissing(x)"})
+    public Object executeRest(Object x,
+                    @Cached("createBinaryProfile()") ConditionProfile conditionProfile) {
         if (!conditionProfile.profile(evalCondition(valueProfile.profile(x)))) {
             handleMessage(x);
         }
@@ -117,7 +98,7 @@ public abstract class FilterNode extends CastNode {
     }
 
     protected boolean evalCondition(Object x) {
-        Object y = boxPrimitives ? boxPrimitiveNode.execute(x) : x;
+        Object y = boxPrimitiveNode != null ? boxPrimitiveNode.execute(x) : x;
         return filter.test(y);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java
index 2aac18c22c..5fa42384ef 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FindFirstNode.java
@@ -24,36 +24,31 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class FindFirstNode extends CastNode {
 
     private final Class<?> elementClass;
-    private final RBaseNode callObj;
-    private final RError.Message message;
-    private final Object[] messageArgs;
+    private final MessageData message;
     private final Object defaultValue;
 
     private final BranchProfile warningProfile = BranchProfile.create();
 
-    protected FindFirstNode(Class<?> elementClass, RBaseNode callObj, RError.Message message, Object[] messageArgs, Object defaultValue) {
-        this.callObj = callObj == null ? this : callObj;
+    protected FindFirstNode(Class<?> elementClass, MessageData message, Object defaultValue) {
         this.elementClass = elementClass;
         this.defaultValue = defaultValue;
         this.message = message;
-        this.messageArgs = messageArgs;
     }
 
     protected FindFirstNode(Class<?> elementClass, Object defaultValue) {
-        this(elementClass, null, null, null, defaultValue);
+        this(elementClass, null, defaultValue);
     }
 
-    public static FindFirstNode create(Class<?> elementClass, RBaseNode callObj, RError.Message message, Object... args) {
-        return FindFirstNodeGen.create(elementClass, callObj, message, args, null);
+    public static FindFirstNode create(Class<?> elementClass, MessageData message) {
+        return FindFirstNodeGen.create(elementClass, message, null);
     }
 
     public Class<?> getElementClass() {
@@ -88,12 +83,11 @@ public abstract class FindFirstNode extends CastNode {
         if (defaultValue != null) {
             if (message != null) {
                 warningProfile.enter();
-                handleArgumentWarning(x, callObj, message, messageArgs);
+                handleArgumentWarning(x, message);
             }
             return defaultValue;
         } else {
-            handleArgumentError(x, callObj, message, messageArgs);
-            return null;
+            throw handleArgumentError(x, message);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java
index 397f7cb57b..3433266300 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/NonNANode.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RMissing;
@@ -36,26 +36,22 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class NonNANode extends CastNode {
 
-    private final RBaseNode callObj;
-    private final RError.Message message;
-    private final Object[] messageArgs;
+    private final MessageData message;
     private final Object naReplacement;
 
     private final BranchProfile warningProfile = BranchProfile.create();
 
-    protected NonNANode(RBaseNode callObj, RError.Message message, Object[] messageArgs, Object naReplacement) {
-        this.callObj = callObj == null ? this : callObj;
+    protected NonNANode(MessageData message, Object naReplacement) {
         this.message = message;
-        this.messageArgs = messageArgs;
         this.naReplacement = naReplacement;
+        assert message != null || naReplacement != null;
     }
 
     protected NonNANode(Object naReplacement) {
-        this(null, null, null, naReplacement);
+        this(null, naReplacement);
     }
 
     public Object getNAReplacement() {
@@ -66,12 +62,11 @@ public abstract class NonNANode extends CastNode {
         if (naReplacement != null) {
             if (message != null) {
                 warningProfile.enter();
-                handleArgumentWarning(arg, callObj, message, messageArgs);
+                handleArgumentWarning(arg, message);
             }
             return naReplacement;
         } else {
-            handleArgumentError(arg, callObj, message, messageArgs);
-            return null;
+            throw handleArgumentError(arg, message);
         }
     }
 
-- 
GitLab


From 14706b27828dc48f33929dcc9f16cf9184f904e7 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Feb 2017 13:24:37 +0100
Subject: [PATCH 055/402] always throw RError.error

---
 .../oracle/truffle/r/library/stats/Covcor.java   | 16 ++++++++--------
 .../r/nodes/builtin/base/LaFunctions.java        |  6 +++---
 .../r/nodes/builtin/base/RepeatInternal.java     |  4 ++--
 .../vector/PositionCharacterLookupNode.java      |  4 ++--
 .../nodes/access/vector/PositionsCheckNode.java  |  8 ++++----
 .../access/vector/RecursiveSubscriptNode.java    |  4 ++--
 .../r/nodes/function/CallArgumentsNode.java      |  2 +-
 .../truffle/r/runtime/nmath/distr/Signrank.java  |  2 +-
 .../truffle/r/runtime/nmath/distr/Wilcox.java    |  2 +-
 9 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index 011ee2add3..629269201a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -100,14 +100,14 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         } else if (getDimsNode.isMatrix(y)) {
             if (nrows(y) != n) {
                 error.enter();
-                error("incompatible dimensions");
+                throw error("incompatible dimensions");
             }
             ncy = ncols(y);
             ansmat = true;
         } else {
             if (y.getLength() != n) {
                 error.enter();
-                error("incompatible dimensions");
+                throw error("incompatible dimensions");
             }
             ncy = 1;
         }
@@ -125,7 +125,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
 
         if (emptyErr && x.getLength() == 0) {
             error.enter();
-            error("'x' is empty");
+            throw error("'x' is empty");
         }
 
         double[] answerData = new double[ncx * ncy];
@@ -195,7 +195,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
             for (i = 0; i < n; i++) {
                 if (Double.isNaN(x.getDataAt(j * n + i))) {
                     if (naFail) {
-                        error("missing observations in cov/cor");
+                        throw error("missing observations in cov/cor");
                     } else {
                         ind.updateDataAt(i, 0, check);
                     }
@@ -215,7 +215,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
             for (i = 0; i < n; i++) {
                 if (Double.isNaN(x.getDataAt(j * n + i))) {
                     if (naFail) {
-                        error("missing observations in cov/cor");
+                        throw error("missing observations in cov/cor");
                     } else {
                         ind.updateDataAt(i, 0, check);
                     }
@@ -228,7 +228,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
             for (i = 0; i < n; i++) {
                 if (Double.isNaN(y.getDataAt(j * n + i))) {
                     if (naFail) {
-                        error("missing observations in cov/cor");
+                        throw error("missing observations in cov/cor");
                     } else {
                         ind.updateDataAt(i, 0, check);
                     }
@@ -737,8 +737,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static void error(String message) {
-        RError.error(NO_CALLER, Message.GENERIC, message);
+    private static RuntimeException error(String message) {
+        throw RError.error(NO_CALLER, Message.GENERIC, message);
     }
 
     private boolean checkNAs(double... xs) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 571d2efef2..404b8719e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -625,10 +625,10 @@ public class LaFunctions {
             }
             int info = dgesvNode.execute(n, p, avals, n, ipiv, bData, n);
             if (info < 0) {
-                RError.error(this, RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv");
+                throw RError.error(this, RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv");
             }
             if (info > 0) {
-                RError.error(this, RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
+                throw RError.error(this, RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
             }
             if (tol > 0) {
                 double anorm = dlangeNode.execute('1', n, n, avals, n, null);
@@ -636,7 +636,7 @@ public class LaFunctions {
                 double[] rcond = new double[1];
                 dgeconNode.execute('1', n, avals, n, anorm, rcond, work, ipiv);
                 if (rcond[0] < tol) {
-                    RError.error(this, RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]);
+                    throw RError.error(this, RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]);
                 }
             }
             return b;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
index f376567ece..b49bef8a6f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
@@ -82,7 +82,7 @@ public abstract class RepeatInternal extends RBuiltinNode {
             int timesValue = times.getDataAt(0);
             if (timesValue < 0) {
                 errorProfile.enter();
-                RError.error(this, RError.Message.INVALID_VALUE, "times");
+                throw RError.error(this, RError.Message.INVALID_VALUE, "times");
             }
             int count = timesValue * valueLength;
             result = arrayConstructor.apply(count);
@@ -98,7 +98,7 @@ public abstract class RepeatInternal extends RBuiltinNode {
                 int data = times.getDataAt(i);
                 if (data < 0) {
                     errorProfile.enter();
-                    RError.error(this, RError.Message.INVALID_VALUE, "times");
+                    throw RError.error(this, RError.Message.INVALID_VALUE, "times");
                 }
                 count += data;
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java
index dbe39a3f17..d1566a34ef 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java
@@ -85,9 +85,9 @@ final class PositionCharacterLookupNode extends Node {
 
     private RError noDimNames() {
         if (mode.isSubset()) {
-            return RError.error(this, Message.NO_ARRAY_DIMNAMES);
+            throw RError.error(this, Message.NO_ARRAY_DIMNAMES);
         } else {
-            return RError.error(this, Message.SUBSCRIPT_BOUNDS);
+            throw RError.error(this, Message.SUBSCRIPT_BOUNDS);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
index 799416e640..0584507735 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
@@ -127,15 +127,15 @@ final class PositionsCheckNode extends Node {
         if (replace) {
             if (mode.isSubset()) {
                 if (getDimensions() == 2) {
-                    return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX);
+                    throw RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX);
                 } else {
-                    return RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS);
+                    throw RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS);
                 }
             } else {
-                return RError.error(this, RError.Message.IMPROPER_SUBSCRIPT);
+                throw RError.error(this, RError.Message.IMPROPER_SUBSCRIPT);
             }
         } else {
-            return RError.error(this, RError.Message.INCORRECT_DIMENSIONS);
+            throw RError.error(this, RError.Message.INCORRECT_DIMENSIONS);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
index 025d674aa9..f294ca9f1b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
@@ -51,11 +51,11 @@ abstract class RecursiveSubscriptNode extends Node {
 
     protected final RError indexingFailed(int i) {
         errorBranch.enter();
-        return RError.error(this, RError.Message.RECURSIVE_INDEXING_FAILED, i);
+        throw RError.error(this, RError.Message.RECURSIVE_INDEXING_FAILED, i);
     }
 
     protected final RError noSuchIndex(int i) {
         errorBranch.enter();
-        return RError.error(this, RError.Message.NO_SUCH_INDEX, i);
+        throw RError.error(this, RError.Message.NO_SUCH_INDEX, i);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
index 0d54c7a623..cc46a97dbc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
@@ -121,7 +121,7 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
         CompilerAsserts.neverPartOfCompilation();
         RArgsValuesAndNames varArgs = ReadVariableNode.lookupVarArgs(frame);
         if (varArgs == null) {
-            RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT);
+            throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT);
         }
         return varArgs;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java
index 2d1baf7bbb..18917863d2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java
@@ -66,7 +66,7 @@ public final class Signrank {
     }
 
     private static RError couldNotAllocateError() {
-        return RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744073172680704", 8);
+        throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744073172680704", 8);
     }
 
     private static double csignrank(double[] w, int kIn, int n) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java
index fc9e1f2ecd..eea537e0c6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java
@@ -100,7 +100,7 @@ public final class Wilcox {
 
     private static RError couldNotAllocateError() {
         // GnuR seems to be reporting the same number regardless of the actual size?
-        return RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744071562067968", 4);
+        throw RError.error(RError.SHOW_CALLER, CALLOC_COULD_NOT_ALLOCATE, "18446744071562067968", 4);
     }
 
     private static double cwilcox(double[][][] w, int kIn, int m, int n) {
-- 
GitLab


From e679a9ac1a044e85c75a5bf708e22795a19b854f Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 24 Feb 2017 11:59:07 +0100
Subject: [PATCH 056/402] introduce RBuiltinBaseNode with centralized handling
 of error contexts

---
 .../r/library/grDevices/DevicesCCalls.java    |  19 +--
 .../r/library/graphics/GraphicsCCalls.java    |  15 +--
 .../truffle/r/library/grid/GridFunctions.java |   2 +-
 .../library/methods/MethodsListDispatch.java  |  26 ++--
 .../truffle/r/library/methods/Slot.java       |   8 +-
 .../r/library/methods/SubstituteDirect.java   |   7 +-
 .../truffle/r/library/stats/BinDist.java      |   3 +-
 .../oracle/truffle/r/library/stats/Cdist.java |   8 +-
 .../r/library/stats/CompleteCases.java        |   6 +-
 .../truffle/r/library/stats/Covcor.java       |   8 +-
 .../truffle/r/library/stats/DoubleCentre.java |   2 +-
 .../r/library/stats/RMultinomNode.java        |  23 ++--
 .../r/library/stats/RandFunctionsNodes.java   |  14 +--
 .../r/library/stats/SplineFunctions.java      |  68 +++++------
 .../r/library/stats/StatsFunctionsNodes.java  |   8 +-
 .../truffle/r/library/tools/C_ParseRd.java    |   6 +-
 .../truffle/r/library/tools/DirChmod.java     |   2 +-
 .../oracle/truffle/r/library/tools/Rmd5.java  |   2 +-
 .../truffle/r/library/tools/ToolsText.java    |   4 +-
 .../truffle/r/library/utils/CountFields.java  | 112 ++++++++----------
 .../oracle/truffle/r/library/utils/Crc64.java |   3 +-
 .../truffle/r/library/utils/Download.java     |   3 +-
 .../oracle/truffle/r/library/utils/Menu.java  |   2 +-
 .../oracle/truffle/r/library/utils/Rprof.java |   2 +-
 .../truffle/r/library/utils/Rprofmem.java     |   2 +-
 .../truffle/r/library/utils/TypeConvert.java  |  23 ++--
 .../r/nodes/builtin/RBuiltinPackages.java     |  22 +++-
 .../truffle/r/nodes/builtin/base/APerm.java   |  16 +--
 .../truffle/r/nodes/builtin/base/Abbrev.java  |   4 +-
 .../r/nodes/builtin/base/AllNames.java        |   6 +-
 .../truffle/r/nodes/builtin/base/Array.java   |  10 +-
 .../truffle/r/nodes/builtin/base/AsCall.java  |   2 +-
 .../nodes/builtin/base/AsCharacterFactor.java |  13 +-
 .../r/nodes/builtin/base/AsFunction.java      |   4 +-
 .../truffle/r/nodes/builtin/base/Assign.java  |   2 +-
 .../r/nodes/builtin/base/AttachFunctions.java |   2 +-
 .../truffle/r/nodes/builtin/base/Bincode.java |   5 +-
 .../nodes/builtin/base/BitwiseFunctions.java  |  10 +-
 .../truffle/r/nodes/builtin/base/CRC64.java   |   3 +-
 .../truffle/r/nodes/builtin/base/Cat.java     |   4 +-
 .../r/nodes/builtin/base/CharMatch.java       |   5 +-
 .../r/nodes/builtin/base/ChooseBuiltin.java   |   4 +-
 .../truffle/r/nodes/builtin/base/Col.java     |   2 +-
 .../r/nodes/builtin/base/ColSumsBase.java     |  12 +-
 .../truffle/r/nodes/builtin/base/Colon.java   |  12 +-
 .../builtin/base/ConditionFunctions.java      |   6 +-
 .../builtin/base/ConnectionFunctions.java     |  90 +++++++-------
 .../r/nodes/builtin/base/Contributors.java    |   2 +-
 .../r/nodes/builtin/base/Crossprod.java       |   4 +-
 .../truffle/r/nodes/builtin/base/DPut.java    |   2 +-
 .../r/nodes/builtin/base/DebugFunctions.java  |   4 +-
 .../r/nodes/builtin/base/DelayedAssign.java   |  10 +-
 .../truffle/r/nodes/builtin/base/Diag.java    |   7 +-
 .../truffle/r/nodes/builtin/base/DoCall.java  |   6 +-
 .../builtin/base/DuplicatedFunctions.java     |   6 +-
 .../nodes/builtin/base/DynLoadFunctions.java  |   6 +-
 .../nodes/builtin/base/EncodingFunctions.java |   8 +-
 .../r/nodes/builtin/base/EnvFunctions.java    |  55 ++++-----
 .../r/nodes/builtin/base/FileFunctions.java   |  46 +++----
 .../truffle/r/nodes/builtin/base/Format.java  |   6 +-
 .../r/nodes/builtin/base/FrameFunctions.java  |  16 +--
 .../r/nodes/builtin/base/GetFunctions.java    |  11 +-
 .../truffle/r/nodes/builtin/base/GetText.java |   3 +-
 .../r/nodes/builtin/base/GrepFunctions.java   |  21 ++--
 .../builtin/base/HiddenInternalFunctions.java |  24 ++--
 .../truffle/r/nodes/builtin/base/IConv.java   |   8 +-
 .../r/nodes/builtin/base/IntToUtf8.java       |   5 +-
 .../nodes/builtin/base/IsFiniteFunctions.java |   2 +-
 .../r/nodes/builtin/base/IsSingle.java        |   2 +-
 .../r/nodes/builtin/base/IsTypeFunctions.java |   3 +-
 .../r/nodes/builtin/base/IsUnsorted.java      |   2 +-
 .../r/nodes/builtin/base/LaFunctions.java     |  70 +++++------
 .../truffle/r/nodes/builtin/base/Lapply.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Lengths.java |   5 +-
 .../truffle/r/nodes/builtin/base/License.java |   2 +-
 .../nodes/builtin/base/LoadSaveFunctions.java |  28 ++---
 .../r/nodes/builtin/base/LocaleFunctions.java |   3 +-
 .../truffle/r/nodes/builtin/base/Ls.java      |   3 +-
 .../r/nodes/builtin/base/MakeNames.java       |   4 +-
 .../r/nodes/builtin/base/MakeUnique.java      |   4 +-
 .../truffle/r/nodes/builtin/base/MatMult.java |  33 ++----
 .../truffle/r/nodes/builtin/base/Match.java   |   3 +-
 .../r/nodes/builtin/base/MatchArg.java        |  19 ++-
 .../r/nodes/builtin/base/MatchFun.java        |   8 +-
 .../truffle/r/nodes/builtin/base/Matrix.java  |   8 +-
 .../truffle/r/nodes/builtin/base/Merge.java   |   4 +-
 .../truffle/r/nodes/builtin/base/Missing.java |   3 +-
 .../builtin/base/NamespaceFunctions.java      |   6 +-
 .../r/nodes/builtin/base/NormalizePath.java   |   2 +-
 .../truffle/r/nodes/builtin/base/OnExit.java  |   2 +-
 .../nodes/builtin/base/OptionsFunctions.java  |  12 +-
 .../truffle/r/nodes/builtin/base/Order.java   |   4 +-
 .../truffle/r/nodes/builtin/base/PMinMax.java |   6 +-
 .../truffle/r/nodes/builtin/base/Parse.java   |   6 +-
 .../truffle/r/nodes/builtin/base/Paste.java   |   6 +-
 .../truffle/r/nodes/builtin/base/Pretty.java  |  10 +-
 .../r/nodes/builtin/base/Primitive.java       |   6 +-
 .../r/nodes/builtin/base/PrintFunctions.java  |   8 +-
 .../r/nodes/builtin/base/Quantifier.java      |  12 +-
 .../truffle/r/nodes/builtin/base/Quit.java    |   2 +-
 .../r/nodes/builtin/base/RNGFunctions.java    |   7 +-
 .../truffle/r/nodes/builtin/base/Rank.java    |   9 +-
 .../r/nodes/builtin/base/RawFunctions.java    |   8 +-
 .../r/nodes/builtin/base/RawToBits.java       |   3 +-
 .../truffle/r/nodes/builtin/base/ReadDCF.java |   4 +-
 .../r/nodes/builtin/base/ReadREnviron.java    |   4 +-
 .../truffle/r/nodes/builtin/base/Recall.java  |   6 +-
 .../r/nodes/builtin/base/RegFinalizer.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Repeat.java  |   4 +-
 .../r/nodes/builtin/base/RepeatInternal.java  |  17 +--
 .../r/nodes/builtin/base/RepeatLength.java    |   4 +-
 .../truffle/r/nodes/builtin/base/Rm.java      |  14 +--
 .../truffle/r/nodes/builtin/base/Row.java     |   3 +-
 .../r/nodes/builtin/base/RowsumFunctions.java |   2 +-
 .../builtin/base/S3DispatchFunctions.java     |  11 +-
 .../truffle/r/nodes/builtin/base/Sample.java  |  25 ++--
 .../truffle/r/nodes/builtin/base/Sample2.java |  16 +--
 .../truffle/r/nodes/builtin/base/Scan.java    |  32 +++--
 .../r/nodes/builtin/base/SeqFunctions.java    |  24 ++--
 .../builtin/base/SerializeFunctions.java      |  10 +-
 .../r/nodes/builtin/base/SetS4Object.java     |   6 +-
 .../truffle/r/nodes/builtin/base/Setwd.java   |   5 +-
 .../r/nodes/builtin/base/ShortRowNames.java   |   4 +-
 .../r/nodes/builtin/base/SinkFunctions.java   |  10 +-
 .../truffle/r/nodes/builtin/base/Slot.java    |   2 +-
 .../r/nodes/builtin/base/SortFunctions.java   |  11 +-
 .../truffle/r/nodes/builtin/base/Sprintf.java |   2 +-
 .../r/nodes/builtin/base/StandardGeneric.java |  14 +--
 .../builtin/base/StartsEndsWithFunctions.java |   2 +-
 .../truffle/r/nodes/builtin/base/Strrep.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Strtrim.java |   4 +-
 .../truffle/r/nodes/builtin/base/Substr.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Switch.java  |   8 +-
 .../r/nodes/builtin/base/SysFunctions.java    |   8 +-
 .../r/nodes/builtin/base/Tabulate.java        |   4 +-
 .../r/nodes/builtin/base/TempFile.java        |   6 +-
 .../r/nodes/builtin/base/TraceFunctions.java  |   5 +-
 .../r/nodes/builtin/base/Transpose.java       |   3 +-
 .../nodes/builtin/base/TrigExpFunctions.java  |   4 +-
 .../truffle/r/nodes/builtin/base/Unique.java  |   2 +-
 .../r/nodes/builtin/base/UpdateAttr.java      |   9 +-
 .../nodes/builtin/base/UpdateAttributes.java  |  16 +--
 .../r/nodes/builtin/base/UpdateClass.java     |   4 +-
 .../r/nodes/builtin/base/UpdateDimNames.java  |   2 +-
 .../r/nodes/builtin/base/UpdateLevels.java    |   3 +-
 .../r/nodes/builtin/base/UpdateNames.java     |   3 +-
 .../r/nodes/builtin/base/UpdateSlot.java      |   4 +-
 .../nodes/builtin/base/UpdateStorageMode.java |  14 +--
 .../r/nodes/builtin/base/UpdateSubstr.java    |   6 +-
 .../r/nodes/builtin/base/Utf8ToInt.java       |   4 +-
 .../truffle/r/nodes/builtin/base/VApply.java  |  10 +-
 .../truffle/r/nodes/builtin/base/Vector.java  |   6 +-
 .../r/nodes/builtin/base/WithVisible.java     |   4 +-
 .../foreign/CallAndExternalFunctions.java     |  14 +--
 .../r/nodes/builtin/base/foreign/Dqrcf.java   |   3 +-
 .../r/nodes/builtin/base/foreign/Fft.java     |   6 +-
 .../base/foreign/FortranAndCFunctions.java    |  12 +-
 .../builtin/base/foreign/LookupAdapter.java   |   2 +-
 .../builtin/base/foreign/ReadTableHead.java   |   3 +-
 .../builtin/base/foreign/WriteTable.java      |   6 +-
 .../nodes/builtin/base/infix/AccessField.java |   2 +-
 .../r/nodes/builtin/base/infix/Subscript.java |   4 +-
 .../nodes/builtin/base/infix/UpdateField.java |   2 +-
 .../builtin/base/infix/UpdateSubscript.java   |   2 +-
 .../builtin/base/infix/UpdateSubset.java      |   2 +-
 .../builtin/base/system/SystemFunction.java   |   2 +-
 .../r/nodes/builtin/fastr/FastRContext.java   |   8 +-
 .../r/nodes/builtin/fastr/FastRInterop.java   |  14 +--
 .../r/nodes/builtin/fastr/FastRPkgSource.java |   8 +-
 .../r/nodes/builtin/fastr/FastRStats.java     |  14 +--
 .../nodes/builtin/fastr/FastRSyntaxTree.java  |   2 +-
 .../r/nodes/builtin/fastr/FastRThrowIt.java   |   2 +-
 .../r/nodes/builtin/fastr/FastRTrace.java     |   8 +-
 .../r/nodes/builtin/CastBuilderTest.java      |  35 +++---
 .../builtin/ResultTypesAnalyserTest.java      |   8 +-
 .../r/nodes/builtin/SampleCollectorTest.java  |   4 +-
 .../truffle/r/nodes/casts/TestCasts.java      |   5 +-
 .../r/nodes/test/PipelineToCastNodeTests.java |   2 +-
 .../r/nodes/binary/BinaryArithmeticNode.java  |  10 +-
 .../r/nodes/binary/BinaryBooleanNode.java     |  10 +-
 .../truffle/r/nodes/builtin/CastBuilder.java  |  98 ++++-----------
 .../nodes/builtin/NodeWithArgumentCasts.java  |  31 +++--
 .../truffle/r/nodes/builtin/RBuiltinNode.java |  32 ++---
 .../r/nodes/builtin/RExternalBuiltinNode.java |  12 +-
 .../r/nodes/builtin/casts/MessageData.java    |   7 ++
 .../r/nodes/builtin/casts/PipelineConfig.java |  63 ++--------
 .../r/nodes/builtin/casts/PipelineStep.java   |  16 +--
 .../builtin/casts/PipelineToCastNode.java     |  75 ++++++------
 .../builtin/casts/fluent/ArgCastBuilder.java  |   8 +-
 .../builtin/casts/fluent/CastNodeBuilder.java |  10 +-
 .../casts/fluent/CoercedPhaseBuilder.java     |  28 +----
 .../casts/fluent/HeadPhaseBuilder.java        |  39 ++----
 .../casts/fluent/InitialPhaseBuilder.java     |  91 +++-----------
 .../builtin/casts/fluent/PipelineBuilder.java |  40 +++----
 .../casts/fluent/PipelineConfigBuilder.java   |  15 +--
 .../casts/fluent/PreinitialPhaseBuilder.java  |  26 +---
 .../truffle/r/nodes/objects/GetPrimName.java  |   3 +-
 .../truffle/r/nodes/objects/NewObject.java    |  16 +--
 .../truffle/r/nodes/unary/UnaryNotNode.java   |   2 +-
 .../com/oracle/truffle/r/runtime/RError.java  |  49 ++++++--
 .../nodes/builtin/RBuiltinBaseNode.java       |  73 ++++++++++++
 .../com/oracle/truffle/r/test/S4/TestS4.java  |   5 +-
 .../com/oracle/truffle/r/test/TestBase.java   |   3 +-
 .../builtins/TestBuiltin_Syssetlocale.java    |   4 +-
 .../test/builtins/TestBuiltin_asfunction.java |   2 +-
 .../r/test/builtins/TestBuiltin_asvector.java |   8 +-
 .../r/test/builtins/TestBuiltin_atan2.java    |   7 +-
 .../r/test/builtins/TestBuiltin_attach.java   |   2 +-
 .../test/builtins/TestBuiltin_attrassign.java |   4 +-
 .../test/builtins/TestBuiltin_bitwiseNot.java |   2 +-
 .../r/test/builtins/TestBuiltin_cat.java      |   6 +-
 .../test/builtins/TestBuiltin_crossprod.java  |   2 +
 .../r/test/builtins/TestBuiltin_inherits.java |   4 +-
 .../test/builtins/TestBuiltin_intToBits.java  |   6 +-
 .../r/test/builtins/TestBuiltin_isvector.java |   5 +-
 .../r/test/builtins/TestBuiltin_levels.java   |   2 +-
 .../r/test/builtins/TestBuiltin_ngettext.java |  18 +--
 .../test/builtins/TestBuiltin_pathexpand.java |   4 +-
 .../r/test/builtins/TestBuiltin_pmatch.java   |   2 +-
 .../r/test/builtins/TestBuiltin_pmax.java     |   4 +-
 .../r/test/builtins/TestBuiltin_pmin.java     |   4 +-
 .../builtins/TestBuiltin_primUntrace.java     |   2 +-
 .../r/test/builtins/TestBuiltin_qr.java       |   2 +-
 .../r/test/builtins/TestBuiltin_quit.java     |   4 +-
 .../r/test/builtins/TestBuiltin_repint.java   |   6 +-
 .../r/test/builtins/TestBuiltin_sample.java   |   6 +-
 .../r/test/builtins/TestBuiltin_scan.java     |   2 +-
 .../test/builtins/TestBuiltin_seq_along.java  |   4 +-
 .../builtins/TestBuiltin_shortRowNames.java   |   2 +-
 .../r/test/builtins/TestBuiltin_substr.java   |  14 ++-
 .../r/test/functions/TestFunctions.java       |   4 +-
 .../r/test/library/base/TestSimpleArrays.java |   4 +-
 .../r/test/library/base/TestSimpleLists.java  |   4 +-
 .../test/library/base/TestSimpleVectors.java  |   2 +-
 .../library/stats/TestExternal_BinDist.java   |   2 +-
 .../stats/TestRandGenerationFunctions.java    |   2 +-
 236 files changed, 1190 insertions(+), 1434 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
index 539994d1f7..1b6c1f9833 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
@@ -17,6 +17,7 @@ package com.oracle.truffle.r.library.grDevices;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -58,24 +59,16 @@ public class DevicesCCalls {
 
     public static final class C_PDF extends RExternalBuiltinNode {
 
-        @Child private CastNode extractFontsNode;
-        @Child private CastNode asStringNode;
-        @Child private CastNode asDoubleNode;
-        @Child private CastNode asLogicalNode;
-        @Child private CastNode asIntNode;
+        @Child private CastNode extractFontsNode = newCastBuilder(NO_CALLER).mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode();
+        @Child private CastNode asStringNode = newCastBuilder(NO_CALLER).asStringVector().findFirst().buildCastNode();
+        @Child private CastNode asDoubleNode = newCastBuilder(NO_CALLER).asDoubleVector().findFirst().buildCastNode();
+        @Child private CastNode asLogicalNode = newCastBuilder(NO_CALLER).asLogicalVector().findFirst().buildCastNode();
+        @Child private CastNode asIntNode = newCastBuilder(NO_CALLER).asIntegerVector().findFirst().buildCastNode();
 
         static {
             Casts.noCasts(C_PDF.class);
         }
 
-        public C_PDF() {
-            asStringNode = newCastBuilder().asStringVector().findFirst().buildCastNode();
-            asDoubleNode = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
-            asLogicalNode = newCastBuilder().asLogicalVector().findFirst().buildCastNode();
-            asIntNode = newCastBuilder().asIntegerVector().findFirst().buildCastNode();
-            extractFontsNode = newCastBuilder().mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode();
-        }
-
         @SuppressWarnings("unused")
         @Override
         @TruffleBoundary
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
index 695ba86dbb..2f04283ba5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
@@ -17,6 +17,7 @@ package com.oracle.truffle.r.library.graphics;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
@@ -35,16 +36,13 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 public class GraphicsCCalls {
     public static final class C_PlotXY extends RExternalBuiltinNode {
-        @Child private CastNode castXYNode;
+
+        @Child private CastNode castXYNode = newCastBuilder(NO_CALLER).mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
 
         static {
             Casts.noCasts(C_PlotXY.class);
         }
 
-        public C_PlotXY() {
-            castXYNode = newCastBuilder().mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
-        }
-
         @Override
         @TruffleBoundary
         public RNull call(RArgsValuesAndNames args) {
@@ -107,16 +105,13 @@ public class GraphicsCCalls {
         private double cex = RRuntime.DOUBLE_NA;
         private double col = RRuntime.DOUBLE_NA;
         private double font = RRuntime.DOUBLE_NA;
-        @Child private CastNode firstDoubleCast;
+
+        @Child private CastNode firstDoubleCast = newCastBuilder(NO_CALLER).asDoubleVector().findFirst().buildCastNode();
 
         static {
             Casts.noCasts(C_mtext.class);
         }
 
-        public C_mtext() {
-            firstDoubleCast = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
-        }
-
         @Override
         @TruffleBoundary
         public Object call(RArgsValuesAndNames args) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
index 35dc425469..d7a155a96f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
@@ -82,7 +82,7 @@ public class GridFunctions {
             for (int i = 0; i < data.length; i++) {
                 int code = convertUnit(units.getDataAt(i));
                 if (code < 0) {
-                    throw RError.error(this, RError.Message.GENERIC, "Invalid unit");
+                    throw error(RError.Message.GENERIC, "Invalid unit");
                 }
                 data[i] = code;
             }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 48f6249fe4..8d0e66deea 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -72,12 +72,12 @@ public class MethodsListDispatch {
                     Function<Object, Integer> vecLenFn) {
         //@formatter:off
         casts.arg(argNum, argName).
-            defaultError(RError.NO_CALLER, RError.Message.SINGLE_STRING_WRONG_TYPE, msg, clsHierFn).
+            defaultError(RError.Message.SINGLE_STRING_WRONG_TYPE, msg, clsHierFn).
             mustBe(stringValue()).
             asStringVector().
-            mustBe(singleElement(), RError.NO_CALLER, RError.Message.SINGLE_STRING_TOO_LONG, msg, vecLenFn).
+            mustBe(singleElement(),  RError.Message.SINGLE_STRING_TOO_LONG, msg, vecLenFn).
             findFirst().
-            mustBe(nonEmpty ? lengthGt(0) : lengthGte(0), RError.NO_CALLER, RError.Message.NON_EMPTY_STRING, msg);
+            mustBe(nonEmpty ? lengthGt(0) : lengthGte(0),  RError.Message.NON_EMPTY_STRING, msg);
         //@formatter:on
     }
 
@@ -131,7 +131,7 @@ public class MethodsListDispatch {
             Casts casts = new Casts(R_getClassFromCache.class);
             casts.arg(0, "klass").defaultError(RError.Message.GENERIC, "class should be either a character-string name or a class definition").mustBe(stringValue().or(instanceOf(RS4Object.class)));
 
-            casts.arg(1, "table").mustNotBeNull(RError.NO_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
+            casts.arg(1, "table").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
         }
 
         protected GetFixedAttributeNode createPckgAttrAccess() {
@@ -146,7 +146,7 @@ public class MethodsListDispatch {
             String klassString = klass.getLength() == 0 ? RRuntime.STRING_NA : klass.getDataAt(0);
 
             if (klassString.length() == 0) {
-                throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
+                throw error(RError.Message.ZERO_LENGTH_VARIABLE);
             }
 
             Object value = table.get(klassString);
@@ -240,7 +240,7 @@ public class MethodsListDispatch {
                 String internalName = RRuntime.asString(initAccessSlotNode().executeAccess(op, "internal"));
                 opx = RContext.lookupBuiltin(internalName);
                 if (opx == null) {
-                    throw RError.error(this, RError.Message.GENERIC, "'internal' slot does not name an internal function: " + internalName);
+                    throw error(RError.Message.GENERIC, "'internal' slot does not name an internal function: " + internalName);
                 }
             }
 
@@ -248,7 +248,7 @@ public class MethodsListDispatch {
             return fnameString;
         }
 
-        private static void setPrimitiveMethodsInternal(Object op, String codeVec, RTypedValue fundef, Object mlist) {
+        private void setPrimitiveMethodsInternal(Object op, String codeVec, RTypedValue fundef, Object mlist) {
             MethodCode code;
             if (codeVec.charAt(0) == 'c') {
                 code = MethodCode.NO_METHODS;
@@ -259,10 +259,10 @@ public class MethodsListDispatch {
             } else if (codeVec.startsWith("su")) {
                 code = MethodCode.SUPPRESSED;
             } else {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_PRIM_METHOD_CODE, codeVec);
+                throw error(RError.Message.INVALID_PRIM_METHOD_CODE, codeVec);
             }
             if (!(op instanceof RFunction) || !((RFunction) op).isBuiltin()) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "invalid object: must be a primitive function");
+                throw error(RError.Message.GENERIC, "invalid object: must be a primitive function");
             }
             int primMethodIndex = ((RFunction) op).getRBuiltin().getPrimMethodIndex();
             assert primMethodIndex != PrimitiveMethodsInfo.INVALID_INDEX;
@@ -280,7 +280,7 @@ public class MethodsListDispatch {
                     primMethodsInfo.setPrimMethodList(primMethodIndex, null);
                 } else if (fundef != RNull.instance && value == null) {
                     if (!(fundef instanceof RFunction)) {
-                        throw RError.error(RError.SHOW_CALLER, RError.Message.PRIM_GENERIC_NOT_FUNCTION, fundef.getRType().getName());
+                        throw error(RError.Message.PRIM_GENERIC_NOT_FUNCTION, fundef.getRType().getName());
                     }
                     primMethodsInfo.setPrimGeneric(primMethodIndex, (RFunction) fundef);
                 }
@@ -340,9 +340,9 @@ public class MethodsListDispatch {
             if (value == RNull.instance) {
                 if (mustFind) {
                     if (env == RContext.getInstance().stateREnvironment.getGlobalEnv()) {
-                        throw RError.error(RError.NO_CALLER, RError.Message.NO_GENERIC_FUN, name);
+                        throw error(RError.Message.NO_GENERIC_FUN, name);
                     } else {
-                        throw RError.error(RError.NO_CALLER, RError.Message.NO_GENERIC_FUN_IN_ENV, name);
+                        throw error(RError.Message.NO_GENERIC_FUN_IN_ENV, name);
                     }
                 }
             }
@@ -453,7 +453,7 @@ public class MethodsListDispatch {
 
             RFunction op = (RFunction) readDotNextMethod.execute(null, ev.getFrame());
             if (op == null) {
-                throw RError.error(this, RError.Message.GENERIC, "internal error in 'callNextMethod': '.nextMethod' was not assigned in the frame of the method call");
+                throw error(RError.Message.GENERIC, "internal error in 'callNextMethod': '.nextMethod' was not assigned in the frame of the method call");
             }
             boolean primCase = op.isBuiltin();
             if (primCase) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
index 51803d72d1..741c709024 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
@@ -38,8 +38,8 @@ public class Slot {
 
         static {
             Casts casts = new Casts(R_getSlot.class);
-            casts.arg(1, "name").defaultError(RError.NO_CALLER, RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe(
-                            singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
+            casts.arg(1, "name").defaultError(RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe(
+                            singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.Message.ZERO_LENGTH_VARIABLE);
         }
 
         protected static String getInternedName(String name) {
@@ -66,8 +66,8 @@ public class Slot {
 
         static {
             Casts casts = new Casts(R_setSlot.class);
-            casts.arg(1, "name").defaultError(RError.NO_CALLER, RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe(
-                            singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
+            casts.arg(1, "name").defaultError(RError.Message.GENERIC, "invalid type or length for slot name").mustBe(stringValue()).asStringVector().mustBe(
+                            singleElement()).findFirst().mustBe(Predef.lengthGt(0), RError.Message.ZERO_LENGTH_VARIABLE);
         }
 
         protected static String getInternedName(String name) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
index bcc83ed895..d450b30ac4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RList2EnvNode;
 import com.oracle.truffle.r.runtime.RError;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LIST_FOR_SUBSTITUTION;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import com.oracle.truffle.r.runtime.RSubstitute;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -43,8 +42,8 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
     static {
-        Casts casts = new Casts(SubstituteDirect.class);
-        casts.arg(1).defaultError(SHOW_CALLER, INVALID_LIST_FOR_SUBSTITUTION).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class)));
+        Casts casts = new Casts(SubstituteDirect.class, RError.SHOW_CALLER);
+        casts.arg(1).defaultError(INVALID_LIST_FOR_SUBSTITUTION).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class)));
     }
 
     @Specialization
@@ -73,7 +72,7 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
     @Fallback
     protected Object substituteDirect(@SuppressWarnings("unused") Object object, @SuppressWarnings("unused") Object env) {
-        throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+        throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
     }
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
index fa604b7662..bb15916f20 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java
@@ -20,7 +20,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 
 import java.util.Arrays;
 
@@ -46,7 +45,7 @@ public abstract class BinDist extends RExternalBuiltinNode.Arg5 {
         casts.arg(1).mustBe(missingValue().not()).returnIf(nullValue(), emptyDoubleVector()).asDoubleVector();
         casts.arg(2).asDoubleVector().findFirst();
         casts.arg(3).asDoubleVector().findFirst();
-        casts.arg(4).asIntegerVector().findFirst().mustBe(gt0().and(intNA().not()), NO_CALLER, Message.INVALID_ARGUMENT, "n");
+        casts.arg(4).asIntegerVector().findFirst().mustBe(gt0().and(intNA().not()), Message.INVALID_ARGUMENT, "n");
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
index a06533fff0..47a820c41a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java
@@ -86,19 +86,19 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 {
         return RRuntime.isFinite(a) && RRuntime.isFinite(b);
     }
 
-    public static Method getMethod(int method) {
+    public Method getMethod(int method) {
         if (method < 1 || method > Method.values().length) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "distance(): invalid distance");
+            throw error(RError.Message.GENERIC, "distance(): invalid distance");
         }
         return Method.values()[method - 1];
     }
 
-    private static void rdistance(double[] x, int nr, int nc, double[] d, boolean diag, Method method, double p) {
+    private void rdistance(double[] x, int nr, int nc, double[] d, boolean diag, Method method, double p) {
         int ij; /* can exceed 2^31 - 1, but Java can't handle that */
         //
         if (method == Method.MINKOWSKI) {
             if (!RRuntime.isFinite(p) || p <= 0) {
-                throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "distance(): invalid p");
+                throw error(RError.Message.GENERIC, "distance(): invalid p");
             }
         }
         int dc = diag ? 0 : 1; /* diag=1: we do the diagonal */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
index ca606b3833..1b7b81345c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
@@ -39,11 +39,11 @@ public final class CompleteCases extends RExternalBuiltinNode {
     }
 
     private RError invalidType(Object entry) {
-        throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) entry).getRType().getName());
+        throw error(RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) entry).getRType().getName());
     }
 
     private RError lengthMismatch() {
-        throw RError.error(this, RError.Message.NOT_ALL_SAME_LENGTH);
+        throw error(RError.Message.NOT_ALL_SAME_LENGTH);
     }
 
     private int checkAbstractVectorLength(int len, Object obj) {
@@ -95,7 +95,7 @@ public final class CompleteCases extends RExternalBuiltinNode {
         }
 
         if (len < 0) {
-            throw RError.error(this, RError.Message.NO_INPUT_NUMBER_OF_CASES);
+            throw error(RError.Message.NO_INPUT_NUMBER_OF_CASES);
         }
 
         byte[] result = new byte[len];
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index 629269201a..7e9d9c2c63 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -14,8 +14,6 @@ package com.oracle.truffle.r.library.stats;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 
 import java.util.Arrays;
 
@@ -49,7 +47,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(Covcor.class);
-        casts.arg(0).mustNotBeMissing().mustBe(nullValue().not(), SHOW_CALLER, Message.IS_NULL, "x").asDoubleVector();
+        casts.arg(0).mustNotBeMissing().mustBe(nullValue().not(), Message.IS_NULL, "x").asDoubleVector();
         casts.arg(1).mustNotBeMissing().asDoubleVector();
         casts.arg(2).asIntegerVector().findFirst().mustBe(eq(4), Message.NYI, "covcor: other method than 4 not implemented.");
         casts.arg(3).asLogicalVector().findFirst().map(toBoolean());
@@ -737,8 +735,8 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
     }
 
-    private static RuntimeException error(String message) {
-        throw RError.error(NO_CALLER, Message.GENERIC, message);
+    private RuntimeException error(String message) {
+        throw error(Message.GENERIC, message);
     }
 
     private boolean checkNAs(double... xs) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
index 34bfd0b02d..9f35e9ded8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java
@@ -25,7 +25,7 @@ public abstract class DoubleCentre extends RExternalBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(DoubleCentre.class);
-        casts.arg(0).mustBe(missingValue().not()).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "REAL()", "numeric", "NULL").asDoubleVector();
+        casts.arg(0).mustBe(missingValue().not()).mustBe(nullValue().not(), RError.Message.MACRO_CAN_BE_APPLIED_TO, "REAL()", "numeric", "NULL").asDoubleVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
index dedf931e57..f2644dfb67 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleV
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.NA_IN_PROB_VECTOR;
 import static com.oracle.truffle.r.runtime.RError.Message.NEGATIVE_PROBABILITY;
 import static com.oracle.truffle.r.runtime.RError.Message.NO_POSITIVE_PROBABILITIES;
@@ -39,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
 import com.oracle.truffle.r.runtime.nmath.distr.RMultinom;
 import com.oracle.truffle.r.runtime.nmath.distr.Rbinom;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.rng.RRNG;
 
 /**
@@ -52,10 +52,15 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 {
     }
 
     static {
-        Casts casts = new Casts(RMultinomNode.class);
-        casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_FIRST_ARGUMENT_NAME, "n");
-        casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), SHOW_CALLER, Message.INVALID_SECOND_ARGUMENT_NAME, "size");
-        casts.arg(2).mustBe(missingValue().not(), SHOW_CALLER, Message.ARGUMENT_MISSING, "prob").mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
+        Casts casts = new Casts(RMultinomNode.class, RError.SHOW_CALLER);
+        casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_FIRST_ARGUMENT_NAME, "n");
+        casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_SECOND_ARGUMENT_NAME, "size");
+        casts.arg(2).mustBe(missingValue().not(), Message.ARGUMENT_MISSING, "prob").mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
+    }
+
+    @Override
+    protected RBaseNode getErrorContext() {
+        return RError.SHOW_CALLER;
     }
 
     @Specialization
@@ -91,15 +96,15 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 {
         return resultVec;
     }
 
-    private static void fixupProb(double[] p) {
+    private void fixupProb(double[] p) {
         double sum = 0.0;
         int npos = 0;
         for (double prob : p) {
             if (!Double.isFinite(prob)) {
-                throw RError.error(SHOW_CALLER, NA_IN_PROB_VECTOR);
+                throw error(NA_IN_PROB_VECTOR);
             }
             if (prob < 0.0) {
-                throw RError.error(SHOW_CALLER, NEGATIVE_PROBABILITY);
+                throw error(NEGATIVE_PROBABILITY);
             }
             if (prob > 0.0) {
                 npos++;
@@ -107,7 +112,7 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 {
             }
         }
         if (npos == 0) {
-            throw RError.error(SHOW_CALLER, NO_POSITIVE_PROBABILITIES);
+            throw error(NO_POSITIVE_PROBABILITIES);
         }
         for (int i = 0; i < p.length; i++) {
             p[i] /= sum;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index 1a5d082b10..c5a88e9279 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -90,7 +90,7 @@ public final class RandFunctionsNodes {
         }
 
         private static void addLengthCast(Casts casts) {
-            casts.arg(0).defaultError(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS).mustBe(abstractVectorValue()).asVector();
+            casts.arg(0).defaultError(INVALID_UNNAMED_ARGUMENTS).mustBe(abstractVectorValue()).asVector();
         }
     }
 
@@ -262,9 +262,9 @@ public final class RandFunctionsNodes {
         static {
             Casts casts = new Casts(RandFunction3Node.class);
             ConvertToLength.addLengthCast(casts);
-            casts.arg(1).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
-            casts.arg(2).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector();
-            casts.arg(3).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "c").asDoubleVector();
+            casts.arg(1).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
+            casts.arg(2).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector();
+            casts.arg(3).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "c").asDoubleVector();
         }
 
         @Specialization
@@ -292,8 +292,8 @@ public final class RandFunctionsNodes {
         static {
             Casts casts = new Casts(RandFunction2Node.class);
             ConvertToLength.addLengthCast(casts);
-            casts.arg(1).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
-            casts.arg(2).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector();
+            casts.arg(1).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
+            casts.arg(2).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "b").asDoubleVector();
         }
 
         @Specialization
@@ -321,7 +321,7 @@ public final class RandFunctionsNodes {
         static {
             Casts casts = new Casts(RandFunction1Node.class);
             ConvertToLength.addLengthCast(casts);
-            casts.arg(1).mustBe(nullValue().not(), RError.SHOW_CALLER, RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
+            casts.arg(1).mustBe(nullValue().not(), RError.Message.INVALID_UNNAMED_ARGUMENTS).mustBe(missingValue().not(), RError.Message.ARGUMENT_MISSING, "a").asDoubleVector();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
index 3a33af53fc..2af07cc9e5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java
@@ -11,22 +11,22 @@
  */
 package com.oracle.truffle.r.library.stats;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import static com.oracle.truffle.r.runtime.RError.Message.NA_INTRODUCED_COERCION;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 import static com.oracle.truffle.r.runtime.RRuntime.INT_NA;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -49,7 +49,7 @@ public class SplineFunctions {
             casts.arg(0).mapNull(constant(INT_NA)).mapIf(numericValue(),
                             chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).end(),
                             chain(asIntegerVector()).with(findFirst().integerElement(INT_NA)).with(
-                                            Predef.shouldBe(integerValue(), NO_CALLER, NA_INTRODUCED_COERCION)).end());
+                                            Predef.shouldBe(integerValue(), NA_INTRODUCED_COERCION)).end());
             casts.arg(1).mustNotBeMissing().asDoubleVector();
             casts.arg(2).mustNotBeMissing().asDoubleVector();
         }
@@ -57,25 +57,46 @@ public class SplineFunctions {
         @Specialization
         @TruffleBoundary
         protected Object splineCoef(int method, RAbstractDoubleVector x, RAbstractDoubleVector y) {
-            return SplineFunctions.splineCoef(method, x.materialize(), y.materialize());
+            return splineCoefImpl(method, x.materialize(), y.materialize());
         }
 
         @Specialization
         @TruffleBoundary
         protected Object splineCoef(int method, RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y) {
-            return SplineFunctions.splineCoef(method, x.materialize(), RDataFactory.createDoubleVector(0));
+            return splineCoefImpl(method, x.materialize(), RDataFactory.createDoubleVector(0));
         }
 
         @Specialization
         @TruffleBoundary
         protected Object splineCoef(int method, @SuppressWarnings("unused") RNull x, RAbstractDoubleVector y) {
-            return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), y.materialize());
+            return splineCoefImpl(method, RDataFactory.createDoubleVector(0), y.materialize());
         }
 
         @Specialization
         @TruffleBoundary
         protected Object splineCoef(int method, @SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") RNull y) {
-            return SplineFunctions.splineCoef(method, RDataFactory.createDoubleVector(0), RDataFactory.createDoubleVector(0));
+            return splineCoefImpl(method, RDataFactory.createDoubleVector(0), RDataFactory.createDoubleVector(0));
+        }
+
+        private RList splineCoefImpl(int method, RDoubleVector x, RDoubleVector y) {
+            int n = x.getLength();
+            if (y.getLength() != n) {
+                throw error(RError.Message.INPUTS_DIFFERENT_LENGTHS);
+            }
+
+            double[] b = new double[n];
+            double[] c = new double[n];
+            double[] d = new double[n];
+
+            SplineFunctions.splineCoef(method, n, x.getDataWithoutCopying(), y.getDataWithoutCopying(), b, c, d);
+
+            final boolean complete = x.isComplete() && y.isComplete();
+            RDoubleVector bv = RDataFactory.createDoubleVector(b, complete);
+            RDoubleVector cv = RDataFactory.createDoubleVector(c, complete);
+            RDoubleVector dv = RDataFactory.createDoubleVector(d, complete);
+            Object[] resultData = new Object[]{method, n, x, y, bv, cv, dv};
+            RStringVector resultNames = RDataFactory.createStringVector(new String[]{"method", "n", "x", "y", "b", "c", "d"}, RDataFactory.COMPLETE_VECTOR);
+            return RDataFactory.createList(resultData, resultNames);
         }
     }
 
@@ -95,27 +116,6 @@ public class SplineFunctions {
         }
     }
 
-    private static RList splineCoef(int method, RDoubleVector x, RDoubleVector y) {
-        final int n = x.getLength();
-        if (y.getLength() != n) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.INPUTS_DIFFERENT_LENGTHS);
-        }
-
-        double[] b = new double[n];
-        double[] c = new double[n];
-        double[] d = new double[n];
-
-        splineCoef(method, n, x.getDataWithoutCopying(), y.getDataWithoutCopying(), b, c, d);
-
-        final boolean complete = x.isComplete() && y.isComplete();
-        RDoubleVector bv = RDataFactory.createDoubleVector(b, complete);
-        RDoubleVector cv = RDataFactory.createDoubleVector(c, complete);
-        RDoubleVector dv = RDataFactory.createDoubleVector(d, complete);
-        Object[] resultData = new Object[]{method, n, x, y, bv, cv, dv};
-        RStringVector resultNames = RDataFactory.createStringVector(new String[]{"method", "n", "x", "y", "b", "c", "d"}, RDataFactory.COMPLETE_VECTOR);
-        return RDataFactory.createList(resultData, resultNames);
-    }
-
     private static void splineCoef(int method, int n, double[] x, double[] y, double[] b, double[] c, double[] d) {
         switch (method) {
             case 1:
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
index 9798af5abb..ec765e5a52 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java
@@ -150,7 +150,7 @@ public final class StatsFunctionsNodes {
     }
 
     private static void castDoubleVec(Casts casts, int index) {
-        casts.arg(index).mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).asDoubleVector();
+        casts.arg(index).mustBe(numericValue(), Message.NON_NUMERIC_MATH).asDoubleVector();
     }
 
     public abstract static class Function3_2Node extends RExternalBuiltinNode.Arg5 {
@@ -337,16 +337,16 @@ public final class StatsFunctionsNodes {
                     break;
                 case 2:
                     if (!RRuntime.isFinite(f) || f < 0.0 || f > 1.0) {
-                        throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "approx(): invalid f value");
+                        throw error(RError.Message.GENERIC, "approx(): invalid f value");
                     }
                     break;
                 default:
-                    throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "approx(): invalid interpolation method");
+                    throw error(RError.Message.GENERIC, "approx(): invalid interpolation method");
             }
 
             for (int i = 0; i < nx; i++) {
                 if (RRuntime.isNAorNaN(x.getDataAt(i)) || RRuntime.isNAorNaN(y.getDataAt(i))) {
-                    throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ("approx(): attempted to interpolate NA values"));
+                    throw error(RError.Message.GENERIC, ("approx(): attempted to interpolate NA values"));
                 }
             }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
index 915a54f613..7b78cebbe2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
@@ -69,7 +69,7 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 {
         int con = conAsInteger.execute(conObj);
         int warningCalls = warningCallsAsLogical.execute(warningCallsObj);
         if (RRuntime.isNA(warningCalls)) {
-            throw RError.error(this, RError.Message.INVALID_VALUE, "warningCalls");
+            throw error(RError.Message.INVALID_VALUE, "warningCalls");
         }
         int fragment = fragmentAsLogical.execute(fragmentObj);
         int warndups = warnDupsAsLogical.execute(warndupsObj);
@@ -86,7 +86,7 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 {
                             RDataFactory.createLogicalVectorFromScalar((byte) warndups));
             // @formatter:on
         } catch (Throwable ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
     }
 
@@ -94,6 +94,6 @@ public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 {
     @Fallback
     public Object parseRd(Object con, Object srcfile, Object encoding, Object verbose, Object basename, Object fragment, Object warningCalls,
                     Object macros, Object warndupsL) {
-        throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+        throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
index 9685b25687..28efcde356 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
@@ -77,6 +77,6 @@ public abstract class DirChmod extends RExternalBuiltinNode.Arg2 {
     @SuppressWarnings("unused")
     @Fallback
     protected Object fallback(Object dir, Object gws) {
-        throw RError.error(this, RError.Message.INVALID_ARGUMENT, "dir");
+        throw error(RError.Message.INVALID_ARGUMENT, "dir");
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java
index 7b9d09c4a8..3678eb45a2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/Rmd5.java
@@ -46,7 +46,7 @@ public abstract class Rmd5 extends RExternalBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Rmd5.class);
-        casts.arg(0).defaultError(RError.NO_CALLER, RError.Message.ARG_MUST_BE_CHARACTER, "files").mustBe(stringValue());
+        casts.arg(0).defaultError(RError.Message.ARG_MUST_BE_CHARACTER, "files").mustBe(stringValue());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
index 576ff1bd55..d412a0a76d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
@@ -38,8 +38,8 @@ public class ToolsText {
 
         static {
             Casts casts = new Casts(DoTabExpand.class);
-            casts.arg(0, "strings").defaultError(RError.NO_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "STRING_ELT()", "character vector", typeName()).mustBe(stringValue());
-            casts.arg(1, "starts").defaultError(RError.NO_CALLER, RError.Message.MACRO_CAN_BE_APPLIED_TO, "INTEGER()", "integer", typeName()).mustBe(integerValue()).asIntegerVector();
+            casts.arg(0, "strings").defaultError(RError.Message.MACRO_CAN_BE_APPLIED_TO, "STRING_ELT()", "character vector", typeName()).mustBe(stringValue());
+            casts.arg(1, "starts").defaultError(RError.Message.MACRO_CAN_BE_APPLIED_TO, "INTEGER()", "integer", typeName()).mustBe(integerValue()).asIntegerVector();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
index cb470182d5..b3405af7d8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
@@ -15,19 +15,20 @@ import java.io.IOException;
 import java.io.InputStream;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 // Transcribed from GnuR, library/utils/src/io.c
 
 // Checkstyle: stop
-public final class CountFields extends RExternalBuiltinNode {
+public abstract class CountFields extends RExternalBuiltinNode.Arg6 {
 
     private static final int R_EOF = -1;
     private static final int SCAN_BLOCKSIZE = 1000;
@@ -54,7 +55,53 @@ public final class CountFields extends RExternalBuiltinNode {
     }
 
     static {
-        Casts.noCasts(CountFields.class);
+        Casts casts = new Casts(CountFields.class);
+        casts.arg(0, "conn").asIntegerVector().findFirst();
+        casts.arg(1, "sep").allowNull().mustBe(Predef.stringValue()).asStringVector().findFirst();
+        casts.arg(2, "quote").allowNull().mustBe(Predef.stringValue()).asStringVector().findFirst();
+        casts.arg(3, "nskip").asIntegerVector().findFirst();
+        casts.arg(4, "blskip").asLogicalVector().findFirst().replaceNA(RRuntime.LOGICAL_TRUE).map(Predef.toBoolean());
+        casts.arg(5, "commend.char").mustBe(Predef.stringValue()).asStringVector().findFirst().mustBe(Predef.length(1));
+    }
+
+    @Specialization
+    protected Object count(int conn, Object sep, Object quote, int nskipArg, boolean blskip, String commentCharArg) {
+        char comChar;
+        if (!(commentCharArg != null && commentCharArg.length() == 1)) {
+            throw error(RError.Message.INVALID_ARGUMENT, "comment.char");
+        } else {
+            comChar = commentCharArg.charAt(0);
+        }
+
+        int nskip;
+        if (nskipArg < 0 || nskipArg == RRuntime.INT_NA) {
+            nskip = 0;
+        } else {
+            nskip = nskipArg;
+        }
+
+        char sepChar;
+        if (sep instanceof RNull) {
+            sepChar = 0;
+        } else {
+            String s = (String) sep;
+            if (s == null) {
+                throw error(RError.Message.INVALID_ARGUMENT, "sep");
+            } else {
+                sepChar = s.length() == 0 ? 0 : s.charAt(0);
+            }
+        }
+        String quoteSet;
+        if (quote instanceof RNull) {
+            quoteSet = "";
+        } else {
+            quoteSet = (String) quote;
+        }
+        try (RConnection openConn = RConnection.fromIndex(conn).forceOpen("r")) {
+            return countFields(openConn, sepChar, quoteSet, nskip, blskip, comChar);
+        } catch (IllegalStateException | IOException ex) {
+            throw error(RError.Message.GENERIC, ex.getMessage());
+        }
     }
 
     @TruffleBoundary
@@ -291,63 +338,4 @@ public final class CountFields extends RExternalBuiltinNode {
         // TODO locale
         return false;
     }
-
-    // Transcribed from GnuR, library/utils/src/io.c
-    @Override
-    @TruffleBoundary
-    public Object call(RArgsValuesAndNames args) {
-        Object[] argValues = args.getArguments();
-        int conn = castInt(castVector(argValues[0]));
-        Object sepArg = argValues[1];
-        char sepChar;
-        Object quoteArg = argValues[2];
-        int nskip = castInt(castVector(argValues[3]));
-        byte blskip = castLogical(castVector(argValues[4]));
-        String commentCharArg = isString(argValues[5]);
-        char comChar;
-        if (!(commentCharArg != null && commentCharArg.length() == 1)) {
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "comment.char");
-        } else {
-            comChar = commentCharArg.charAt(0);
-        }
-
-        if (nskip < 0 || nskip == RRuntime.INT_NA) {
-            nskip = 0;
-        }
-        if (blskip == RRuntime.LOGICAL_NA) {
-            blskip = RRuntime.LOGICAL_TRUE;
-        }
-
-        if (sepArg instanceof RNull) {
-            sepChar = 0;
-        } else {
-            String s = isString(sepArg);
-            if (s == null) {
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "sep");
-            } else {
-                if (s.length() == 0) {
-                    sepChar = 0;
-                } else {
-                    sepChar = s.charAt(0);
-                }
-            }
-        }
-        String quoteSet;
-        if (quoteArg instanceof RNull) {
-            quoteSet = "";
-        } else {
-            String s = isString(quoteArg);
-            if (s == null) {
-                throw RError.error(this, RError.Message.GENERIC, "invalid quote symbol set");
-            } else {
-                quoteSet = s;
-            }
-        }
-        try (RConnection openConn = RConnection.fromIndex(conn).forceOpen("r")) {
-            return countFields(openConn, sepChar, quoteSet, nskip, RRuntime.fromLogical(blskip), comChar);
-        } catch (IllegalStateException | IOException ex) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java
index 51eb47a457..301ce24664 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Crc64.java
@@ -34,8 +34,7 @@ public abstract class Crc64 extends RExternalBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Crc64.class);
-        casts.arg(0).mustNotBeNull(RError.NO_CALLER,
-                        RError.Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INPUT_MUST_BE_STRING);
+        casts.arg(0).mustNotBeNull(RError.Message.INPUT_MUST_BE_STRING).mustBe(stringValue(), RError.Message.INPUT_MUST_BE_STRING);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
index 0017248292..b51d2be570 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
@@ -66,8 +66,7 @@ public abstract class Download extends RExternalBuiltinNode.Arg5 {
             }
             return 0;
         } catch (IOException e) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.GENERIC, e.getMessage());
+            throw error(RError.Message.GENERIC, e.getMessage());
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
index 05fca52ffd..86b2f791bb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
@@ -60,6 +60,6 @@ public abstract class Menu extends RExternalBuiltinNode.Arg1 {
     @Fallback
     @TruffleBoundary
     protected int menu(@SuppressWarnings("unused") Object choices) {
-        throw RError.error(this, RError.Message.INVALID_ARGUMENT, "choices");
+        throw error(RError.Message.INVALID_ARGUMENT, "choices");
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index f783de61da..26a5862074 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -127,7 +127,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
                 profState.initialize(out, profileThread, statementListener, intervalInMillis, lineProfiling, memProfiling);
                 profileThread.start();
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, String.format("Rprof: cannot open profile file '%s'", filename));
+                throw error(RError.Message.GENERIC, String.format("Rprof: cannot open profile file '%s'", filename));
             }
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java
index 9500f6f83e..34a5b00b39 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java
@@ -78,7 +78,7 @@ public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDat
                 RDataFactory.addListener(this);
                 RDataFactory.setTracingState(true);
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filename));
+                throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filename));
             }
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
index 27d158bbc8..34a46b38cc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
@@ -22,11 +22,6 @@
  */
 package com.oracle.truffle.r.library.utils;
 
-import java.util.Arrays;
-import java.util.TreeSet;
-
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
@@ -35,12 +30,18 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import static com.oracle.truffle.r.runtime.RError.Message.FIRST_ARGUMENT_MUST_BE_CHARACTER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARG;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
-import com.oracle.truffle.r.runtime.RRuntime;
 import static com.oracle.truffle.r.runtime.RRuntime.LOGICAL_FALSE;
+
+import java.util.Arrays;
+import java.util.TreeSet;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -53,9 +54,9 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 {
     @Child private SetFixedAttributeNode setLevelsAttrNode = SetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY);
 
     static {
-        Casts casts = new Casts(TypeConvert.class);
-        casts.arg(0).mustBe(stringValue(), SHOW_CALLER, FIRST_ARGUMENT_MUST_BE_CHARACTER).asStringVector();
-        casts.arg(1).mustBe(stringValue(), SHOW_CALLER, INVALID_ARG, "'na.strings'").asStringVector();
+        Casts casts = new Casts(TypeConvert.class, RError.SHOW_CALLER);
+        casts.arg(0).mustBe(stringValue(), FIRST_ARGUMENT_MUST_BE_CHARACTER).asStringVector();
+        casts.arg(1).mustBe(stringValue(), INVALID_ARG, "'na.strings'").asStringVector();
         casts.arg(2).mapIf(logicalValue(),
                         chain(asLogicalVector()).with(findFirst().logicalElement(LOGICAL_FALSE)).with(toBoolean()).end(),
                         chain(map(constant(LOGICAL_FALSE))).with(toBoolean()).end());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
index e8bfecd924..8b13bea09c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
@@ -31,10 +31,13 @@ import java.util.Map;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
 import com.oracle.truffle.r.nodes.builtin.base.BaseVariables;
+import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -51,6 +54,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 /**
  * Support for loading the base package and also optional overrides for the packages provided with
@@ -152,13 +156,29 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         return createFunction(builtin, methodName);
     }
 
+    private static RootCallTarget createArgumentsCallTarget(RBuiltinFactory builtin) {
+        CompilerAsserts.neverPartOfCompilation();
+
+        RBuiltinNode node = builtin.getConstructor().get();
+        FormalArguments formals = FormalArguments.createForBuiltin(node.getDefaultParameterValues(), builtin.getSignature());
+        if (builtin.getKind() == RBuiltinKind.INTERNAL) {
+            assert node.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values";
+            assert builtin.getSignature().getVarArgCount() == 0 || builtin.getSignature().getVarArgIndex() == builtin.getSignature().getLength() - 1 : "only last argument can be vararg";
+        }
+
+        FrameDescriptor frameDescriptor = new FrameDescriptor();
+        RBuiltinRootNode root = new RBuiltinRootNode(builtin, node, formals, frameDescriptor, null);
+        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor);
+        return Truffle.getRuntime().createCallTarget(root);
+    }
+
     private static RFunction createFunction(RBuiltinFactory builtinFactory, String methodName) {
         try {
             RFunction function = cachedBuiltinFunctions.get(methodName);
             if (function != null) {
                 return function;
             }
-            RootCallTarget callTarget = RBuiltinNode.createArgumentsCallTarget(builtinFactory);
+            RootCallTarget callTarget = createArgumentsCallTarget(builtinFactory);
             function = RDataFactory.createFunction(builtinFactory.getName(), "base", callTarget, builtinFactory, null);
             cachedBuiltinFunctions.put(methodName, function);
             return function;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
index 40b36e8afd..4a4a475317 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
@@ -43,7 +43,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "aperm", kind = INTERNAL, parameterNames = {"a", "perm", "resize"}, behavior = PURE)
 public abstract class APerm extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
     private final BranchProfile emptyPermVector = BranchProfile.create();
     private final ConditionProfile mustResize = ConditionProfile.createBinaryProfile();
 
@@ -56,8 +55,7 @@ public abstract class APerm extends RBuiltinNode {
 
     private void checkErrorConditions(int[] dim) {
         if (!GetDimAttributeNode.isArray(dim)) {
-            errorProfile.enter();
-            throw RError.error(RError.SHOW_CALLER, RError.Message.FIRST_ARG_MUST_BE_ARRAY);
+            throw error(RError.Message.FIRST_ARG_MUST_BE_ARRAY);
         }
     }
 
@@ -137,8 +135,7 @@ public abstract class APerm extends RBuiltinNode {
         RList dimNames = getDimNamesNode.getDimNames(vector);
         if (dimNames == null) {
             // TODO: this error is reported after IS_OF_WRONG_LENGTH in GnuR
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.DOES_NOT_HAVE_DIMNAMES, "a");
+            throw error(RError.Message.DOES_NOT_HAVE_DIMNAMES, "a");
         }
 
         int[] perm = new int[permVector.getLength()];
@@ -176,22 +173,19 @@ public abstract class APerm extends RBuiltinNode {
             for (int i = 0; i < perm.getLength(); i++) {
                 int pos = perm.getDataAt(i) - 1; // Adjust to zero based permute.
                 if (pos >= perm.getLength() || pos < 0) {
-                    errorProfile.enter();
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.VALUE_OUT_OF_RANGE, "perm");
+                    throw error(RError.Message.VALUE_OUT_OF_RANGE, "perm");
                 }
                 arrayPerm[i] = pos;
                 if (visited[pos]) {
                     // Duplicate dimension mapping in permute
-                    errorProfile.enter();
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "perm");
+                    throw error(RError.Message.INVALID_ARGUMENT, "perm");
                 }
                 visited[pos] = true;
             }
             return arrayPerm;
         } else {
             // perm size error
-            errorProfile.enter();
-            throw RError.error(RError.SHOW_CALLER, RError.Message.IS_OF_WRONG_LENGTH, "perm", perm.getLength(), dim.length);
+            throw error(RError.Message.IS_OF_WRONG_LENGTH, "perm", perm.getLength(), dim.length);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
index acf3a5b1cc..a1c904169a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
@@ -32,8 +32,8 @@ public abstract class Abbrev extends RBuiltinNode {
     static {
         Casts casts = new Casts(Abbrev.class);
         casts.arg("x").mustBe(stringValue());
-        casts.arg("minlength").asIntegerVector().findFirst().notNA();
-        casts.arg("use.classes").asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg("minlength").asIntegerVector().findFirst().mustNotBeNA();
+        casts.arg("use.classes").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
index ce62baed1a..d93063eb23 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
@@ -53,9 +53,9 @@ public abstract class AllNames extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AllNames.class);
-        casts.arg("functions").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA(RRuntime.LOGICAL_FALSE);
-        casts.arg("max.names").asIntegerVector().findFirst(0).notNA(0);
-        casts.arg("unique").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE);
+        casts.arg("functions").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).replaceNA(RRuntime.LOGICAL_FALSE);
+        casts.arg("max.names").asIntegerVector().findFirst(0).replaceNA(0);
+        casts.arg("unique").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).replaceNA(RRuntime.LOGICAL_TRUE);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
index 0e7f1dadde..9778fe9c13 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
@@ -78,9 +78,9 @@ public abstract class Array extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Array.class);
-        casts.arg("data").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", typeName()).mustBe(abstractVectorValue());
-        casts.arg("dim").defaultError(RError.SHOW_CALLER, RError.Message.CANNOT_BE_LENGTH, "dims", 0).mustNotBeNull().asIntegerVector().mustBe(notEmpty());
-        casts.arg("dimnames").defaultError(RError.SHOW_CALLER, RError.Message.DIMNAMES_LIST).allowNull().mustBe(instanceOf(RList.class));
+        casts.arg("data").defaultError(RError.Message.MUST_BE_VECTOR_BUT_WAS, "data", typeName()).mustBe(abstractVectorValue());
+        casts.arg("dim").defaultError(RError.Message.CANNOT_BE_LENGTH, "dims", 0).mustNotBeNull().asIntegerVector().mustBe(notEmpty());
+        casts.arg("dimnames").defaultError(RError.Message.DIMNAMES_LIST).allowNull().mustBe(instanceOf(RList.class));
     }
 
     private int dimDataHelper(RAbstractIntVector dim, int[] dimData) {
@@ -94,9 +94,9 @@ public abstract class Array extends RBuiltinNode {
             totalLength *= dimData[i];
         }
         if (seenNegative == dim.getLength() && seenNegative != 0) {
-            throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
+            throw error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
         } else if (seenNegative > 0) {
-            throw RError.error(this, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED);
+            throw error(RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED);
         }
         return totalLength;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index afc469496d..136f10c14c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -113,6 +113,6 @@ public abstract class AsCall extends RBuiltinNode {
 
     @Fallback
     protected Object asCallFunction(@SuppressWarnings("unused") Object x) {
-        throw RError.error(this, RError.Message.GENERIC, "invalid argument list");
+        throw error(RError.Message.GENERIC, "invalid argument list");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
index a3878fe3db..cb0d77ec54 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
@@ -42,13 +42,14 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "asCharacterFactor", kind = INTERNAL, parameterNames = "x", behavior = PURE)
 public abstract class AsCharacterFactor extends RBuiltinNode {
-    private final NACheck naCheck = NACheck.create();
     private static final RStringVector CLASS_FACTOR_VEC = RDataFactory.createStringVectorFromScalar(RRuntime.CLASS_FACTOR);
 
-    @Child InheritsNode inheritsNode = InheritsNodeGen.create();
-    @Child CastToVectorNode castToVectorNode = CastToVectorNode.create();
+    @Child private InheritsNode inheritsNode = InheritsNodeGen.create();
+    @Child private CastToVectorNode castToVectorNode = CastToVectorNode.create();
     @Child private GetFixedAttributeNode getLevelsAttrNode = GetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY);
 
+    private final NACheck naCheck = NACheck.create();
+
     static {
         Casts.noCasts(AsCharacterFactor.class);
     }
@@ -57,7 +58,7 @@ public abstract class AsCharacterFactor extends RBuiltinNode {
     protected RStringVector doAsCharacterFactor(Object x) {
         byte isFactor = (byte) inheritsNode.execute(x, CLASS_FACTOR_VEC, false);
         if (isFactor == RRuntime.LOGICAL_FALSE) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.COERCE_NON_FACTOR);
+            throw error(RError.Message.COERCE_NON_FACTOR);
         }
         RIntVector xVec = (RIntVector) x;
         int n = xVec.getLength();
@@ -65,7 +66,7 @@ public abstract class AsCharacterFactor extends RBuiltinNode {
         Object levsAttr = getLevelsAttrNode.execute(xVec);
         Object levs;
         if (levsAttr == null || !((levs = castToVectorNode.execute(levsAttr)) instanceof RAbstractStringVector)) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.MALFORMED_FACTOR);
+            throw error(RError.Message.MALFORMED_FACTOR);
         }
         RAbstractStringVector levsString = (RAbstractStringVector) levs;
         int nl = levsString.getLength();
@@ -77,7 +78,7 @@ public abstract class AsCharacterFactor extends RBuiltinNode {
             } else if (xi >= 1 && xi <= nl) {
                 data[i] = levsString.getDataAt(xi - 1);
             } else {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.MALFORMED_FACTOR);
+                throw error(RError.Message.MALFORMED_FACTOR);
             }
         }
         return RDataFactory.createStringVector(data, naCheck.neverSeenNA());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
index a049ddd75d..6480199a1c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
@@ -66,7 +66,7 @@ public abstract class AsFunction extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsFunction.class);
-        casts.arg("x").mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(RExpression.class)), RError.SHOW_CALLER2, RError.Message.TYPE_EXPECTED, RType.List.getName());
+        casts.arg("x").mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(RExpression.class)), RError.Message.TYPE_EXPECTED, RType.List.getName());
         casts.arg("envir").mustBe(instanceOf(REnvironment.class), RError.Message.INVALID_ENVIRONMENT);
     }
 
@@ -74,7 +74,7 @@ public abstract class AsFunction extends RBuiltinNode {
     @TruffleBoundary
     protected RFunction asFunction(RAbstractVector x, REnvironment envir) {
         if (x.getLength() == 0) {
-            throw RError.error(this, RError.Message.GENERIC, "argument must have length at least 1");
+            throw error(RError.Message.GENERIC, "argument must have length at least 1");
         }
         SaveArgumentsNode saveArguments;
         FormalArguments formals;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
index 9b191ab4b9..f313b51e44 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
@@ -98,7 +98,7 @@ public abstract class Assign extends RBuiltinNode {
 
         // this argument could be made Boolean unless there were AssignFastPath relying upon the
         // byte argument
-        casts.arg("inherits").asLogicalVector().findFirst().notNA();
+        casts.arg("inherits").asLogicalVector().findFirst().mustNotBeNA();
     }
 
     /**
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
index f1ef8beb37..b490525f18 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
@@ -116,7 +116,7 @@ public class AttachFunctions {
             try {
                 return REnvironment.detach(pos.getDataAt(0));
             } catch (DetachException ex) {
-                throw RError.error(this, ex);
+                throw error(ex);
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
index 1c9c02253c..ee5ee09e40 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -29,7 +28,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 @RBuiltin(name = "bincode", kind = INTERNAL, parameterNames = {"x", "breaks", "right", "include.lowest"}, behavior = PURE)
 public abstract class Bincode extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
     private final NACheck naCheck = NACheck.create();
 
     static {
@@ -58,8 +56,7 @@ public abstract class Bincode extends RBuiltinNode {
         /* This relies on breaks being sorted, so wise to check that */
         for (int i = 1; i < nb; i++) {
             if (breaks.getDataAt(i - 1) > breaks.getDataAt(i)) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.GENERIC, "'breaks' is not sorted");
+                throw error(RError.Message.GENERIC, "'breaks' is not sorted");
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
index 9fe775ec76..439d14b064 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
@@ -154,7 +154,7 @@ public class BitwiseFunctions {
         @Fallback
         @SuppressWarnings("unused")
         protected Object differentTypes(Object a, Object b) {
-            throw RError.error(this, RError.Message.SAME_TYPE, "a", "b");
+            throw error(RError.Message.SAME_TYPE, "a", "b");
         }
     }
 
@@ -175,7 +175,7 @@ public class BitwiseFunctions {
         @Fallback
         @SuppressWarnings("unused")
         protected Object differentTypes(Object a, Object b) {
-            throw RError.error(this, RError.Message.SAME_TYPE, "a", "b");
+            throw error(RError.Message.SAME_TYPE, "a", "b");
         }
     }
 
@@ -196,7 +196,7 @@ public class BitwiseFunctions {
         @Fallback
         @SuppressWarnings("unused")
         protected Object differentTypes(Object a, Object b) {
-            throw RError.error(this, RError.Message.SAME_TYPE, "a", "b");
+            throw error(RError.Message.SAME_TYPE, "a", "b");
         }
     }
 
@@ -232,9 +232,9 @@ public class BitwiseFunctions {
 
         static {
             Casts casts = new Casts(BitwiseShiftL.class);
-            casts.arg("a").defaultError(RError.ROOTNODE, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe(
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe(
                             doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("n").allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.SHOW_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end(),
+            casts.arg("n").allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.Message.NA_INTRODUCED_COERCION)).end(),
                             asIntegerVector());
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
index 8680eccad3..1cb9a96123 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.utils.Crc64;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -40,7 +39,7 @@ public abstract class CRC64 extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(CRC64.class);
-        casts.arg("x").defaultError(RError.NO_CALLER, Message.INPUT_MUST_BE_STRING).mustBe(stringValue());
+        casts.arg("x").defaultError(Message.INPUT_MUST_BE_STRING).mustBe(stringValue());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
index d1e14444e7..20c0a39034 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
@@ -193,7 +193,7 @@ public abstract class Cat extends RBuiltinNode {
         try (RConnection openConn = conn.forceOpen("wt")) {
             openConn.writeLines(RDataFactory.createStringVectorFromScalar(data), "", false);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
 
         return RNull.instance;
@@ -202,7 +202,7 @@ public abstract class Cat extends RBuiltinNode {
     private void validateType(int argIndex, Object obj) {
         if (obj instanceof RList || obj instanceof RLanguage || obj instanceof RExpression) {
             RTypedValue rType = (RTypedValue) obj;
-            throw RError.error(this, Message.CAT_ARGUMENT_OF_TYPE, argIndex, rType.getRType().getName());
+            throw error(Message.CAT_ARGUMENT_OF_TYPE, argIndex, rType.getRType().getName());
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
index 86c6b72e20..c371f39b79 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -29,8 +28,8 @@ public abstract class CharMatch extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(CharMatch.class);
-        casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, Message.ARG_IS_NOT_OF_MODE, "character");
-        casts.arg("table").mustBe(stringValue(), RError.NO_CALLER, Message.ARG_IS_NOT_OF_MODE, "character");
+        casts.arg("x").mustBe(stringValue(), Message.ARG_IS_NOT_OF_MODE, "character");
+        casts.arg("table").mustBe(stringValue(), Message.ARG_IS_NOT_OF_MODE, "character");
         casts.arg("noMatch").asIntegerVector().findFirst(RRuntime.INT_NA);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
index c72287f73e..cef52279d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
@@ -54,8 +54,8 @@ public abstract class ChooseBuiltin extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(ChooseBuiltin.class);
-        casts.arg("n").mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector());
-        casts.arg("k").mustBe(numericValue(), RError.SHOW_CALLER, Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector());
+        casts.arg("n").mustBe(numericValue(), Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector());
+        casts.arg("k").mustBe(numericValue(), Message.NON_NUMERIC_MATH).mapIf(logicalValue(), asIntegerVector());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
index 242bce76a3..6ceabd9a8f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
@@ -42,7 +42,7 @@ public abstract class Col extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Col.class);
-        casts.arg("dims").defaultError(RError.SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "col").mustBe(integerValue()).asIntegerVector().mustBe(size(2));
+        casts.arg("dims").defaultError(RError.Message.MATRIX_LIKE_REQUIRED, "col").mustBe(integerValue()).asIntegerVector().mustBe(size(2));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
index 34215dc57f..7b3b0aa1ac 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
@@ -48,16 +48,16 @@ public abstract class ColSumsBase extends RBuiltinNode {
 
     protected static Casts createCasts(Class<? extends ColSumsBase> extCls) {
         Casts casts = new Casts(extCls);
-        casts.arg("X").mustBe(numericValue(), RError.SHOW_CALLER, RError.Message.X_NUMERIC);
-        casts.arg("m").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "n").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA);
-        casts.arg("n").defaultError(RError.SHOW_CALLER, INVALID_ARGUMENT, "p").asIntegerVector().findFirst().notNA(RError.NO_CALLER, RError.Message.VECTOR_SIZE_NA);
-        casts.arg("na.rm").asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg("X").mustBe(numericValue(), RError.Message.X_NUMERIC);
+        casts.arg("m").defaultError(INVALID_ARGUMENT, "n").asIntegerVector().findFirst().mustNotBeNA(RError.Message.VECTOR_SIZE_NA);
+        casts.arg("n").defaultError(INVALID_ARGUMENT, "p").asIntegerVector().findFirst().mustNotBeNA(RError.Message.VECTOR_SIZE_NA);
+        casts.arg("na.rm").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         return casts;
     }
 
     protected final void checkVectorLength(RAbstractVector x, int rowNum, int colNum) {
         if (vectorLengthProfile.profile(x.getLength() < rowNum * colNum)) {
-            throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X");
+            throw error(RError.Message.TOO_SHORT, "X");
         }
     }
 
@@ -130,7 +130,7 @@ public abstract class ColSumsBase extends RBuiltinNode {
 
     private void checkLengthOne(int rowNum, int colNum) {
         if (vectorLengthProfile.profile(rowNum * colNum > 1)) {
-            throw RError.error(RError.NO_CALLER, RError.Message.TOO_SHORT, "X");
+            throw error(RError.Message.TOO_SHORT, "X");
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index 601a63c728..f70e479a57 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -25,7 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.Colon.ColonCastNode;
@@ -99,13 +98,11 @@ public abstract class Colon extends RBuiltinNode {
         private final NACheck leftNA = NACheck.create();
         private final NACheck rightNA = NACheck.create();
 
-        private final BranchProfile naCheckErrorProfile = BranchProfile.create();
-
         abstract RSequence execute(Object left, Object right);
 
         private void naCheck(boolean na) {
             if (na) {
-                naCheckErrorProfile.enter();
+                CompilerDirectives.transferToInterpreter();
                 throw RError.error(this, RError.Message.NA_OR_NAN);
             }
         }
@@ -207,6 +204,7 @@ public abstract class Colon extends RBuiltinNode {
                 RError.warning(this, RError.Message.ONLY_FIRST_USED, length);
             }
             if (lengthEqualsZero.profile(length == 0)) {
+                CompilerDirectives.transferToInterpreter();
                 throw RError.error(this, Message.ARGUMENT_LENGTH_0);
             }
         }
@@ -239,11 +237,13 @@ public abstract class Colon extends RBuiltinNode {
             checkLength(vector.getLength());
             String val = vector.getDataAt(0);
             if (RRuntime.isNA(val)) {
+                CompilerDirectives.transferToInterpreter();
                 throw RError.error(this, RError.Message.NA_OR_NAN);
             }
             // TODO it might be a double or complex string
             int result = RRuntime.string2intNoCheck(val);
             if (RRuntime.isNA(result)) {
+                CompilerDirectives.transferToInterpreter();
                 RError.warning(this, RError.Message.NA_INTRODUCED_COERCION);
                 throw RError.error(this, RError.Message.NA_OR_NAN);
             }
@@ -251,8 +251,8 @@ public abstract class Colon extends RBuiltinNode {
         }
 
         @Fallback
-        @TruffleBoundary
         protected int doOther(@SuppressWarnings("unused") Object value) {
+            CompilerDirectives.transferToInterpreter();
             throw RError.error(this, Message.ARGUMENT_LENGTH_0);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
index 5c745baf5c..b2cf2f7964 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
@@ -81,7 +81,7 @@ public class ConditionFunctions {
                         @Cached("createHandlerFrameSlot(frame)") FrameSlot handlerFrameSlot) {
             if (classes.getLength() != handlers.getLength()) {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.BAD_HANDLER_DATA);
+                throw error(RError.Message.BAD_HANDLER_DATA);
             }
             try {
                 if (!frame.isObject(handlerFrameSlot) || frame.getObject(handlerFrameSlot) == null) {
@@ -117,7 +117,7 @@ public class ConditionFunctions {
     public abstract static class RestartAdapter extends RBuiltinNode {
         protected void checkLength(RList restart) {
             if (restart.getLength() < 2) {
-                throw RError.error(this, RError.Message.BAD_RESTART);
+                throw error(RError.Message.BAD_RESTART);
             }
         }
 
@@ -182,7 +182,7 @@ public class ConditionFunctions {
         protected RNull invokeRestart(RList restart, Object args) {
             checkLength(restart);
             if (RErrorHandling.invokeRestart(restart, args) == null) {
-                throw RError.error(this, RError.Message.RESTART_NOT_ON_STACK);
+                throw error(RError.Message.RESTART_NOT_ON_STACK);
             } else {
                 return RNull.instance; // not reached
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index a959470c20..b4203c3d0f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -140,11 +140,11 @@ public abstract class ConnectionFunctions {
 
     public static final class CastsHelper {
         private static void description(Casts casts) {
-            casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().notNA();
+            casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
         }
 
         private static HeadPhaseBuilder<String> open(Casts casts) {
-            return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA();
+            return casts.arg("open").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustNotBeNA();
         }
 
         private static HeadPhaseBuilder<String> openMode(Casts casts) {
@@ -157,11 +157,11 @@ public abstract class ConnectionFunctions {
         }
 
         private static void raw(Casts casts) {
-            casts.arg("raw").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("raw").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         private static void blocking(Casts casts) {
-            casts.arg("blocking").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("blocking").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         public static void connection(Casts casts) {
@@ -173,7 +173,7 @@ public abstract class ConnectionFunctions {
         }
 
         private static void useBytes(Casts casts) {
-            casts.arg("useBytes").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("useBytes").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         private static void n(Casts casts) {
@@ -185,7 +185,7 @@ public abstract class ConnectionFunctions {
         }
 
         private static void swap(Casts casts) {
-            casts.arg("swap").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("swap").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         private static void method(Casts casts) {
@@ -228,7 +228,7 @@ public abstract class ConnectionFunctions {
                 return new FileRConnection(path, open).asVector();
             } catch (IOException ex) {
                 RError.warning(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
     }
@@ -250,7 +250,7 @@ public abstract class ConnectionFunctions {
             CastsHelper.description(casts);
             CastsHelper.open(casts);
             CastsHelper.encoding(casts);
-            casts.arg("compression").asIntegerVector().findFirst().notNA().mustBe(gte(cType == RCompression.Type.XZ ? -9 : 0).and(lte(9)));
+            casts.arg("compression").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte(cType == RCompression.Type.XZ ? -9 : 0).and(lte(9)));
             return casts;
         }
 
@@ -264,9 +264,9 @@ public abstract class ConnectionFunctions {
             }
         }
 
-        private static RError reportError(String path, IOException ex) throws RError {
+        private RError reportError(String path, IOException ex) throws RError {
             RError.warning(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage());
-            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+            throw error(RError.Message.CANNOT_OPEN_CONNECTION);
         }
     }
 
@@ -315,7 +315,7 @@ public abstract class ConnectionFunctions {
             casts.arg("text").allowNull().mustBe(stringValue());
             CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
             casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
-            casts.arg("encoding").asIntegerVector().findFirst().notNA();
+            casts.arg("encoding").asIntegerVector().findFirst().mustNotBeNA();
         }
 
         @Specialization
@@ -333,7 +333,7 @@ public abstract class ConnectionFunctions {
         @TruffleBoundary
         protected RAbstractIntVector textConnection(String description, RNull text, String open, REnvironment env, int encoding) {
             if (open.length() == 0 || open.equals("r")) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "text");
+                throw error(RError.Message.INVALID_ARGUMENT, "text");
             } else {
                 throw RError.nyi(RError.SHOW_CALLER, "textConnection: NULL");
             }
@@ -355,7 +355,7 @@ public abstract class ConnectionFunctions {
             if (connection instanceof TextRConnection) {
                 return RDataFactory.createStringVector(((TextRConnection) connection).getValue(), RDataFactory.COMPLETE_VECTOR);
             } else {
-                throw RError.error(RError.SHOW_CALLER, Message.NOT_A_TEXT_CONNECTION);
+                throw error(Message.NOT_A_TEXT_CONNECTION);
             }
         }
     }
@@ -366,8 +366,8 @@ public abstract class ConnectionFunctions {
         static {
             Casts casts = new Casts(SocketConnection.class);
             casts.arg("host").mustBe(stringValue()).asStringVector().findFirst();
-            casts.arg("port").asIntegerVector().findFirst().notNA().mustBe(gte(0));
-            casts.arg("server").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("port").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte(0));
+            casts.arg("server").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
             CastsHelper.open(casts);
             CastsHelper.blocking(casts);
             casts.arg("timeout").asIntegerVector().findFirst();
@@ -379,7 +379,7 @@ public abstract class ConnectionFunctions {
             try {
                 return new RSocketConnection(open, server, host, port, blocking, timeout).asVector();
             } catch (IOException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
     }
@@ -403,9 +403,9 @@ public abstract class ConnectionFunctions {
             try {
                 return new URLRConnection(url, open).asVector();
             } catch (MalformedURLException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_URL_SCHEME);
+                throw error(RError.Message.UNSUPPORTED_URL_SCHEME);
             } catch (IOException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
     }
@@ -456,7 +456,7 @@ public abstract class ConnectionFunctions {
             if (connection instanceof RawRConnection) {
                 return RDataFactory.createRawVector(((RawRConnection) connection).getValue());
             } else {
-                throw RError.error(RError.SHOW_CALLER, Message.NOT_A_RAW_CONNECTION);
+                throw error(Message.NOT_A_RAW_CONNECTION);
             }
         }
     }
@@ -503,7 +503,7 @@ public abstract class ConnectionFunctions {
             try {
                 BaseRConnection baseConn = getBaseConnection(RConnection.fromIndex(con));
                 if (baseConn.isClosed()) {
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_CONNECTION);
+                    throw error(RError.Message.INVALID_CONNECTION);
                 }
                 if (baseConn.isOpen()) {
                     RError.warning(RError.SHOW_CALLER, RError.Message.ALREADY_OPEN_CONNECTION);
@@ -511,7 +511,7 @@ public abstract class ConnectionFunctions {
                 }
                 baseConn.open(open);
             } catch (IOException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, ex.getMessage());
+                throw error(RError.Message.GENERIC, ex.getMessage());
             }
             return RNull.instance;
         }
@@ -541,7 +541,7 @@ public abstract class ConnectionFunctions {
                     result &= baseCon.canWrite();
                     break;
                 default:
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_VALUE, "rw");
+                    throw error(RError.Message.UNKNOWN_VALUE, "rw");
             }
             return RDataFactory.createLogicalVectorFromScalar(result);
         }
@@ -563,7 +563,7 @@ public abstract class ConnectionFunctions {
             try {
                 connection.closeAndDestroy();
             } catch (IOException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, ex.getMessage());
+                throw error(RError.Message.GENERIC, ex.getMessage());
             }
             return RNull.instance;
         }
@@ -575,11 +575,11 @@ public abstract class ConnectionFunctions {
         static {
             Casts casts = new Casts(ReadLines.class);
             CastsHelper.connection(casts);
-            casts.arg("n").asIntegerVector().findFirst().notNA();
-            casts.arg("ok").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("warn").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("n").asIntegerVector().findFirst().mustNotBeNA();
+            casts.arg("ok").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("warn").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
             CastsHelper.encoding(casts);
-            casts.arg("skipNul").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("skipNul").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -589,11 +589,11 @@ public abstract class ConnectionFunctions {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("rt")) {
                 String[] lines = openConn.readLines(n, warn, skipNul);
                 if (n > 0 && lines.length < n && !ok) {
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.TOO_FEW_LINES_READ_LINES);
+                    throw error(RError.Message.TOO_FEW_LINES_READ_LINES);
                 }
                 return RDataFactory.createStringVector(lines, RDataFactory.COMPLETE_VECTOR);
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
+                throw error(RError.Message.ERROR_READING_CONNECTION, x.getMessage());
             }
         }
     }
@@ -615,7 +615,7 @@ public abstract class ConnectionFunctions {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wt")) {
                 openConn.writeLines(text, sep, useBytes);
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
+                throw error(RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
             }
             return RNull.instance;
         }
@@ -635,7 +635,7 @@ public abstract class ConnectionFunctions {
             try {
                 RConnection.fromIndex(con).flush();
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_FLUSHING_CONNECTION, x.getMessage());
+                throw error(RError.Message.ERROR_FLUSHING_CONNECTION, x.getMessage());
             }
             return RNull.instance;
         }
@@ -648,7 +648,7 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(PushBack.class);
             casts.arg("data").asStringVector().mustBe(instanceOf(RAbstractStringVector.class));
             CastsHelper.connection(casts);
-            casts.arg("newLine").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("newLine").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
             casts.arg("type").asIntegerVector().findFirst();
         }
 
@@ -715,7 +715,7 @@ public abstract class ConnectionFunctions {
                 }
                 return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
+                throw error(RError.Message.ERROR_READING_CONNECTION, x.getMessage());
             }
         }
 
@@ -730,10 +730,10 @@ public abstract class ConnectionFunctions {
         static {
             // @formatter:off
             Casts casts = new Casts(WriteChar.class);
-            casts.arg("object").mustBe(stringValue(), RError.SHOW_CALLER, Message.ONLY_WRITE_CHAR_OBJECTS).asStringVector();
+            casts.arg("object").mustBe(stringValue(), Message.ONLY_WRITE_CHAR_OBJECTS).asStringVector();
             casts.arg("con").mustBe(rawValue().not(), Message.GENERIC, "raw connection in writeChar not implemented in FastR yet.").
                     mustBe(stringValue().not(), Message.GENERIC, "filename as a connection in writeChar not implemented in FastR yet.").
-                    mustBe(integerValue(), RError.SHOW_CALLER, Message.INVALID_CONNECTION).asIntegerVector().findFirst();
+                    mustBe(integerValue(), Message.INVALID_CONNECTION).asIntegerVector().findFirst();
             CastsHelper.nchars(casts);
             casts.arg("sep").mustNotBeMissing().returnIf(nullValue()).mustBe(stringValue()).asStringVector();
             CastsHelper.useBytes(casts);
@@ -746,7 +746,7 @@ public abstract class ConnectionFunctions {
         }
 
         @TruffleBoundary
-        private static RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
+        private RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wb")) {
                 int length = object.getLength();
                 for (int i = 0; i < length; i++) {
@@ -761,7 +761,7 @@ public abstract class ConnectionFunctions {
                     openConn.writeChar(s.substring(0, writeLen), pad, getSepFor(sep, i), useBytes);
                 }
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
+                throw error(RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
             }
             return RNull.instance;
         }
@@ -803,7 +803,7 @@ public abstract class ConnectionFunctions {
             casts.arg("what").asStringVector().findFirst();
             CastsHelper.n(casts);
             CastsHelper.size(casts);
-            casts.arg("signed").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("signed").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
             CastsHelper.swap(casts);
         }
 
@@ -814,7 +814,7 @@ public abstract class ConnectionFunctions {
             BaseRConnection connection = RConnection.fromIndex(con);
             try (RConnection openConn = connection.forceOpen("rb")) {
                 if (getBaseConnection(openConn).getOpenMode().isText()) {
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.ONLY_READ_BINARY_CONNECTION);
+                    throw error(RError.Message.ONLY_READ_BINARY_CONNECTION);
                 }
                 switch (what) {
                     case "int":
@@ -849,7 +849,7 @@ public abstract class ConnectionFunctions {
                         throw RInternalError.shouldNotReachHere();
                 }
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, x.getMessage());
+                throw error(RError.Message.ERROR_READING_CONNECTION, x.getMessage());
             }
             return result;
         }
@@ -1097,19 +1097,19 @@ public abstract class ConnectionFunctions {
         protected Object writeBin(RAbstractVector object, int con, int size, boolean swap, boolean useBytes,
                         @Cached("create()") WriteDataNode writeData) {
             if (object instanceof RList || object instanceof RExpression) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "object");
+                throw error(RError.Message.INVALID_ARGUMENT, "object");
             }
             if (object.getLength() > 0) {
                 RConnection connection = RConnection.fromIndex(con);
                 try (RConnection openConn = connection.forceOpen("wb")) {
                     if (getBaseConnection(openConn).isTextMode()) {
-                        throw RError.error(RError.SHOW_CALLER, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
+                        throw error(RError.Message.ONLY_WRITE_BINARY_CONNECTION);
                     }
                     ByteBuffer buffer = writeData.execute(object, size, swap, useBytes);
                     buffer.flip();
                     connection.writeBin(buffer);
                 } catch (IOException x) {
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
+                    throw error(RError.Message.ERROR_WRITING_CONNECTION, x.getMessage());
                 }
             }
             return RNull.instance;
@@ -1137,7 +1137,7 @@ public abstract class ConnectionFunctions {
         protected RAbstractIntVector getConnection(int what) {
             BaseRConnection con = RContext.getInstance().stateRConnection.getConnection(what, false);
             if (con == null) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.NO_SUCH_CONNECTION, what);
+                throw error(RError.Message.NO_SUCH_CONNECTION, what);
             } else {
                 return con.asVector();
             }
@@ -1199,7 +1199,7 @@ public abstract class ConnectionFunctions {
                 }
                 return (int) newOffset;
             } catch (IOException x) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, x.getMessage());
+                throw error(RError.Message.GENERIC, x.getMessage());
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
index 36d37e5547..cd0f1324ed 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
@@ -48,7 +48,7 @@ public abstract class Contributors extends RBuiltinNode {
         try {
             StdConnections.getStdout().writeString(CONTRIBUTORS, true);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
index 8917f9ffe0..4928c3ee38 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
@@ -47,8 +47,8 @@ public abstract class Crossprod extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Crossprod.class);
-        casts.arg("x").mustBe(numericValue().or(complexValue()), RError.ROOTNODE, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
-        casts.arg("y").defaultError(RError.ROOTNODE, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue()));
+        casts.arg("x").mustBe(numericValue().or(complexValue()), RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
+        casts.arg("y").defaultError(RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue()));
     }
 
     private Object matMult(Object op1, Object op2) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
index 8a72551092..1a1f358599 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
@@ -56,7 +56,7 @@ public abstract class DPut extends RBuiltinNode {
         try (RConnection openConn = RConnection.fromIndex(file).forceOpen("wt")) {
             openConn.writeString(string, true);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
         return x;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
index c6f3bba716..6ed51005c6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
@@ -52,7 +52,7 @@ public class DebugFunctions {
             // GnuR does not generate an error for builtins, but debug (obviously) has no effect
             if (!fun.isBuiltin()) {
                 if (!DebugHandling.enableDebug(fun, text, condition, once, false)) {
-                    throw RError.error(this, RError.Message.GENERIC, "failed to attach debug handler (not instrumented?)");
+                    throw error(RError.Message.GENERIC, "failed to attach debug handler (not instrumented?)");
                 }
             }
         }
@@ -100,7 +100,7 @@ public class DebugFunctions {
         @TruffleBoundary
         protected RNull undebug(RFunction func) {
             if (!DebugHandling.undebug(func)) {
-                throw RError.error(this, RError.Message.NOT_DEBUGGED);
+                throw error(RError.Message.NOT_DEBUGGED);
             }
             return RNull.instance;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
index 6db3144a98..41271c43ea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -46,13 +45,11 @@ import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 @RBuiltin(name = "delayedAssign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "eval.env", "assign.env"}, behavior = COMPLEX)
 public abstract class DelayedAssign extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     static {
         Casts casts = new Casts(DelayedAssign.class);
         casts.arg("x").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_FIRST_ARGUMENT).findFirst();
-        casts.arg("eval.env").mustNotBeNull(RError.SHOW_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
-        casts.arg("assign.env").mustNotBeNull(RError.SHOW_CALLER, RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
+        casts.arg("eval.env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
+        casts.arg("assign.env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
     }
 
     @Specialization
@@ -62,8 +59,7 @@ public abstract class DelayedAssign extends RBuiltinNode {
             assignEnv.put(name, RDataFactory.createPromise(PromiseState.Explicit, Closure.create(RASTUtils.createNodeForValue(value)), evalEnv.getFrame()));
             return RNull.instance;
         } catch (PutException ex) {
-            errorProfile.enter();
-            throw RError.error(this, ex);
+            throw error(ex);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
index 56e2cae7e7..c9c2b803af 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
@@ -23,7 +23,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -44,11 +43,11 @@ public abstract class Diag extends RBuiltinNode {
         casts.arg("ncol").asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_LARGE_NA_VALUE, "ncol").mustBe(gte0(), Message.INVALID_NEGATIVE_VALUE, "ncol");
     }
 
-    private static int checkX(RAbstractVector x, int nrow, int ncol) {
+    private int checkX(RAbstractVector x, int nrow, int ncol) {
         int mn = (nrow < ncol) ? nrow : ncol;
         if (mn > 0 && x.getLength() == 0) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(RError.SHOW_CALLER2, Message.POSITIVE_LENGTH, "x");
+            throw error(Message.POSITIVE_LENGTH, "x");
         }
         return mn;
     }
@@ -58,7 +57,7 @@ public abstract class Diag extends RBuiltinNode {
         if (nrow == 0 && ncol == 0) {
             return RDataFactory.createDoubleVector(new double[]{}, true, new int[]{0, 0});
         } else {
-            throw RError.error(RError.SHOW_CALLER2, Message.X_NUMERIC);
+            throw error(Message.X_NUMERIC);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 9976ccbaa8..8a56fb21ff 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -94,7 +94,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
     protected ReadVariableNode createRead(RAbstractStringVector what) {
         if (what.getLength() != 1) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
+            throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
         }
         return ReadVariableNode.createForcedFunctionLookup(RSyntaxNode.INTERNAL, what.getDataAt(0));
     }
@@ -104,7 +104,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
                     @Cached("createGet()") Get getNode) {
         if (what.getLength() != 1) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
+            throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
         }
         RFunction func = (RFunction) getNode.execute(frame, what.getDataAt(0), env, RType.Function.getName(), true);
         return doCall(frame, func, argsAsList, quote, env);
@@ -121,7 +121,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
     protected Object doCall(VirtualFrame frame, RAbstractStringVector what, RList argsAsList, boolean quote, RMissing env) {
         if (what.getLength() != 1) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
+            throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
         }
         RFunction func = ReadVariableNode.lookupFunction(what.getDataAt(0), frame.materialize());
         return doCall(frame, func, argsAsList, quote, env);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
index 066f216726..b2043833e9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
@@ -47,7 +47,7 @@ public class DuplicatedFunctions {
 
         protected static void casts(Casts casts) {
             // these are similar to those in DuplicatedFunctions.java
-            casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.SHOW_CALLER, RError.Message.APPLIES_TO_VECTORS, "duplicated()").asVector();
+            casts.arg("x").mapNull(emptyList()).mustBe(abstractVectorValue(), RError.Message.APPLIES_TO_VECTORS, "duplicated()").asVector();
             // not much more can be done for incomparables as it is either a vector of incomparable
             // values or a (single) logical value
             casts.arg("incomparables").asVector(true);
@@ -119,7 +119,7 @@ public class DuplicatedFunctions {
             RType xType = typeof.execute(x);
             // TODO: this is not quite correct, as passing expression generated some obscure error
             // message, but is it worth fixing
-            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, ((RTypedValue) incomparables).getRType().getName(), xType.getName());
+            throw error(RError.Message.CANNOT_COERCE, ((RTypedValue) incomparables).getRType().getName(), xType.getName());
         }
 
         @SuppressWarnings("unused")
@@ -156,7 +156,7 @@ public class DuplicatedFunctions {
             initChildren();
             // TODO: this is not quite correct, as passing expression generated some obscure error
             // message, but is it worth fixing
-            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, TypeofNode.getTypeof(incomparables).getName(), TypeofNode.getTypeof(x).getName());
+            throw error(RError.Message.CANNOT_COERCE, TypeofNode.getTypeof(incomparables).getName(), TypeofNode.getTypeof(x).getName());
         }
 
         @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
index 688dd47a2c..535ada9f47 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
@@ -76,7 +76,7 @@ public class DynLoadFunctions {
                 DLLInfo dllInfo = loadPackageDLLNode.execute(lib, local, now);
                 return dllInfo.toRList();
             } catch (DLLException ex) {
-                throw RError.error(RError.SHOW_CALLER, ex);
+                throw error(ex);
             }
         }
     }
@@ -96,7 +96,7 @@ public class DynLoadFunctions {
             try {
                 dllUnloadNode.execute(lib.getDataAt(0));
             } catch (DLLException ex) {
-                throw RError.error(this, ex);
+                throw error(ex);
             }
             return RNull.instance;
         }
@@ -189,7 +189,7 @@ public class DynLoadFunctions {
                         @Cached("create()") DLL.RdlsymNode dlsymNode) {
             DLL.DLLInfo dllInfo = (DLLInfo) externalPtr.getExternalObject();
             if (dllInfo == null) {
-                throw RError.error(this, RError.Message.REQUIRES_NAME_DLLINFO);
+                throw error(RError.Message.REQUIRES_NAME_DLLINFO);
             }
 
             DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
index 9b05c97603..6bd38e8e75 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
@@ -42,7 +42,7 @@ public class EncodingFunctions {
 
         static {
             Casts casts = new Casts(Encoding.class);
-            casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT);
+            casts.arg("x").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT);
         }
 
         @Specialization
@@ -57,10 +57,10 @@ public class EncodingFunctions {
 
         static {
             Casts casts = new Casts(SetEncoding.class);
-            casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.CHAR_VEC_ARGUMENT).mustBe(stringValue());
+            casts.arg("x").defaultError(RError.Message.CHAR_VEC_ARGUMENT).mustBe(stringValue());
             // asStringVector is required for notEmpty() to receive a proper type in case of scalars
-            casts.arg("value").defaultError(RError.SHOW_CALLER, RError.Message.GENERIC, "a character vector 'value' expected").mustBe(stringValue()).asStringVector().mustBe(notEmpty(),
-                            RError.SHOW_CALLER, RError.Message.GENERIC, "'value' must be of positive length");
+            casts.arg("value").defaultError(RError.Message.GENERIC, "a character vector 'value' expected").mustBe(stringValue()).asStringVector().mustBe(notEmpty(),
+                            RError.Message.GENERIC, "'value' must be of positive length");
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index f71df176ee..390b88decb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -101,7 +101,7 @@ public class EnvFunctions {
 
         @Specialization
         protected REnvironment asEnvironment(@SuppressWarnings("unused") RNull rnull) {
-            throw RError.error(this, RError.Message.AS_ENV_NULL_DEFUNCT);
+            throw error(RError.Message.AS_ENV_NULL_DEFUNCT);
         }
 
         @Specialization
@@ -114,7 +114,7 @@ public class EnvFunctions {
                         @Cached("new()") GetCallerFrameNode getCallerFrame) {
             if (pos.getLength() == 0) {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, Message.INVALID_ARGUMENT, "pos");
+                throw error(Message.INVALID_ARGUMENT, "pos");
             }
             Object[] results = pos.getLength() == 1 ? null : new Object[pos.getLength()];
             for (int i = 0; i < pos.getLength(); i++) {
@@ -122,8 +122,7 @@ public class EnvFunctions {
                 int p = pos.getDataAt(i);
                 if (p == -1) {
                     if (RArguments.getDepth(frame) == 0) {
-                        errorProfile.enter();
-                        throw RError.error(this, RError.Message.NO_ENCLOSING_ENVIRONMENT);
+                        throw error(RError.Message.NO_ENCLOSING_ENVIRONMENT);
                     }
                     Frame callerFrame = getCallerFrame.execute(frame);
                     env = REnvironment.frameToEnvironment(callerFrame.materialize());
@@ -146,8 +145,7 @@ public class EnvFunctions {
                 // not accessible by name, GnuR allows it to be accessible by index
                 return REnvironment.emptyEnv();
             } else if ((p <= 0) || (p > searchPath.length + 1)) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pos");
+                throw error(RError.Message.INVALID_ARGUMENT, "pos");
             } else {
                 return REnvironment.lookupOnSearchPath(searchPath[p - 1]);
             }
@@ -163,8 +161,7 @@ public class EnvFunctions {
                     return REnvironment.lookupOnSearchPath(e);
                 }
             }
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.NO_ITEM_NAMED, name);
+            throw error(RError.Message.NO_ITEM_NAMED, name);
         }
 
         @Specialization
@@ -185,7 +182,7 @@ public class EnvFunctions {
             // generic dispatch tried already
             Object xData = getXDataAttrNode.execute(obj);
             if (xData == null || !(xData instanceof REnvironment)) {
-                throw RError.error(this, RError.Message.S4OBJECT_NX_ENVIRONMENT);
+                throw error(RError.Message.S4OBJECT_NX_ENVIRONMENT);
             } else {
                 return xData;
             }
@@ -193,7 +190,7 @@ public class EnvFunctions {
 
         @Fallback
         protected REnvironment asEnvironment(@SuppressWarnings("unused") Object object) {
-            throw RError.error(this, RError.Message.INVALID_OBJECT);
+            throw error(RError.Message.INVALID_OBJECT);
         }
     }
 
@@ -286,14 +283,14 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(ParentEnv.class);
-            casts.arg("env").mustBe(instanceOf(REnvironment.class), RError.SHOW_CALLER, Message.ARGUMENT_NOT_ENVIRONMENT);
+            casts.arg("env").mustBe(instanceOf(REnvironment.class), Message.ARGUMENT_NOT_ENVIRONMENT);
         }
 
         @Specialization
         protected REnvironment parentenv(REnvironment env) {
             if (env == REnvironment.emptyEnv()) {
                 errorProfile.enter();
-                throw RError.error(RError.SHOW_CALLER, RError.Message.EMPTY_NO_PARENT);
+                throw error(RError.Message.EMPTY_NO_PARENT);
             }
             return env.getParent();
         }
@@ -312,7 +309,7 @@ public class EnvFunctions {
         @TruffleBoundary
         protected REnvironment setParentenv(REnvironment env, REnvironment parent) {
             if (env == REnvironment.emptyEnv()) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_SET_PARENT);
+                throw error(RError.Message.CANNOT_SET_PARENT);
             }
             env.setParent(parent);
             return env;
@@ -424,7 +421,7 @@ public class EnvFunctions {
         @Specialization
         @TruffleBoundary
         protected Object updateEnvironment(@SuppressWarnings("unused") RFunction fun, @SuppressWarnings("unused") RNull env) {
-            throw RError.error(this, RError.Message.USE_NULL_ENV_DEFUNCT);
+            throw error(RError.Message.USE_NULL_ENV_DEFUNCT);
         }
 
         protected SetFixedAttributeNode createSetEnvAttrNode() {
@@ -468,7 +465,7 @@ public class EnvFunctions {
         @Specialization
         @TruffleBoundary
         protected Object updateEnvironment(@SuppressWarnings("unused") RNull obj, @SuppressWarnings("unused") REnvironment env) {
-            throw RError.error(this, Message.SET_ATTRIBUTES_ON_NULL);
+            throw error(Message.SET_ATTRIBUTES_ON_NULL);
         }
     }
 
@@ -523,7 +520,7 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(LockEnvironment.class);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
             // TODO: the actual interpretation of this parameter remains dubious
             casts.arg("bindings").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
@@ -540,7 +537,7 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(EnvironmentIsLocked.class);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
         @Specialization
@@ -554,8 +551,8 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(LockBinding.class);
-            casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
         @Specialization
@@ -570,8 +567,8 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(UnlockBinding.class);
-            casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
         @Specialization
@@ -586,8 +583,8 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(BindingIsLocked.class);
-            casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
         @Specialization
@@ -601,9 +598,9 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(MakeActiveBinding.class);
-            casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
-            casts.arg("fun").mustBe(RFunction.class, RError.SHOW_CALLER, Message.NOT_A_FUNCTION);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL);
+            casts.arg("fun").mustBe(RFunction.class, Message.NOT_A_FUNCTION);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
         @SuppressWarnings("unused")
@@ -619,8 +616,8 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(BindingIsActive.class);
-            casts.arg("sym").mustBe(RSymbol.class, RError.SHOW_CALLER, Message.NOT_A_SYMBOL);
-            casts.arg("env").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("sym").mustBe(RSymbol.class, Message.NOT_A_SYMBOL);
+            casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
         @SuppressWarnings("unused")
@@ -638,7 +635,7 @@ public class EnvFunctions {
 
         static {
             Casts casts = new Casts(EnvToList.class);
-            casts.arg("x").mustBe(REnvironment.class, RError.SHOW_CALLER, Message.NOT_AN_ENVIRONMENT);
+            casts.arg("x").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
             casts.arg("all.names").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
             casts.arg("sorted").mustNotBeNull().asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index 8dfde766fb..bd1710371d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -147,7 +147,7 @@ public class FileFunctions {
             int len1 = file1Vec.getLength();
             int len2 = file2Vec.getLength();
             if (len1 < 1) {
-                throw RError.error(this, RError.Message.FILE_APPEND_TO);
+                throw error(RError.Message.FILE_APPEND_TO);
             }
             if (len2 < 1) {
                 return RDataFactory.createEmptyLogicalVector();
@@ -436,7 +436,7 @@ public class FileFunctions {
             int lenFrom = vecFrom.getLength();
             int lenTo = vecTo.getLength();
             if (lenFrom < 1) {
-                throw RError.error(this, RError.Message.NOTHING_TO_LINK);
+                throw error(RError.Message.NOTHING_TO_LINK);
             }
             if (lenTo < 1) {
                 return RDataFactory.createLogicalVector(0);
@@ -544,7 +544,7 @@ public class FileFunctions {
         protected Object doFileRename(RAbstractStringVector vecFrom, RAbstractStringVector vecTo) {
             int len = vecFrom.getLength();
             if (len != vecTo.getLength()) {
-                throw RError.error(this, RError.Message.FROM_TO_DIFFERENT);
+                throw error(RError.Message.FROM_TO_DIFFERENT);
             }
             byte[] status = new byte[len];
             for (int i = 0; i < len; i++) {
@@ -602,12 +602,12 @@ public class FileFunctions {
             Casts casts = new Casts(ListFiles.class);
             casts.arg("path").mustBe(stringValue()).asStringVector();
             casts.arg("pattern").allowNull().mustBe(stringValue());
-            casts.arg("all.files").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("full.names").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("ignore.case").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("include.dirs").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("no..").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("all.files").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("full.names").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("ignore.case").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("include.dirs").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("no..").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @SuppressWarnings("unused")
@@ -632,7 +632,7 @@ public class FileFunctions {
             String pattern = null;
             if (patternVec.getLength() > 0) {
                 if (RRuntime.isNA(patternVec.getDataAt(0))) {
-                    throw RError.error(this, RError.Message.INVALID_ARGUMENT, "pattern");
+                    throw error(RError.Message.INVALID_ARGUMENT, "pattern");
                 } else {
                     pattern = patternVec.getDataAt(0);
                 }
@@ -743,8 +743,8 @@ public class FileFunctions {
         static {
             Casts casts = new Casts(ListDirs.class);
             casts.arg("directory").mustBe(stringValue()).asStringVector();
-            casts.arg("full.names").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("full.names").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -799,7 +799,7 @@ public class FileFunctions {
         static {
             Casts casts = new Casts(FilePath.class);
             casts.arg("paths").mustBe(instanceOf(RList.class), RError.Message.INVALID_FIRST_ARGUMENT);
-            casts.arg("fsep").mustBe(stringValue()).asStringVector().findFirst().notNA();
+            casts.arg("fsep").mustBe(stringValue()).asStringVector().findFirst().mustNotBeNA();
         }
 
         @Child private CastStringNode castStringNode;
@@ -857,7 +857,7 @@ public class FileFunctions {
                 } else if (elem instanceof RStringVector) {
                     inputs[i] = ((RStringVector) elem).getDataWithoutCopying();
                 } else {
-                    throw RError.error(this, RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE);
+                    throw error(RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE);
                 }
             }
             for (int i = 0; i < resultLength; i++) {
@@ -899,10 +899,10 @@ public class FileFunctions {
             Casts casts = new Casts(FileCopy.class);
             casts.arg("from").mustBe(stringValue()).asStringVector();
             casts.arg("to").mustBe(stringValue()).asStringVector();
-            casts.arg("overwrite").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("copy.mode").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("copy.date").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("overwrite").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("copy.mode").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("copy.date").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -914,7 +914,7 @@ public class FileFunctions {
             if (lenFrom > 0) {
                 int lenTo = vecTo.getLength();
                 if (lenTo != 1) {
-                    throw RError.error(this, RError.Message.INVALID_ARGUMENT, "to");
+                    throw error(RError.Message.INVALID_ARGUMENT, "to");
                 }
 
                 // Java cannot distinguish copy.mode and copy.dates
@@ -1041,7 +1041,7 @@ public class FileFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected static RNull show(RAbstractStringVector files, RAbstractStringVector header, RAbstractStringVector title, boolean deleteFile, @SuppressWarnings("unused") String pager) {
+        protected RNull show(RAbstractStringVector files, RAbstractStringVector header, RAbstractStringVector title, boolean deleteFile, @SuppressWarnings("unused") String pager) {
             ConsoleHandler console = RContext.getInstance().getConsoleHandler();
             for (int i = 0; i < title.getLength(); i++) {
                 console.println("==== " + title.getDataAt(i) + " ====");
@@ -1060,7 +1060,7 @@ public class FileFunctions {
                         path.toFile().delete();
                     }
                 } catch (IOException e) {
-                    throw RError.error(RError.SHOW_CALLER, Message.GENERIC, e.getMessage());
+                    throw error(Message.GENERIC, e.getMessage());
                 }
             }
             return RNull.instance;
@@ -1129,8 +1129,8 @@ public class FileFunctions {
         static {
             Casts casts = new Casts(Unlink.class);
             casts.arg("x").mustBe(stringValue(), RError.Message.CHAR_VEC_ARGUMENT);
-            casts.arg("recursive").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("force").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("recursive").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("force").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index ad0e3d20d3..05b94d6661 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -90,12 +90,12 @@ public abstract class Format extends RBuiltinNode {
     static {
         Casts casts = new Casts(Format.class);
         casts.arg("x");
-        casts.arg("trim").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean());
+        casts.arg("trim").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
         casts.arg("digits").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(R_MIN_DIGITS_OPT).and(lte(R_MAX_DIGITS_OPT))));
         casts.arg("nsmall").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(0).and(lte(20))));
-        casts.arg("width").asIntegerVector().findFirst(0).notNA();
+        casts.arg("width").asIntegerVector().findFirst(0).mustNotBeNA();
         casts.arg("justify").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(0).and(lte(3))));
-        casts.arg("na.encode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean());
+        casts.arg("na.encode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
         casts.arg("scientific").asIntegerVector().findFirst();
         casts.arg("decimal.mark").asStringVector().findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
index 109ff35ab3..19e877dcd4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
@@ -93,7 +93,6 @@ public class FrameFunctions {
     public abstract static class FrameHelper extends RBuiltinNode {
 
         private final ConditionProfile currentFrameProfile = ConditionProfile.createBinaryProfile();
-        protected final BranchProfile errorProfile = BranchProfile.create();
 
         /**
          * Determine the frame access mode of a subclass. The rule of thumb is that subclasses that
@@ -134,14 +133,12 @@ public class FrameFunctions {
             int depth = call.getDepth();
             if (n > 0) {
                 if (n > depth) {
-                    errorProfile.enter();
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_THAT_MANY_FRAMES);
+                    throw error(RError.Message.NOT_THAT_MANY_FRAMES);
                 }
                 return n;
             } else {
                 if (-n > depth) {
-                    errorProfile.enter();
-                    throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_THAT_MANY_FRAMES);
+                    throw error(RError.Message.NOT_THAT_MANY_FRAMES);
                 }
                 return depth + n;
             }
@@ -253,7 +250,7 @@ public class FrameFunctions {
              */
             RLanguage call = checkCall(callObj);
             if (expandDotsL == RRuntime.LOGICAL_NA) {
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "expand.dots");
+                throw error(RError.Message.INVALID_ARGUMENT, "expand.dots");
             }
             boolean expandDots = RRuntime.fromLogical(expandDotsL);
 
@@ -384,7 +381,7 @@ public class FrameFunctions {
         @Specialization
         @SuppressWarnings("unused")
         protected RLanguage matchCall(Object definition, Object call, Object expandDots, Object envir) {
-            throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
         }
 
         private RLanguage checkCall(Object obj) throws RError {
@@ -399,7 +396,7 @@ public class FrameFunctions {
                     return call;
                 }
             }
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "call");
+            throw error(RError.Message.INVALID_ARGUMENT, "call");
         }
     }
 
@@ -684,8 +681,7 @@ public class FrameFunctions {
         @Specialization(replaces = "parentFrameDirect")
         protected REnvironment parentFrame(VirtualFrame frame, int n) {
             if (n <= 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.INVALID_VALUE, "n");
+                throw error(RError.Message.INVALID_VALUE, "n");
             }
             RCaller call = RArguments.getCall(frame);
             while (call.isPromise()) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index cae0c2dcee..9ccf4cdf32 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -79,7 +79,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  */
 public class GetFunctions {
     public abstract static class Adapter extends RBuiltinNode {
-        private final BranchProfile unknownObjectErrorProfile = BranchProfile.create();
         protected final ValueProfile modeProfile = ValueProfile.createIdentityProfile();
         protected final BranchProfile recursiveProfile = BranchProfile.create();
         @Child private PromiseHelperNode promiseHelper = new PromiseHelperNode();
@@ -88,11 +87,11 @@ public class GetFunctions {
         @CompilationFinal private boolean firstExecution = true;
 
         protected void unknownObject(String x, RType modeType, String modeString) throws RError {
-            unknownObjectErrorProfile.enter();
+            CompilerDirectives.transferToInterpreter();
             if (modeType == RType.Any) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, x);
+                throw error(RError.Message.UNKNOWN_OBJECT, x);
             } else {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT_MODE, x, modeType == null ? modeString : modeType.getName());
+                throw error(RError.Message.UNKNOWN_OBJECT_MODE, x, modeType == null ? modeString : modeType.getName());
             }
         }
 
@@ -299,11 +298,11 @@ public class GetFunctions {
             State state = new State(xv, mode, ifNotFound);
             if (!(state.modeLength == 1 || state.modeLength == state.svLength)) {
                 wrongLengthErrorProfile.enter();
-                throw RError.error(this, RError.Message.WRONG_LENGTH_ARG, "mode");
+                throw error(RError.Message.WRONG_LENGTH_ARG, "mode");
             }
             if (!(state.ifNotFoundLength == 1 || state.ifNotFoundLength == state.svLength)) {
                 wrongLengthErrorProfile.enter();
-                throw RError.error(this, RError.Message.WRONG_LENGTH_ARG, "ifnotfound");
+                throw error(RError.Message.WRONG_LENGTH_ARG, "ifnotfound");
             }
             return state;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
index b9905ce517..4262e5e87a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -39,7 +38,7 @@ public abstract class GetText extends RBuiltinNode {
     static {
         Casts casts = new Casts(GetText.class);
         casts.arg("domain").asStringVector().findFirst("");
-        casts.arg("args").mustNotBeMissing(SHOW_CALLER, Message.ARGUMENT_EMPTY, 2).asStringVector();
+        casts.arg("args").mustNotBeMissing(Message.ARGUMENT_EMPTY, 2).asStringVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 0ce9433368..184c3dbf50 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -68,12 +68,12 @@ public class GrepFunctions {
 
         protected static void castPattern(Casts casts) {
             // with default error message, NO_CALLER does not work
-            casts.arg("pattern").mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT,
+            casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT,
                             "pattern");
         }
 
         protected static void castText(Casts casts, String textId) {
-            casts.arg(textId).mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, textId);
+            casts.arg(textId).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, textId);
         }
 
         protected static void castIgnoreCase(Casts casts) {
@@ -140,7 +140,7 @@ public class GrepFunctions {
 
         protected String checkLength(RAbstractStringVector arg, String name) {
             if (arg.getLength() < 1) {
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, name);
+                throw error(RError.Message.INVALID_ARGUMENT, name);
             } else if (arg.getLength() > 1) {
                 RError.warning(this, RError.Message.ARGUMENT_ONLY_FIRST, name);
             }
@@ -206,7 +206,7 @@ public class GrepFunctions {
             PCRERFFI.Result pcre = compileNode.execute(pattern, cflags, tables);
             if (pcre.result == 0) {
                 // TODO output warning if pcre.errorMessage not NULL
-                throw RError.error(this, RError.Message.INVALID_REGEXP, pattern);
+                throw error(RError.Message.INVALID_REGEXP, pattern);
             }
             return pcre;
         }
@@ -370,8 +370,7 @@ public class GrepFunctions {
 
         protected static void castReplacement(Casts casts) {
             // with default error message, NO_CALLER does not work
-            casts.arg("replacement").mustBe(stringValue(), RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.NO_CALLER,
-                            RError.Message.INVALID_ARGUMENT, "replacement");
+            casts.arg("replacement").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, "replacement");
         }
 
         protected RStringVector doSub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte perlLogical,
@@ -1175,8 +1174,8 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(Strsplit.class);
-            casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER);
-            casts.arg("split").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER);
+            casts.arg("x").mustBe(stringValue(), RError.Message.NON_CHARACTER);
+            casts.arg("split").mustBe(stringValue(), RError.Message.NON_CHARACTER);
             castFixed(casts, RRuntime.LOGICAL_FALSE);
             castPerl(casts);
             castUseBytes(casts);
@@ -1205,7 +1204,7 @@ public class GrepFunctions {
                         pcreSplits[i] = compileNode.execute(currentSplit, 0, pcreTables);
                         if (pcreSplits[i].result == 0) {
                             // TODO output warning if pcre.errorMessage not NULL
-                            throw RError.error(this, RError.Message.INVALID_REGEXP, currentSplit);
+                            throw error(RError.Message.INVALID_REGEXP, currentSplit);
                         }
                         // TODO pcre_study for vectors > 10 ? (cf GnuR)
                     }
@@ -1252,9 +1251,9 @@ public class GrepFunctions {
         @Fallback
         protected RList split(Object x, Object splitArg, Object fixedLogical, Object perlLogical, Object useBytes) {
             if (!(x instanceof RAbstractStringVector)) {
-                throw RError.error(this, RError.Message.NON_CHARACTER);
+                throw error(RError.Message.NON_CHARACTER);
             } else {
-                throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+                throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index 6d4a9370e3..0044450c3a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -127,7 +127,7 @@ public class HiddenInternalFunctions {
                      * not an error, but is used as an override mechanism.
                      */
                     if (!RContext.getInstance().getLoadingBase()) {
-                        throw RError.error(this, ex);
+                        throw error(ex);
                     }
                 }
             }
@@ -157,7 +157,7 @@ public class HiddenInternalFunctions {
         protected RNull importIntoEnv(REnvironment impEnv, RAbstractStringVector impNames, REnvironment expEnv, RAbstractStringVector expNames) {
             int length = impNames.getLength();
             if (length != expNames.getLength()) {
-                throw RError.error(this, Message.IMP_EXP_NAMES_MATCH);
+                throw error(Message.IMP_EXP_NAMES_MATCH);
             }
             for (int i = 0; i < length; i++) {
                 String impsym = impNames.getDataAt(i);
@@ -173,7 +173,7 @@ public class HiddenInternalFunctions {
                 try {
                     impEnv.put(impsym, binding);
                 } catch (PutException ex) {
-                    throw RError.error(RError.SHOW_CALLER, ex);
+                    throw error(ex);
                 }
             }
             return RNull.instance;
@@ -247,7 +247,7 @@ public class HiddenInternalFunctions {
                 }
             }
             if (!rc) {
-                throw RError.error(this, RError.Message.LAZY_LOAD_DB_CORRUPT, dbPath);
+                throw error(RError.Message.LAZY_LOAD_DB_CORRUPT, dbPath);
             }
             try {
                 RSerialize.CallHook callHook = new RSerialize.CallHook() {
@@ -284,7 +284,7 @@ public class HiddenInternalFunctions {
 
         @Specialization
         protected RList getRegisteredRoutines(@SuppressWarnings("unused") RNull info) {
-            throw RError.error(this, RError.Message.NULL_DLLINFO);
+            throw error(RError.Message.NULL_DLLINFO);
         }
 
         @Specialization(guards = "isDLLInfo(externalPtr)")
@@ -315,7 +315,7 @@ public class HiddenInternalFunctions {
 
         @Fallback
         protected RList getRegisteredRoutines(@SuppressWarnings("unused") Object info) {
-            throw RError.error(this, RError.Message.REQUIRES_DLLINFO);
+            throw error(RError.Message.REQUIRES_DLLINFO);
         }
 
         protected static boolean isDLLInfo(RExternalPtr externalPtr) {
@@ -339,7 +339,7 @@ public class HiddenInternalFunctions {
                 String var = varsVec.getDataAt(i);
                 Object value = env.get(var);
                 if (value == null) {
-                    throw RError.error(this, RError.Message.UNKNOWN_OBJECT, var);
+                    throw error(RError.Message.UNKNOWN_OBJECT, var);
                 }
                 if (force && value instanceof RPromise) {
                     if (promiseHelper == null) {
@@ -356,7 +356,7 @@ public class HiddenInternalFunctions {
         @SuppressWarnings("unused")
         @Fallback
         protected RList getVarsFromFrame(Object varsVec, Object env, Object forceArg) {
-            throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
         }
     }
 
@@ -379,7 +379,7 @@ public class HiddenInternalFunctions {
         @TruffleBoundary
         private RIntVector lazyLoadDBinsertValueInternal(MaterializedFrame frame, Object value, RAbstractStringVector file, int type, int compression, RFunction hook) {
             if (!(compression == 1 || compression == 3)) {
-                throw RError.error(this, Message.GENERIC, "unsupported compression");
+                throw error(Message.GENERIC, "unsupported compression");
             }
 
             RSerialize.CallHook callHook = new RSerialize.CallHook() {
@@ -403,7 +403,7 @@ public class HiddenInternalFunctions {
                     cdata = new byte[outLen];
                     boolean rc = RCompression.compress(ctype, data, cdata);
                     if (!rc) {
-                        throw RError.error(this, Message.GENERIC, "zlib compress error");
+                        throw error(Message.GENERIC, "zlib compress error");
                     }
                 } else if (compression == 3) {
                     ctype = RCompression.Type.XZ;
@@ -412,7 +412,7 @@ public class HiddenInternalFunctions {
                     cdata = new byte[outLen];
                     boolean rc = RCompression.compress(ctype, data, cdata);
                     if (!rc) {
-                        throw RError.error(this, Message.GENERIC, "lzma compress error");
+                        throw error(Message.GENERIC, "lzma compress error");
                     }
                 } else {
                     throw RInternalError.shouldNotReachHere();
@@ -431,7 +431,7 @@ public class HiddenInternalFunctions {
         @SuppressWarnings("unused")
         @Fallback
         protected Object lazyLoadDBinsertValue(Object value, Object file, Object ascii, Object compsxp, Object hook) {
-            throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
         }
 
         /**
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
index 62b894730e..c03a1d9ba8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
@@ -41,11 +41,11 @@ public abstract class IConv extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(IConv.class);
-        casts.arg("x").mustBe(stringValue(), RError.NO_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "x");
+        casts.arg("x").mustBe(stringValue(), RError.Message.NOT_CHARACTER_VECTOR, "x");
         // with default error message, NO_CALLER does not work
-        casts.arg("from").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "from").mustBe(stringValue()).asStringVector().mustBe(size(1));
-        casts.arg("to").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "to").mustBe(stringValue()).asStringVector().mustBe(size(1));
-        casts.arg("sub").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "sub").mustBe(stringValue()).asStringVector().mustBe(size(1));
+        casts.arg("from").defaultError(RError.Message.INVALID_ARGUMENT, "from").mustBe(stringValue()).asStringVector().mustBe(size(1));
+        casts.arg("to").defaultError(RError.Message.INVALID_ARGUMENT, "to").mustBe(stringValue()).asStringVector().mustBe(size(1));
+        casts.arg("sub").defaultError(RError.Message.INVALID_ARGUMENT, "sub").mustBe(stringValue()).asStringVector().mustBe(size(1));
         casts.arg("mark").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         casts.arg("toRaw").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
index 51a84c924e..0b617546ed 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -71,7 +70,7 @@ public abstract class IntToUtf8 extends RBuiltinNode {
                 try {
                     result[j] = new String(new int[]{temp}, 0, 1);
                 } catch (IllegalArgumentException e) {
-                    throw RError.error(RError.SHOW_CALLER, Message.GENERIC, "illegal unicode code point");
+                    throw error(Message.GENERIC, "illegal unicode code point");
                 }
             }
         }
@@ -97,7 +96,7 @@ public abstract class IntToUtf8 extends RBuiltinNode {
         try {
             return new String(result, 0, pos);
         } catch (IllegalArgumentException e) {
-            throw RError.error(RError.SHOW_CALLER, Message.GENERIC, "illegal unicode code point");
+            throw error(Message.GENERIC, "illegal unicode code point");
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
index f98ece1fa5..98b5684683 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
@@ -86,7 +86,7 @@ public class IsFiniteFunctions {
         @Fallback
         @TruffleBoundary
         protected Object doIsFiniteOther(Object x) {
-            throw RError.error(this, RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, TypeofNode.getTypeof(x).getName());
+            throw error(RError.Message.DEFAULT_METHOD_NOT_IMPLEMENTED_FOR_TYPE, TypeofNode.getTypeof(x).getName());
         }
 
         protected RLogicalVector doFunConstant(RAbstractVector x, byte value) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
index b9d87fff25..cffe0507af 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
@@ -40,7 +40,7 @@ public abstract class IsSingle extends RBuiltinNode {
 
     @Specialization
     protected Object isSingle(@SuppressWarnings("unused") Object x) {
-        throw RError.error(this, RError.Message.UNIMPLEMENTED_TYPE_IN_R, "single");
+        throw error(RError.Message.UNIMPLEMENTED_TYPE_IN_R, "single");
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
index 4c096d94e5..2c7aa8fd52 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
@@ -62,7 +62,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Handles all builtin functions of the form {@code is.xxx}, where is {@code xxx} is a "type".
@@ -73,7 +72,7 @@ public class IsTypeFunctions {
 
         protected static Casts createCasts(Class<? extends MissingAdapter> extCls) {
             Casts casts = new Casts(extCls);
-            casts.arg("x").mustNotBeMissing((RBaseNode) null, RError.Message.ARGUMENT_MISSING, "x");
+            casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENT_MISSING, "x");
             return casts;
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
index cb571f301f..c426cb80a7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
@@ -56,7 +56,7 @@ public abstract class IsUnsorted extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(IsUnsorted.class);
-        casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).notNA().map(toBoolean());
+        casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).mustNotBeNA().map(toBoolean());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 404b8719e7..27d3bd635c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -87,7 +87,7 @@ public class LaFunctions {
         protected static Casts createCasts(Class<? extends RsgRBuiltinNode> extClass) {
             Casts casts = new Casts(extClass);
             casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_NUMERIC, "x");
-            casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
             return casts;
         }
     }
@@ -124,16 +124,14 @@ public class LaFunctions {
             // ask for optimal size of work array
             int info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1);
             if (info != 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev");
+                throw error(RError.Message.LAPACK_ERROR, info, "dgeev");
             }
             // now allocate work array and make the actual call
             int lwork = (int) work[0];
             work = new double[lwork];
             info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork);
             if (info != 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeev");
+                throw error(RError.Message.LAPACK_ERROR, info, "dgeev");
             }
             // result is a list containing "values" and "vectors" (unless only.values is TRUE)
             boolean complexValues = false;
@@ -231,8 +229,7 @@ public class LaFunctions {
             int[] iwork = new int[1];
             int info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
             if (info != 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr");
+                throw error(RError.Message.LAPACK_ERROR, info, "dysevr");
             }
             lwork = (int) work[0];
             liwork = iwork[0];
@@ -240,8 +237,7 @@ public class LaFunctions {
             iwork = new int[liwork];
             info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
             if (info != 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dysevr");
+                throw error(RError.Message.LAPACK_ERROR, info, "dysevr");
             }
             Object[] data = new Object[onlyValues ? 1 : 2];
             RStringVector names;
@@ -262,8 +258,6 @@ public class LaFunctions {
 
         @CompilationFinal private static final String[] NAMES = new String[]{"qr", "rank", "qraux", "pivot"};
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         static {
             Casts casts = new Casts(Qr.class);
             casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a");
@@ -286,15 +280,13 @@ public class LaFunctions {
             // ask for optimal size of work array
             int info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, -1);
             if (info < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3");
+                throw error(RError.Message.LAPACK_ERROR, info, "dgeqp3");
             }
             int lwork = (int) work[0];
             work = new double[lwork];
             info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, lwork);
             if (info < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgeqp3");
+                throw error(RError.Message.LAPACK_ERROR, info, "dgeqp3");
             }
             Object[] data = new Object[4];
             // TODO check complete
@@ -312,8 +304,6 @@ public class LaFunctions {
     @RBuiltin(name = "qr_coef_real", kind = INTERNAL, parameterNames = {"q", "b"}, behavior = PURE)
     public abstract static class QrCoefReal extends RBuiltinNode {
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         private static final char SIDE = 'L';
         private static final char TRANS = 'T';
 
@@ -341,8 +331,7 @@ public class LaFunctions {
             int[] qrDims = getQDimsNode.getDimensions(qr);
             int n = qrDims[0];
             if (bDims[0] != n) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]);
+                throw error(RError.Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]);
             }
             int nrhs = bDims[1];
             double[] work = new double[1];
@@ -354,20 +343,17 @@ public class LaFunctions {
             // ask for optimal size of work array
             int info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1);
             if (info < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr");
+                throw error(RError.Message.LAPACK_ERROR, info, "dormqr");
             }
             int lwork = (int) work[0];
             work = new double[lwork];
             info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork);
             if (info < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dormqr");
+                throw error(RError.Message.LAPACK_ERROR, info, "dormqr");
             }
             info = dtrtrsNode.execute('U', 'N', 'N', k, nrhs, qrData, n, bData, n);
             if (info < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dtrtrs");
+                throw error(RError.Message.LAPACK_ERROR, info, "dtrtrs");
             }
             // TODO check complete
             return b;
@@ -380,7 +366,6 @@ public class LaFunctions {
         private static final RStringVector NAMES_VECTOR = RDataFactory.createStringVector(new String[]{"modulus", "sign"}, RDataFactory.COMPLETE_VECTOR);
         private static final RStringVector DET_CLASS = RDataFactory.createStringVector(new String[]{"det"}, RDataFactory.COMPLETE_VECTOR);
 
-        private final BranchProfile errorProfile = BranchProfile.create();
         private final ConditionProfile infoGreaterZero = ConditionProfile.createBinaryProfile();
         private final ConditionProfile doUseLog = ConditionProfile.createBinaryProfile();
         private final NACheck naCheck = NACheck.create();
@@ -391,7 +376,7 @@ public class LaFunctions {
             Casts casts = new Casts(DetGeReal.class);
             casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a");
 
-            casts.arg("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -407,8 +392,7 @@ public class LaFunctions {
             int info = dgetrfNode.execute(n, n, aData, n, ipiv);
             int sign = 1;
             if (info < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dgetrf");
+                throw error(RError.Message.LAPACK_ERROR, info, "dgetrf");
             } else if (infoGreaterZero.profile(info > 0)) {
                 modulus = useLog ? Double.NEGATIVE_INFINITY : 0;
             } else {
@@ -471,7 +455,7 @@ public class LaFunctions {
             casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a").mustBe(
                             dimGt(1, 0), RError.Message.DIMS_GT_ZERO, "a");
 
-            casts.arg("pivot").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("pivot").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
             casts.arg("tol").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
         }
@@ -500,7 +484,7 @@ public class LaFunctions {
                 if (info != 0) {
                     errorProfile.enter();
                     // TODO informative error message (aka GnuR)
-                    throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dpotrf");
+                    throw error(RError.Message.LAPACK_ERROR, info, "dpotrf");
                 }
             } else {
                 int[] ipiv = new int[m];
@@ -510,7 +494,7 @@ public class LaFunctions {
                 if (info != 0) {
                     errorProfile.enter();
                     // TODO informative error message (aka GnuR)
-                    throw RError.error(this, RError.Message.LAPACK_ERROR, info, "dpotrf");
+                    throw error(RError.Message.LAPACK_ERROR, info, "dpotrf");
                 }
                 setPivotAttrNode.execute(a, RRuntime.asLogical(piv));
                 setRankAttrNode.execute(a, rank[0]);
@@ -538,10 +522,10 @@ public class LaFunctions {
 
         static {
             Casts casts = new Casts(LaSolve.class);
-            casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), RError.ROOTNODE, RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), RError.ROOTNODE,
-                            RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.ROOTNODE, RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
+            casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)),
+                            RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
 
-            casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), RError.ROOTNODE, RError.Message.GENERIC, "no right-hand side in 'b'");
+            casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), RError.Message.GENERIC, "no right-hand side in 'b'");
 
             casts.arg("tolin").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
         }
@@ -561,11 +545,11 @@ public class LaFunctions {
             int[] aDims = getADimsNode.getDimensions(a);
             int n = aDims[0];
             if (n == 0) {
-                throw RError.error(this, RError.Message.GENERIC, "'a' is 0-diml");
+                throw error(RError.Message.GENERIC, "'a' is 0-diml");
             }
             int n2 = aDims[1];
             if (n2 != n) {
-                throw RError.error(this, RError.Message.MUST_BE_SQUARE, "a", n, n2);
+                throw error(RError.Message.MUST_BE_SQUARE, "a", n, n2);
             }
             RList aDn = getADimNamesNode.getDimNames(a);
             int p;
@@ -575,11 +559,11 @@ public class LaFunctions {
                 int[] bDims = getBinDimsNode.getDimensions(bin);
                 p = bDims[1];
                 if (p == 0) {
-                    throw RError.error(this, RError.Message.GENERIC, "no right-hand side in 'b'");
+                    throw error(RError.Message.GENERIC, "no right-hand side in 'b'");
                 }
                 int p2 = bDims[0];
                 if (p2 != n) {
-                    throw RError.error(this, RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", p2, p, "a", n, n);
+                    throw error(RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", p2, p, "a", n, n);
                 }
                 bData = new double[n * p];
                 b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR);
@@ -602,7 +586,7 @@ public class LaFunctions {
             } else {
                 p = 1;
                 if (bin.getLength() != n) {
-                    throw RError.error(this, RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", bin.getLength(), p, "a", n, n);
+                    throw error(RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", bin.getLength(), p, "a", n, n);
                 }
                 bData = new double[n];
                 b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR);
@@ -625,10 +609,10 @@ public class LaFunctions {
             }
             int info = dgesvNode.execute(n, p, avals, n, ipiv, bData, n);
             if (info < 0) {
-                throw RError.error(this, RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv");
+                throw error(RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv");
             }
             if (info > 0) {
-                throw RError.error(this, RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
+                throw error(RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
             }
             if (tol > 0) {
                 double anorm = dlangeNode.execute('1', n, n, avals, n, null);
@@ -636,7 +620,7 @@ public class LaFunctions {
                 double[] rcond = new double[1];
                 dgeconNode.execute('1', n, avals, n, anorm, rcond, work, ipiv);
                 if (rcond[0] < tol) {
-                    throw RError.error(this, RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]);
+                    throw error(RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]);
                 }
             }
             return b;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index a3bb7941e9..7f2f3de45e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -75,7 +75,7 @@ public abstract class Lapply extends RBuiltinNode {
         // asVector() to whatever GNU R is doing there; still this can be a problem only if the
         // internal is called directly (otherwise, it's guaranteed that it's a vector)
         casts.arg("X").asVector();
-        casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.NO_CALLER, RError.Message.APPLY_NON_FUNCTION);
+        casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.APPLY_NON_FUNCTION);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
index 3b1cff197b..a9eb95fc48 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -53,8 +52,8 @@ public abstract class Lengths extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Lengths.class);
-        casts.arg("x").defaultError(RError.SHOW_CALLER, X_LIST_ATOMIC).allowNull().mustBe(abstractVectorValue());
-        casts.arg("use.names").mustBe(numericValue(), RError.SHOW_CALLER, INVALID_VALUE, "use.names").asLogicalVector().findFirst().map(toBoolean());
+        casts.arg("x").defaultError(X_LIST_ATOMIC).allowNull().mustBe(abstractVectorValue());
+        casts.arg("use.names").mustBe(numericValue(), INVALID_VALUE, "use.names").asLogicalVector().findFirst().map(toBoolean());
     }
 
     private void initLengthNode() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
index dc2757951a..2e9f08ddef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
@@ -46,7 +46,7 @@ public abstract class License extends RBuiltinNode {
         try {
             StdConnections.getStdout().writeString(RRuntime.LICENSE, true);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
index 462f900017..bec48dd87d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
@@ -78,7 +78,7 @@ public class LoadSaveFunctions {
                         return RDataFactory.createEmptyStringVector();
                     }
                     if (!(o instanceof RPairList)) {
-                        throw RError.error(this, RError.Message.GENERIC, "loaded data is not in pair list form");
+                        throw error(RError.Message.GENERIC, "loaded data is not in pair list form");
                     }
                     RPairList vars = (RPairList) o;
 
@@ -102,12 +102,12 @@ public class LoadSaveFunctions {
                     return RDataFactory.createStringVector(data, naCheck.neverSeenNA());
 
                 } else {
-                    throw RError.error(this, RError.Message.GENERIC, "the input does not start with a magic number compatible with loading from a connection");
+                    throw error(RError.Message.GENERIC, "the input does not start with a magic number compatible with loading from a connection");
                 }
             } catch (IOException iox) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, iox.getMessage());
+                throw error(RError.Message.ERROR_READING_CONNECTION, iox.getMessage());
             } catch (PutException px) {
-                throw RError.error(RError.SHOW_CALLER, px);
+                throw error(px);
             }
         }
     }
@@ -140,16 +140,16 @@ public class LoadSaveFunctions {
                 int magic = readMagic(bs);
                 switch (magic) {
                     case R_MAGIC_EMPTY:
-                        throw RError.error(this, RError.Message.MAGIC_EMPTY);
+                        throw error(RError.Message.MAGIC_EMPTY);
                     case R_MAGIC_TOONEW:
-                        throw RError.error(this, RError.Message.MAGIC_TOONEW);
+                        throw error(RError.Message.MAGIC_TOONEW);
                     case R_MAGIC_CORRUPT:
-                        throw RError.error(this, RError.Message.MAGIC_CORRUPT);
+                        throw error(RError.Message.MAGIC_CORRUPT);
                     default:
 
                 }
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.FILE_OPEN_ERROR);
+                throw error(RError.Message.FILE_OPEN_ERROR);
             }
             throw RError.nyi(this, "load");
         }
@@ -200,7 +200,7 @@ public class LoadSaveFunctions {
             casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL);
             casts.arg("version").allowNull().mustBe(integerValue());
             casts.arg("environment").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
-            casts.arg("eval.promises").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("eval.promises").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -212,7 +212,7 @@ public class LoadSaveFunctions {
                 String varName = list.getDataAt(i);
                 Object value = envir.get(varName);
                 if (value == null) {
-                    throw RError.error(this, RError.Message.UNKNOWN_OBJECT, varName);
+                    throw error(RError.Message.UNKNOWN_OBJECT, varName);
                 }
                 if (evalPromises) {
                     value = promiseHelper.checkEvaluate(frame, value);
@@ -235,22 +235,22 @@ public class LoadSaveFunctions {
         private void doSaveConn(Object toSave, RConnection conn, boolean ascii) {
             try (RConnection openConn = conn.forceOpen(ascii ? "wt" : "wb")) {
                 if (!openConn.canWrite()) {
-                    throw RError.error(this, RError.Message.CONNECTION_NOT_OPEN_WRITE);
+                    throw error(RError.Message.CONNECTION_NOT_OPEN_WRITE);
                 }
                 if (!ascii && openConn.isTextMode()) {
-                    throw RError.error(this, RError.Message.CONN_XDR);
+                    throw error(RError.Message.CONN_XDR);
                 }
                 openConn.writeChar(ascii ? ASCII_HEADER : XDR_HEADER, 0, "", false);
                 RSerialize.serialize(openConn, toSave, ascii ? RSerialize.ASCII : RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+                throw error(RError.Message.GENERIC, ex.getMessage());
             }
         }
 
         @SuppressWarnings("unused")
         @Fallback
         protected Object saveToConn(Object list, Object con, Object ascii, Object version, Object envir, Object evaPromises) {
-            throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
index 29231259c8..4f043390f4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.ARGUMENT_NOT_CHAR_VECTOR;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_VALUE;
@@ -184,7 +183,7 @@ public class LocaleFunctions {
         }
 
         private static void category(Casts casts) {
-            casts.arg("category").mustBe(numericValue(), NO_CALLER, INVALID_ARGUMENT, "category").asIntegerVector().findFirst();
+            casts.arg("category").mustBe(numericValue(), INVALID_ARGUMENT, "category").asIntegerVector().findFirst();
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
index 0e05ca0385..f2323827fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -40,7 +39,7 @@ public abstract class Ls extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Ls.class);
-        casts.arg("envir").mustBe(REnvironment.class, NO_CALLER, INVALID_ARGUMENT, "envir");
+        casts.arg("envir").mustBe(REnvironment.class, INVALID_ARGUMENT, "envir");
         casts.arg("all.names").asLogicalVector().findFirst().map(toBoolean());
         casts.arg("sorted").asLogicalVector().findFirst().map(toBoolean());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
index d1ac331fb5..1272133457 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
@@ -47,8 +47,8 @@ public abstract class MakeNames extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(MakeNames.class);
-        casts.arg("names").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER_NAMES);
-        casts.arg("allow_").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "allow_").asLogicalVector().findFirst().mustBe(notLogicalNA());
+        casts.arg("names").mustBe(stringValue(), RError.Message.NON_CHARACTER_NAMES);
+        casts.arg("allow_").defaultError(RError.Message.INVALID_VALUE, "allow_").asLogicalVector().findFirst().mustBe(notLogicalNA());
     }
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
index 9a0d72178e..6fd3a0feca 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
@@ -46,8 +46,8 @@ public abstract class MakeUnique extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(MakeUnique.class);
-        casts.arg("names").defaultError(RError.SHOW_CALLER, RError.Message.NOT_CHARACTER_VECTOR, "names").mustBe(stringValue());
-        casts.arg("sep").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "sep").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
+        casts.arg("names").defaultError(RError.Message.NOT_CHARACTER_VECTOR, "names").mustBe(stringValue());
+        casts.arg("sep").defaultError(RError.Message.MUST_BE_STRING, "sep").mustBe(stringValue()).asStringVector().mustBe(size(1)).findFirst();
 
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index f5fa51dfa9..a531e18b3e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -70,7 +70,6 @@ public abstract class MatMult extends RBuiltinNode {
     @Child private BinaryMapArithmeticFunctionNode add = new BinaryMapArithmeticFunctionNode(BinaryArithmetic.ADD.createOperation());
     private final boolean promoteDimNames;
 
-    private final BranchProfile errorProfile = BranchProfile.create();
     private final LoopConditionProfile mainLoopProfile = LoopConditionProfile.createCountingProfile();
     private final LoopConditionProfile remainingLoopProfile = LoopConditionProfile.createCountingProfile();
 
@@ -175,8 +174,7 @@ public abstract class MatMult extends RBuiltinNode {
     public RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols, int aRowStride, int aColStride, int bRowStride,
                     int bColStride, boolean mirrored) {
         if (aCols != bRows) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+            throw error(RError.Message.NON_CONFORMABLE_ARGS);
         }
         double[] dataA = a.materialize().getDataWithoutCopying();
         double[] dataB = b.materialize().getDataWithoutCopying();
@@ -333,8 +331,7 @@ public abstract class MatMult extends RBuiltinNode {
                 return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols);
             } else {
                 if (a.getLength() != b.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 double result = 0.0;
                 na.enable(a);
@@ -378,8 +375,7 @@ public abstract class MatMult extends RBuiltinNode {
                 final int aCols = aDimensions[1];
                 final int bRows = bDimensions[0];
                 if (aCols != bRows) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 final int aRows = aDimensions[0];
                 final int bCols = bDimensions[1];
@@ -403,8 +399,7 @@ public abstract class MatMult extends RBuiltinNode {
                 final int aCols = aDimensions[1];
                 final int aRows = aDimensions[0];
                 if (aCols != 1 && aCols != b.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 na.enable(a);
                 na.enable(b);
@@ -438,8 +433,7 @@ public abstract class MatMult extends RBuiltinNode {
                 final int bRows = bDimensions[0];
                 final int bCols = bDimensions[1];
                 if (bRows != 1 && bRows != a.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 na.enable(a);
                 na.enable(b);
@@ -469,8 +463,7 @@ public abstract class MatMult extends RBuiltinNode {
                 }
             } else {
                 if (a.getLength() != b.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 RComplex result = RDataFactory.createComplexZero();
                 na.enable(a);
@@ -510,8 +503,7 @@ public abstract class MatMult extends RBuiltinNode {
                 int aCols = aDimensions[1];
                 int bRows = bDimensions[0];
                 if (aCols != bRows) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 int aRows = aDimensions[0];
                 int bCols = bDimensions[1];
@@ -533,8 +525,7 @@ public abstract class MatMult extends RBuiltinNode {
                 final int aCols = aDimensions[1];
                 final int aRows = aDimensions[0];
                 if (aCols != 1 && aCols != b.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 na.enable(a);
                 na.enable(b);
@@ -566,8 +557,7 @@ public abstract class MatMult extends RBuiltinNode {
                 final int bCols = bDimensions[1];
                 final int bRows = bDimensions[0];
                 if (bRows != 1 && bRows != a.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 na.enable(a);
                 na.enable(b);
@@ -595,8 +585,7 @@ public abstract class MatMult extends RBuiltinNode {
                 }
             } else {
                 if (a.getLength() != b.getLength()) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.NON_CONFORMABLE_ARGS);
+                    throw error(RError.Message.NON_CONFORMABLE_ARGS);
                 }
                 int result = 0;
                 na.enable(result);
@@ -677,7 +666,7 @@ public abstract class MatMult extends RBuiltinNode {
     @Fallback
     @TruffleBoundary
     protected RDoubleVector doRaw(@SuppressWarnings("unused") Object a, @SuppressWarnings("unused") Object b) {
-        throw RError.error(this, RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
+        throw error(RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
     }
 
     // guards
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index 77bdce22b0..11e4b0d23b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -43,7 +43,6 @@ import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.helpers.RFactorNodes;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -156,7 +155,7 @@ public abstract class Match extends RBuiltinNode {
     @Fallback
     @SuppressWarnings("unused")
     protected RIntVector match(Object x, Object table, Object nomatch, Object incomparables) {
-        throw RError.error(this, MATCH_VECTOR_ARGS);
+        throw error(MATCH_VECTOR_ARGS);
     }
 
     protected abstract static class MatchInternalNode extends Node {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
index 9247558952..dd8a4b0e48 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE;
 
@@ -39,7 +41,6 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RRootNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.MatchArgNodeGen.MatchArgInternalNodeGen;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
@@ -80,20 +81,14 @@ public abstract class MatchArg extends RBuiltinNode {
         @Child private PMatch pmatch = PMatchNodeGen.create();
         @Child private Identical identical = IdenticalNodeGen.create();
 
-        @Children private final CastNode[] casts;
-
-        {
-            CastBuilder builder = new CastBuilder();
-            builder.arg(0).asStringVector();
-            builder.arg(1).allowMissing().mustBe(stringValue()).asStringVector();
-            builder.arg(2).mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean());
-            this.casts = builder.getCasts();
-        }
+        @Child private CastNode argCast = newCastBuilder(NO_CALLER).asStringVector().buildCastNode();
+        @Child private CastNode choicesCast = newCastBuilder(NO_CALLER).allowMissing().mustBe(stringValue()).asStringVector().buildCastNode();
+        @Child private CastNode severalOKCast = newCastBuilder(NO_CALLER).mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()).buildCastNode();
 
         public abstract Object execute(Object arg, Object choices, Object severalOK);
 
         public final Object castAndExecute(Object arg, Object choices, Object severalOK) {
-            return execute(casts[0].execute(arg), casts[1].execute(choices), casts[2].execute(severalOK));
+            return execute(argCast.execute(arg), choicesCast.execute(choices), severalOKCast.execute(severalOK));
         }
 
         @Specialization
@@ -233,6 +228,6 @@ public abstract class MatchArg extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Fallback
     protected Object matchArgFallback(Object arg, Object choices, Object severalOK) {
-        throw RError.error(this, Message.GENERIC, "too many different names in match.arg");
+        throw error(Message.GENERIC, "too many different names in match.arg");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
index 69cb73a3f1..552a480a2c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
@@ -118,7 +118,7 @@ public abstract class MatchFun extends RBuiltinNode {
                 return (RFunction) result;
             } else {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(outer, RError.Message.NON_FUNCTION, RDeparse.deparse(result));
+                throw outer.error(RError.Message.NON_FUNCTION, RDeparse.deparse(result));
             }
         }
 
@@ -149,10 +149,10 @@ public abstract class MatchFun extends RBuiltinNode {
         }
 
         @TruffleBoundary
-        private static Object slowPathLookup(String name, MaterializedFrame frame, boolean descend) {
+        private Object slowPathLookup(String name, MaterializedFrame frame, boolean descend) {
             Object result = descend ? ReadVariableNode.lookupFunction(name, frame) : ReadVariableNode.lookupAny(name, frame, false);
             if (result == null) {
-                throw RError.error(RError.SHOW_CALLER, descend ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, name);
+                throw outer.error(descend ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, name);
             }
             return result;
         }
@@ -179,7 +179,7 @@ public abstract class MatchFun extends RBuiltinNode {
                 return checkResult(slowPathLookup(lookupName, getCallerFrame.execute(frame), descend));
             } else {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(outer, RError.Message.NOT_FUNCTION, RDeparse.deparseSyntaxElement(rep));
+                throw outer.error(RError.Message.NOT_FUNCTION, RDeparse.deparseSyntaxElement(rep));
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
index 90f7823259..feb1059c09 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
@@ -130,7 +130,7 @@ public abstract class Matrix extends RBuiltinNode {
             return new int[]{size, 1};
         } else if (nrowGivenNcolMissing.profile(!missingNr && missingNc)) {
             if (nrow == 0 && size > 0) {
-                throw RError.error(this, RError.Message.NROW_ZERO);
+                throw error(RError.Message.NROW_ZERO);
             }
             if (empty.profile(size == 0)) {
                 return new int[]{nrow, 0};
@@ -139,7 +139,7 @@ public abstract class Matrix extends RBuiltinNode {
             }
         } else if (nrowMissingNcolGiven.profile(missingNr && !missingNc)) {
             if (ncol == 0 && size > 0) {
-                throw RError.error(this, RError.Message.NCOL_ZERO);
+                throw error(RError.Message.NCOL_ZERO);
             }
             if (empty.profile(size == 0)) {
                 return new int[]{0, ncol};
@@ -157,7 +157,7 @@ public abstract class Matrix extends RBuiltinNode {
             return new int[]{1, size};
         } else if (nrowGivenNcolMissing.profile(!missingNr && missingNc)) {
             if (nrow == 0 && size > 0) {
-                throw RError.error(this, RError.Message.NROW_ZERO);
+                throw error(RError.Message.NROW_ZERO);
             }
             if (empty.profile(size == 0)) {
                 return new int[]{0, nrow};
@@ -167,7 +167,7 @@ public abstract class Matrix extends RBuiltinNode {
             }
         } else if (nrowMissingNcolGiven.profile(missingNr && !missingNc)) {
             if (ncol == 0 && size > 0) {
-                throw RError.error(this, RError.Message.NCOL_ZERO);
+                throw error(RError.Message.NCOL_ZERO);
             }
             if (empty.profile(size == 0)) {
                 return new int[]{ncol, 0};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
index 45dd58eeec..018f96b894 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
@@ -50,7 +50,7 @@ public abstract class Merge extends RBuiltinNode {
     }
 
     private static void addLogicalCast(Casts casts, String name) {
-        casts.arg(name).defaultError(INVALID_LOGICAL, "all.x").mustBe(numericValue()).asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg(name).defaultError(INVALID_LOGICAL, "all.x").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     private static void isortWithIndex(int[] x, int[] indx, int n) {
@@ -142,7 +142,7 @@ public abstract class Merge extends RBuiltinNode {
             dnans += ((double) (nnx - i)) * (nny - j);
         }
         if (dnans > RRuntime.INT_MAX_VALUE) {
-            throw RError.error(this, RError.Message.GENERIC, "number of rows in the result exceeds maximum vector length");
+            throw error(RError.Message.GENERIC, "number of rows in the result exceeds maximum vector length");
         }
         int nans = (int) dnans;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
index a814219f4e..92cad61f05 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.signature.MissingNode;
 import com.oracle.truffle.r.nodes.function.signature.MissingNode.MissingCheckCache;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -53,7 +52,7 @@ public abstract class Missing extends RBuiltinNode {
         String symbol = promise.getClosure().asSymbol();
         if (symbol == null) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, Message.INVALID_USE, "missing");
+            throw error(Message.INVALID_USE, "missing");
         }
         return RRuntime.asLogical(cache.execute(frame, symbol));
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
index 276bb1ad32..b91bffd815 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
@@ -145,7 +145,7 @@ public class NamespaceFunctions {
         @Specialization
         protected RNull registerNamespace(RAbstractStringVector name, REnvironment env) {
             if (REnvironment.registerNamespace(name.getDataAt(0), env) == null) {
-                throw RError.error(this, RError.Message.NS_ALREADY_REG);
+                throw error(RError.Message.NS_ALREADY_REG);
             }
             return RNull.instance;
         }
@@ -153,7 +153,7 @@ public class NamespaceFunctions {
         @Specialization
         protected RNull registerNamespace(RSymbol nameSym, REnvironment env) {
             if (REnvironment.registerNamespace(nameSym.getName(), env) == null) {
-                throw RError.error(this, RError.Message.NS_ALREADY_REG);
+                throw error(RError.Message.NS_ALREADY_REG);
             }
             return RNull.instance;
 
@@ -183,7 +183,7 @@ public class NamespaceFunctions {
         private void doUnregisterNamespace(String name) {
             Object ns = REnvironment.unregisterNamespace(name);
             if (ns == null) {
-                throw RError.error(this, RError.Message.NS_NOTREG);
+                throw error(RError.Message.NS_NOTREG);
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
index 835eb027f5..da6ed4bb29 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
@@ -87,7 +87,7 @@ public abstract class NormalizePath extends RBuiltinNode {
                         msg = Message.GENERIC;
                     }
                     if (mustWork == RRuntime.LOGICAL_TRUE) {
-                        throw RError.error(this, msg, errorArgs);
+                        throw error(msg, errorArgs);
                     } else {
                         // NA means warning
                         RError.warning(this, msg, errorArgs);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index 7d3f43e6bb..993863cf59 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -79,7 +79,7 @@ public abstract class OnExit extends RBuiltinNode {
     protected Object onExit(VirtualFrame frame, RPromise expr, byte add) {
 
         if (na.isNA(add)) {
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "add");
+            throw error(RError.Message.INVALID_ARGUMENT, "add");
         }
 
         // the empty (RNull.instance) expression is used to clear on.exit
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
index cc56be1bf2..11140af453 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import java.util.Map;
 import java.util.Set;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -106,8 +105,7 @@ public class OptionsFunctions {
                 visibility.execute(frame, result.visible);
                 return result.value;
             } catch (OptionsException ex) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(RError.SHOW_CALLER, ex);
+                throw error(ex);
             }
         }
 
@@ -167,7 +165,7 @@ public class OptionsFunctions {
                             names = newNames;
                         }
                     } else {
-                        throw RError.error(RError.SHOW_CALLER, Message.INVALID_UNNAMED_ARGUMENT);
+                        throw error(Message.INVALID_UNNAMED_ARGUMENT);
                     }
                     Object optionVal = options.getValue(optionName);
                     data[i] = optionVal == null ? RNull.instance : optionVal;
@@ -196,14 +194,14 @@ public class OptionsFunctions {
 
         static {
             Casts casts = new Casts(GetOption.class);
-            casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING, "x").mustBe(stringValue()).asStringVector().findFirst();
+            casts.arg("x").defaultError(RError.Message.MUST_BE_STRING, "x").mustBe(stringValue()).asStringVector().findFirst();
         }
 
         @TruffleBoundary
         @Specialization
         protected Object getOption(RAbstractStringVector x) {
             if (x.getLength() != 1) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING);
+                throw error(RError.Message.MUST_BE_STRING);
             }
             ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
             return options.getValue(x.getDataAt(0));
@@ -211,7 +209,7 @@ public class OptionsFunctions {
 
         @Fallback
         protected Object getOption(@SuppressWarnings("unused") Object x) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.MUST_BE_STRING);
+            throw error(RError.Message.MUST_BE_STRING);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index 13d246bb06..5e62c37d0e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -233,7 +233,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
             case 1:
                 return RDataFactory.createIntVectorFromScalar(1);
             default:
-                throw RError.error(RError.NO_CALLER, RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, "list", "orderVector1");
+                throw error(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, "list", "orderVector1");
         }
     }
 
@@ -248,7 +248,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
             v = castVector2(vectors[i]);
             if (n != v.getLength()) {
                 error.enter();
-                throw RError.error(this, RError.Message.ARGUMENT_LENGTHS_DIFFER);
+                throw error(RError.Message.ARGUMENT_LENGTHS_DIFFER);
             }
             vectors[i] = v;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index 0614dd2f28..ac3c210e4d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -91,7 +89,7 @@ public abstract class PMinMax extends RBuiltinNode {
 
     protected static Casts createCasts(Class<? extends PMinMax> extCls) {
         Casts casts = new Casts(extCls);
-        casts.arg("na.rm").defaultError(SHOW_CALLER, Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean());
+        casts.arg("na.rm").defaultError(Message.INVALID_VALUE, "na.rm").mustBe(numericValue()).asLogicalVector().findFirst().mustBe(logicalNA().not()).map(toBoolean());
         return casts;
     }
 
@@ -336,7 +334,7 @@ public abstract class PMinMax extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Fallback
     protected RRawVector pMinMaxRaw(Object naRm, Object args) {
-        throw RError.error(NO_CALLER, RError.Message.INVALID_INPUT_TYPE);
+        throw error(RError.Message.INVALID_INPUT_TYPE);
     }
 
     @RBuiltin(name = "pmax", kind = INTERNAL, parameterNames = {"na.rm", "..."}, behavior = PURE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index 7d68d79d72..8ecb53980e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -104,7 +104,7 @@ public abstract class Parse extends RBuiltinNode {
         Casts casts = new Casts(Parse.class);
         // Note: string is captured by the R wrapper and transformed to a file, other types not
         casts.arg("conn").defaultError(MUST_BE_STRING_OR_CONNECTION, "file").mustNotBeNull().asIntegerVector().findFirst();
-        casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).notNA(-1);
+        casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).replaceNA(-1);
         casts.arg("text").asStringVector();
         casts.arg("prompt").asStringVector().findFirst("?");
         casts.arg("encoding").mustBe(stringValue()).asStringVector().findFirst();
@@ -121,7 +121,7 @@ public abstract class Parse extends RBuiltinNode {
         try (RConnection openConn = connection.forceOpen("r")) {
             lines = openConn.readLines(0, false, false);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.PARSE_ERROR);
+            throw error(RError.Message.PARSE_ERROR);
         }
         return doParse(connection, n, lines, prompt, srcFile, encoding);
     }
@@ -154,7 +154,7 @@ public abstract class Parse extends RBuiltinNode {
             }
             return exprs;
         } catch (ParseException ex) {
-            throw RError.error(this, RError.Message.PARSE_ERROR);
+            throw error(RError.Message.PARSE_ERROR);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index 9b682fe956..208ca6d69b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -26,8 +26,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringV
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import static com.oracle.truffle.r.runtime.RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE;
 import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
+import static com.oracle.truffle.r.runtime.RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -223,7 +223,7 @@ public abstract class Paste extends RBuiltinNode {
         }
         if (castAsCharacterResultNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castAsCharacterResultNode = insert(newCastBuilder().mustBe(stringValue(), SHOW_CALLER, NON_STRING_ARG_TO_INTERNAL_PASTE).buildCastNode());
+            castAsCharacterResultNode = insert(newCastBuilder(SHOW_CALLER).mustBe(stringValue(), NON_STRING_ARG_TO_INTERNAL_PASTE).buildCastNode());
         }
     }
 
@@ -238,7 +238,7 @@ public abstract class Paste extends RBuiltinNode {
     private CastNode getAsCharacterNode() {
         if (asCharacterNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            asCharacterNode = insert(newCastBuilder().returnIf(nullValue(), emptyStringVector()).asStringVector().buildCastNode());
+            asCharacterNode = insert(newCastBuilder(SHOW_CALLER).returnIf(nullValue(), emptyStringVector()).asStringVector().buildCastNode());
         }
         return asCharacterNode;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
index aa7eaefcc7..0b099e7803 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
@@ -39,11 +39,11 @@ public abstract class Pretty extends RBuiltinNode {
         Casts casts = new Casts(Pretty.class);
         casts.arg("l").asDoubleVector().findFirst().mustBe(isFinite());
         casts.arg("u").asDoubleVector().findFirst().mustBe(isFinite());
-        casts.arg("n").asIntegerVector().findFirst().notNA().mustBe(gte0());
-        casts.arg("min.n").asIntegerVector().findFirst().notNA().mustBe(gte0());
+        casts.arg("n").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte0());
+        casts.arg("min.n").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte0());
         casts.arg("shrink.sml").asDoubleVector().findFirst().mustBe(and(isFinite(), gt(0.0)));
         casts.arg("hi").asDoubleVector().mustBe(size(2));
-        casts.arg("eps.correct").defaultError(RError.Message.GENERIC, "'eps.correct' must be 0, 1, or 2").asIntegerVector().findFirst().notNA().mustBe(and(gte0(), lte(2)));
+        casts.arg("eps.correct").defaultError(RError.Message.GENERIC, "'eps.correct' must be 0, 1, or 2").asIntegerVector().findFirst().mustNotBeNA().mustBe(and(gte0(), lte(2)));
     }
 
     @Specialization
@@ -52,10 +52,10 @@ public abstract class Pretty extends RBuiltinNode {
         double hi1 = hi.getDataAt(1);
 
         if (!RRuntime.isFinite(hi0) || hi0 < 0.0) {
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "high.u.bias");
+            throw error(RError.Message.INVALID_ARGUMENT, "high.u.bias");
         }
         if (!RRuntime.isFinite(hi1) || hi1 < 0.0) {
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "u5.bias");
+            throw error(RError.Message.INVALID_ARGUMENT, "u5.bias");
         }
         double[] lo = new double[]{l};
         double[] up = new double[]{u};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
index 0a6d792c11..3845cc9588 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -42,8 +41,6 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 @RBuiltin(name = ".Primitive", kind = PRIMITIVE, parameterNames = "name", behavior = PURE)
 public abstract class Primitive extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     static {
         Casts casts = new Casts(Primitive.class);
         casts.arg("name").defaultError(Message.STRING_ARGUMENT_REQUIRED).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
@@ -66,8 +63,7 @@ public abstract class Primitive extends RBuiltinNode {
     protected RFunction lookup(String name) {
         RFunction function = RContext.lookupBuiltin(name);
         if (function == null || function.getRBuiltin() != null && function.getRBuiltin().getKind() != RBuiltinKind.PRIMITIVE) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.NO_SUCH_PRIMITIVE, name);
+            throw error(RError.Message.NO_SUCH_PRIMITIVE, name);
         }
         return function;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
index 61e3e3830d..6f4906fe55 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
@@ -62,19 +62,19 @@ public class PrintFunctions {
             Casts casts = new Casts(PrintDefault.class);
             casts.arg("digits").allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(Format.R_MIN_DIGITS_OPT).and(lte(Format.R_MAX_DIGITS_OPT)));
 
-            casts.arg("quote").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("quote").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
             casts.arg("na.print").defaultError(RError.Message.INVALID_NA_PRINT_SPEC).allowNull().mustBe(stringValue()).asStringVector().findFirst();
 
             casts.arg("print.gap").defaultError(RError.Message.GAP_MUST_BE_NON_NEGATIVE).allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(0));
 
-            casts.arg("right").defaultError(RError.Message.INVALID_ARGUMENT, "right").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("right").defaultError(RError.Message.INVALID_ARGUMENT, "right").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
             casts.arg("max").allowNull().asIntegerVector().findFirst().mustBe(notIntNA()).mustBe(gte(0));
 
-            casts.arg("useSource").defaultError(RError.Message.INVALID_ARGUMENT, "useSource").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("useSource").defaultError(RError.Message.INVALID_ARGUMENT, "useSource").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
-            casts.arg("noOpt").defaultError(RError.Message.GENERIC, "invalid 'tryS4' internal argument").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("noOpt").defaultError(RError.Message.GENERIC, "invalid 'tryS4' internal argument").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization(guards = "!isS4(o)")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index 37bba1bf20..c9af0b9004 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -62,8 +62,9 @@ public abstract class Quantifier extends RBuiltinNode {
         private final ValueProfile profile = ValueProfile.createClassProfile();
         @Child private CastNode next;
 
-        ProfileCastNode(CastNode next) {
-            this.next = next;
+        ProfileCastNode() {
+            this.next = newCastBuilder(null).allowNull().shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))),
+                            RError.Message.COERCING_ARGUMENT, typeName(), "logical").asLogicalVector().buildCastNode();
         }
 
         @Override
@@ -84,12 +85,7 @@ public abstract class Quantifier extends RBuiltinNode {
     }
 
     private void createArgCast(int index) {
-        // @formatter:off
-        argCastNodes[index] = insert(new ProfileCastNode(newCastBuilder().allowNull().
-            shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))),
-                    RError.Message.COERCING_ARGUMENT, typeName(), "logical").
-            asLogicalVector().buildCastNode()));
-        // @formatter:on
+        argCastNodes[index] = insert(new ProfileCastNode());
     }
 
     protected boolean emptyVectorResult() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index 05eafee4ae..a9e765ebd9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -46,7 +46,7 @@ public abstract class Quit extends RBuiltinNode {
                 return SA_TYPE.fromString(save);
             }
         }
-        throw RError.error(this, RError.Message.QUIT_SAVE);
+        throw error(RError.Message.QUIT_SAVE);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
index a2e1f23a25..8abbd12d7a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_NORMAL_TYPE_IN_RGNKIND;
 import static com.oracle.truffle.r.runtime.RError.Message.SEED_NOT_VALID_INT;
@@ -51,10 +50,10 @@ public class RNGFunctions {
 
         static {
             Casts casts = new Casts(SetSeed.class);
-            casts.arg("seed").allowNull().mustBe(numericValue(), SHOW_CALLER, SEED_NOT_VALID_INT).asIntegerVector().findFirst();
+            casts.arg("seed").allowNull().mustBe(numericValue(), SEED_NOT_VALID_INT).asIntegerVector().findFirst();
             CastsHelper.kindInteger(casts, "kind", INVALID_ARGUMENT, "kind");
             // TODO: implement normal.kind specializations with String
-            casts.arg("normal.kind").allowNull().mustBe(anyValue().not(), UNIMPLEMENTED_TYPE_IN_FUNCTION, "String", "set.seed").mustBe(stringValue(), SHOW_CALLER, INVALID_NORMAL_TYPE_IN_RGNKIND);
+            casts.arg("normal.kind").allowNull().mustBe(anyValue().not(), UNIMPLEMENTED_TYPE_IN_FUNCTION, "String", "set.seed").mustBe(stringValue(), INVALID_NORMAL_TYPE_IN_RGNKIND);
         }
 
         @SuppressWarnings("unused")
@@ -100,7 +99,7 @@ public class RNGFunctions {
 
     private static final class CastsHelper {
         public static void kindInteger(Casts casts, String name, Message error, Object... messageArgs) {
-            casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), SHOW_CALLER, error, messageArgs).asIntegerVector().findFirst();
+            casts.arg(name).mapNull(constant(RRNG.NO_KIND_CHANGE)).mustBe(numericValue(), error, messageArgs).asIntegerVector().findFirst();
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
index 16f4d02288..bbb518539e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
@@ -20,7 +20,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_TIES_FOR_RANK;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_VALUE;
@@ -64,14 +63,14 @@ public abstract class Rank extends RBuiltinNode {
     static {
         Casts casts = new Casts(Rank.class);
         Function<Object, Object> typeFunc = x -> x.getClass().getSimpleName();
-        casts.arg("x").mustBe(abstractVectorValue(), SHOW_CALLER, UNIMPLEMENTED_TYPE_IN_GREATER, typeFunc).mustBe(not(rawValue()), SHOW_CALLER, RError.Message.RAW_SORT);
+        casts.arg("x").mustBe(abstractVectorValue(), UNIMPLEMENTED_TYPE_IN_GREATER, typeFunc).mustBe(not(rawValue()), RError.Message.RAW_SORT);
         // Note: in the case of no long vector support, when given anything but integer as n, GnuR
         // behaves as if n=1,
         // we allow ourselves to be bit inconsistent with GnuR in that.
-        casts.arg("len").defaultError(NO_CALLER, INVALID_VALUE, "length(xx)").mustBe(numericValue()).asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(intNA().not().and(gte0()));
+        casts.arg("len").defaultError(INVALID_VALUE, "length(xx)").mustBe(numericValue()).asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(intNA().not().and(gte0()));
         // Note: we parse ties.methods in the Specialization anyway, so the validation of the value
         // is there
-        casts.arg("ties.method").defaultError(NO_CALLER, INVALID_TIES_FOR_RANK).mustBe(stringValue()).asStringVector().findFirst();
+        casts.arg("ties.method").defaultError(INVALID_TIES_FOR_RANK).mustBe(stringValue()).asStringVector().findFirst();
     }
 
     private Order.OrderVector1Node initOrderVector1() {
@@ -156,7 +155,7 @@ public abstract class Rank extends RBuiltinNode {
                 return TiesKind.MIN;
             default:
                 errorProfile.enter();
-                throw RError.error(NO_CALLER, RError.Message.GENERIC, "invalid ties.method for rank() [should never happen]");
+                throw error(RError.Message.GENERIC, "invalid ties.method for rank() [should never happen]");
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
index 4278530d54..633373acf3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
@@ -76,8 +76,8 @@ public class RawFunctions {
 
         static {
             Casts casts = new Casts(RawToChar.class);
-            casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
-            casts.arg("multiple").defaultError(RError.Message.INVALID_LOGICAL).asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
+            casts.arg("multiple").defaultError(RError.Message.INVALID_LOGICAL).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -110,8 +110,8 @@ public class RawFunctions {
 
         static {
             Casts casts = new Casts(RawShift.class);
-            casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
-            casts.arg("n").defaultError(RError.Message.MUST_BE_SMALL_INT, "shift").asIntegerVector().findFirst().notNA().mustBe(gte(-8).and(lte(8)));
+            casts.arg("x").mustBe(instanceOf(RAbstractRawVector.class), RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
+            casts.arg("n").defaultError(RError.Message.MUST_BE_SMALL_INT, "shift").asIntegerVector().findFirst().mustNotBeNA().mustBe(gte(-8).and(lte(8)));
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
index 538a0d8c68..389eb9cbc4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
@@ -38,8 +38,7 @@ public abstract class RawToBits extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(RawToBits.class);
-        casts.arg("x").mustNotBeNull(RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x").mustBe(Predef.rawValue(), RError.SHOW_CALLER,
-                        RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
+        casts.arg("x").mustNotBeNull(RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x").mustBe(Predef.rawValue(), RError.Message.ARGUMENT_MUST_BE_RAW_VECTOR, "x");
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
index f0a6a89595..e888b61de4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
@@ -72,10 +72,10 @@ public abstract class ReadDCF extends RBuiltinNode {
             }
             dcf = DCF.read(openConn.readLines(0, true, false), keepWhiteSet);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
+            throw error(RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
         }
         if (dcf == null) {
-            throw RError.error(this, RError.Message.INVALID_CONNECTION);
+            throw error(RError.Message.INVALID_CONNECTION);
         }
         List<DCF.Fields> records = dcf.getRecords();
         int nRecords = records.size();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
index 999f8ef7f3..0c126db0a0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
@@ -43,7 +43,7 @@ public abstract class ReadREnviron extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(ReadREnviron.class);
-        casts.arg("x").mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_STRING, "x").asStringVector().findFirst();
+        casts.arg("x").mustBe(stringValue(), RError.Message.ARGUMENT_MUST_BE_STRING, "x").asStringVector().findFirst();
     }
 
     @TruffleBoundary
@@ -56,7 +56,7 @@ public abstract class ReadREnviron extends RBuiltinNode {
             RError.warning(this, RError.Message.GENERIC, ex.getMessage());
             result = RRuntime.LOGICAL_FALSE;
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
index 4c53575646..6d88f338e4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
@@ -29,7 +29,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
@@ -47,8 +46,6 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 @RBuiltin(name = "Recall", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"..."}, nonEvalArgs = {0}, behavior = COMPLEX)
 public abstract class Recall extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     @Child private LocalReadVariableNode readArgs = LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false);
 
     @Child private GetCallerFrameNode callerFrame = new GetCallerFrameNode();
@@ -64,8 +61,7 @@ public abstract class Recall extends RBuiltinNode {
         Frame cframe = callerFrame.execute(frame);
         RFunction function = RArguments.getFunction(cframe);
         if (function == null) {
-            errorProfile.enter();
-            throw RError.error(RError.SHOW_CALLER, RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE);
+            throw error(RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE);
         }
         /*
          * The args passed to the Recall internal are ignored, they are always "...". Instead, this
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
index 4703cc2b23..88bd9e9c80 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
@@ -43,7 +43,7 @@ public abstract class RegFinalizer extends RBuiltinNode {
         Casts casts = new Casts(RegFinalizer.class);
         casts.arg("e").mustBe(instanceOf(REnvironment.class).or(instanceOf(RExternalPtr.class)), RError.Message.REG_FINALIZER_FIRST);
         casts.arg("f").mustBe(instanceOf(RFunction.class), RError.Message.REG_FINALIZER_SECOND);
-        casts.arg("onexit").asLogicalVector().findFirst().notNA(RError.Message.REG_FINALIZER_THIRD).map(toBoolean());
+        casts.arg("onexit").asLogicalVector().findFirst().mustNotBeNA(RError.Message.REG_FINALIZER_THIRD).map(toBoolean());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index 27948929a0..db5dbce76a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -92,7 +92,7 @@ public abstract class Repeat extends RBuiltinNode {
         casts.arg("times").defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector();
         casts.arg("length.out").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA,
                         RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0)));
-        casts.arg("each").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each").notNA(
+        casts.arg("each").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each").replaceNA(
                         1).mustBe(gte(0));
     }
 
@@ -101,7 +101,7 @@ public abstract class Repeat extends RBuiltinNode {
     }
 
     private RError invalidTimes() {
-        throw RError.error(this, RError.Message.INVALID_ARGUMENT, "times");
+        throw error(RError.Message.INVALID_ARGUMENT, "times");
     }
 
     @Specialization(guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
index b49bef8a6f..41e4ed34b5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import java.util.function.IntFunction;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -54,13 +53,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 public abstract class RepeatInternal extends RBuiltinNode {
 
     private final ConditionProfile timesOneProfile = ConditionProfile.createBinaryProfile();
-    private final BranchProfile errorProfile = BranchProfile.create();
 
     static {
         Casts casts = new Casts(RepeatInternal.class);
-        casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER2, RError.Message.ATTEMPT_TO_REPLICATE, typeName());
-        casts.arg("times").defaultError(RError.SHOW_CALLER, RError.Message.INCORRECT_ARG_TYPE, "second").mustBe(abstractVectorValue()).asIntegerVector().mustBe(notEmpty(),
-                        RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "times");
+        casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName());
+        casts.arg("times").defaultError(RError.Message.INCORRECT_ARG_TYPE, "second").mustBe(abstractVectorValue()).asIntegerVector().mustBe(notEmpty(),
+                        RError.Message.INVALID_VALUE, "times");
     }
 
     @FunctionalInterface
@@ -81,8 +79,7 @@ public abstract class RepeatInternal extends RBuiltinNode {
         if (timesOneProfile.profile(timesLength == 1)) {
             int timesValue = times.getDataAt(0);
             if (timesValue < 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.INVALID_VALUE, "times");
+                throw error(RError.Message.INVALID_VALUE, "times");
             }
             int count = timesValue * valueLength;
             result = arrayConstructor.apply(count);
@@ -97,8 +94,7 @@ public abstract class RepeatInternal extends RBuiltinNode {
             for (int i = 0; i < timesLength; i++) {
                 int data = times.getDataAt(i);
                 if (data < 0) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.INVALID_VALUE, "times");
+                    throw error(RError.Message.INVALID_VALUE, "times");
                 }
                 count += data;
             }
@@ -111,8 +107,7 @@ public abstract class RepeatInternal extends RBuiltinNode {
                 }
             }
         } else {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.INVALID_VALUE, "times");
+            throw error(RError.Message.INVALID_VALUE, "times");
         }
         return createResult.create(result, value.isComplete());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
index 163552a82d..2b6a4d9387 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
@@ -43,9 +43,9 @@ public abstract class RepeatLength extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(RepeatLength.class);
-        casts.arg("x").mustBe(abstractVectorValue(), RError.SHOW_CALLER, RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR);
+        casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR);
         // with default error message, SHOW_CALLER does not work
-        casts.arg("length.out").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "length.out").mustNotBeNull().asIntegerVector().mustBe(size(1)).findFirst().mustBe(notIntNA());
+        casts.arg("length.out").defaultError(RError.Message.INVALID_VALUE, "length.out").mustNotBeNull().asIntegerVector().mustBe(size(1)).findFirst().mustBe(notIntNA());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
index 544075d500..0eca527fe5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
@@ -60,24 +60,22 @@ public abstract class Rm extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Rm.class);
-        casts.arg("list").mustBe(stringValue(), SHOW_CALLER, INVALID_FIRST_ARGUMENT);
-        casts.arg("envir").mustNotBeNull(SHOW_CALLER, USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, SHOW_CALLER, INVALID_ARGUMENT, "envir");
-        casts.arg("inherits").mustBe(numericValue(), SHOW_CALLER, INVALID_ARGUMENT, "inherits").asLogicalVector().findFirst().map(toBoolean());
+        casts.arg("list").mustBe(stringValue(), INVALID_FIRST_ARGUMENT);
+        casts.arg("envir").mustNotBeNull(USE_NULL_ENV_DEFUNCT).mustBe(REnvironment.class, INVALID_ARGUMENT, "envir");
+        casts.arg("inherits").mustBe(numericValue(), INVALID_ARGUMENT, "inherits").asLogicalVector().findFirst().map(toBoolean());
     }
 
     // this specialization is for internal use only
     // TODO: what internal use? Does it still apply?
     @Specialization
-    @SuppressWarnings("unused")
-    protected Object rm(VirtualFrame frame, String name, RMissing envir, boolean inherits) {
+    protected Object rm(VirtualFrame frame, String name, @SuppressWarnings("unused") RMissing envir, @SuppressWarnings("unused") boolean inherits) {
         removeFromFrame(frame, name);
         return RNull.instance;
     }
 
     @Specialization
     @TruffleBoundary
-    @SuppressWarnings("unused")
-    protected Object rm(RAbstractStringVector list, REnvironment envir, boolean inherits) {
+    protected Object rm(RAbstractStringVector list, REnvironment envir, @SuppressWarnings("unused") boolean inherits) {
         try {
             for (int i = 0; i < list.getLength(); i++) {
                 if (envir == REnvironment.globalEnv()) {
@@ -87,7 +85,7 @@ public abstract class Rm extends RBuiltinNode {
                 }
             }
         } catch (PutException ex) {
-            throw RError.error(SHOW_CALLER, ex);
+            throw error(ex);
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
index 245edd7529..e7ac9923d1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
@@ -14,7 +14,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -31,7 +30,7 @@ public abstract class Row extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Row.class);
-        casts.arg("dims").defaultError(SHOW_CALLER, RError.Message.MATRIX_LIKE_REQUIRED, "row").mustBe(integerValue()).asIntegerVector().mustBe(size(2));
+        casts.arg("dims").defaultError(RError.Message.MATRIX_LIKE_REQUIRED, "row").mustBe(integerValue()).asIntegerVector().mustBe(size(2));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
index f476fd860d..b7db4f9029 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
@@ -58,7 +58,7 @@ public class RowsumFunctions {
 
             casts.arg("uniqueg").asVector();
 
-            casts.arg("snarm").asLogicalVector().findFirst().notNA(RError.Message.INVALID_LOGICAL).map(toBoolean());
+            casts.arg("snarm").asLogicalVector().findFirst().mustNotBeNA(RError.Message.INVALID_LOGICAL).map(toBoolean());
 
             casts.arg("rn").mustBe(stringValue(), RError.Message.ROWSUM_NAMES_NOT_CHAR).asStringVector();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
index 76766dbfcf..7465e31dfb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
@@ -96,7 +96,6 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
         @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNodeGen.create(true, true);
         @Child private PromiseCheckHelperNode promiseCheckHelper;
 
-        private final BranchProfile errorProfile = BranchProfile.create();
         private final BranchProfile firstArgMissing = BranchProfile.create();
         private final ConditionProfile argMissingProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile argsValueAndNamesProfile = ConditionProfile.createBinaryProfile();
@@ -136,8 +135,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
          */
         private Object getEnclosingArg(VirtualFrame frame, String generic) {
             if (RArguments.getArgumentsLength(frame) == 0 || RArguments.getArgument(frame, 0) == null) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.UNKNOWN_FUNCTION_USE_METHOD, generic, RRuntime.toString(RNull.instance));
+                throw error(RError.Message.UNKNOWN_FUNCTION_USE_METHOD, generic, RRuntime.toString(RNull.instance));
             }
             Object enclosingArg = RArguments.getArgument(frame, 0);
             if (argsValueAndNamesProfile.profile(enclosingArg instanceof RArgsValuesAndNames)) {
@@ -188,7 +186,6 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
 
         @Child private PromiseHelperNode promiseHelper;
 
-        private final BranchProfile errorProfile = BranchProfile.create();
         private final ConditionProfile emptyArgsProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile genericCallFrameNullProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile genericDefFrameNullProfile = ConditionProfile.createBinaryProfile();
@@ -218,8 +215,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
         protected Object nextMethod(VirtualFrame frame, @SuppressWarnings("unused") Object ignoredGeneric, Object obj, RArgsValuesAndNames args) {
             String generic = (String) rvnGeneric.execute(frame);
             if (generic == null || generic.isEmpty()) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.GEN_FUNCTION_NOT_SPECIFIED);
+                throw error(RError.Message.GEN_FUNCTION_NOT_SPECIFIED);
             }
             return nextMethod(frame, generic, obj, args);
         }
@@ -290,8 +286,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
             }
             if (RArguments.getArgumentsLength(frame) == 0 || RArguments.getArgument(frame, 0) == null ||
                             (!(RArguments.getArgument(frame, 0) instanceof RAbstractContainer) && !(RArguments.getArgument(frame, 0) instanceof RPromise))) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.OBJECT_NOT_SPECIFIED);
+                throw error(RError.Message.OBJECT_NOT_SPECIFIED);
             }
             Object arg = RArguments.getArgument(frame, 0);
             if (arg instanceof RPromise) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
index 995836e400..c58dd93629 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustBe;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_FIRST_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.VECTOR_SIZE_NA_NAN;
@@ -55,12 +54,12 @@ public abstract class Sample extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Sample.class);
-        casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER, VECTOR_SIZE_NA_NAN).mapIf(doubleValue(),
-                        chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), SHOW_CALLER, VECTOR_SIZE_NA_NAN)).with(
-                                        mustBe(lt(4.5e15), SHOW_CALLER, VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0());
-        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().notNA(SHOW_CALLER,
-                        INVALID_ARGUMENT, "size").mustBe(gte0(), SHOW_CALLER, INVALID_ARGUMENT, "size");
-        casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().notNA().map(toBoolean());
+        casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).mustNotBeNA(VECTOR_SIZE_NA_NAN).mapIf(doubleValue(),
+                        chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), VECTOR_SIZE_NA_NAN)).with(
+                                        mustBe(lt(4.5e15), VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0());
+        casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().mustNotBeNA(
+                        INVALID_ARGUMENT, "size").mustBe(gte0(), INVALID_ARGUMENT, "size");
+        casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustNotBeNA().map(toBoolean());
         casts.arg("prob").asDoubleVector();
     }
 
@@ -79,21 +78,21 @@ public abstract class Sample extends RBuiltinNode {
     @SuppressWarnings("unused")
     protected RIntVector doSampleInvalidProb(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.INCORRECT_NUM_PROB);
+        throw error(RError.Message.INCORRECT_NUM_PROB);
     }
 
     @Specialization(guards = "largerPopulation(x, size, isRepeatable)")
     @SuppressWarnings("unused")
     protected RIntVector doSampleLargerPopulation(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.SAMPLE_LARGER_THAN_POPULATION);
+        throw error(RError.Message.SAMPLE_LARGER_THAN_POPULATION);
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = "largerPopulation(x, size, isRepeatable)")
     protected RIntVector doSampleInvalidLargerPopulation(final int x, final int size, final boolean isRepeatable, final RNull prob) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.INCORRECT_NUM_PROB);
+        throw error(RError.Message.INCORRECT_NUM_PROB);
     }
 
     // Actual specializations:
@@ -161,10 +160,10 @@ public abstract class Sample extends RBuiltinNode {
         double probSum = 0;
         for (double aProb : probArray) {
             if (!RRuntime.isFinite(aProb)) {
-                throw RError.error(this, RError.Message.NA_IN_PROB_VECTOR);
+                throw error(RError.Message.NA_IN_PROB_VECTOR);
             }
             if (aProb < 0) {
-                throw RError.error(this, RError.Message.NEGATIVE_PROBABILITY);
+                throw error(RError.Message.NEGATIVE_PROBABILITY);
             }
             if (aProb > 0) {
                 probSum += aProb;
@@ -172,7 +171,7 @@ public abstract class Sample extends RBuiltinNode {
             }
         }
         if (nonZeroProbCount == 0 || (!isRepeatable && size > nonZeroProbCount)) {
-            throw RError.error(this, RError.Message.TOO_FEW_POSITIVE_PROBABILITY);
+            throw error(RError.Message.TOO_FEW_POSITIVE_PROBABILITY);
         }
         for (int i = 0; i < x; i++) {
             probArray[i] /= probSum;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
index 647d0c919f..42488c4dbb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte0;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFinite;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.ALGORITHM_FOR_SIZE_N_DIV_2;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_FIRST_ARGUMENT;
@@ -25,11 +24,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.MODIFIES_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetDouble;
 import com.oracle.truffle.r.runtime.Collections.NonRecursiveHashSetInt;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -44,14 +41,12 @@ public abstract class Sample2 extends RBuiltinNode {
     private static final double U = 33554432.0;
     static final double MAX_INT = Integer.MAX_VALUE;
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     static {
         Casts casts = new Casts(Sample2.class);
-        casts.arg("x").defaultError(SHOW_CALLER, INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).notNA(SHOW_CALLER,
-                        INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(gte(0.0)).mustBe(isFinite());
-        casts.arg("size").defaultError(SHOW_CALLER, INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().notNA(SHOW_CALLER, INVALID_ARGUMENT,
-                        "size").mustBe(gte0(), SHOW_CALLER, INVALID_ARGUMENT, "size");
+        casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).mustNotBeNA(INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(
+                        gte(0.0)).mustBe(isFinite());
+        casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().mustNotBeNA(INVALID_ARGUMENT,
+                        "size").mustBe(gte0(), INVALID_ARGUMENT, "size");
     }
 
     @Specialization(guards = "x > MAX_INT")
@@ -98,8 +93,7 @@ public abstract class Sample2 extends RBuiltinNode {
 
     private void validate(double x, int size) {
         if (size > x / 2) {
-            errorProfile.enter();
-            throw RError.error(SHOW_CALLER, ALGORITHM_FOR_SIZE_N_DIV_2);
+            throw error(ALGORITHM_FOR_SIZE_N_DIV_2);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 760cde6682..6942310e89 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -30,7 +30,6 @@ import java.util.LinkedList;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
@@ -65,7 +64,6 @@ public abstract class Scan extends RBuiltinNode {
     private static final int NO_COMCHAR = 100000; /* won't occur even in Unicode */
 
     private final NACheck naCheck = NACheck.create();
-    private final BranchProfile errorProfile = BranchProfile.create();
     @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
 
     @Child private CastToVectorNode castVector;
@@ -106,7 +104,7 @@ public abstract class Scan extends RBuiltinNode {
 
         casts.arg("what").asVector();
 
-        casts.arg("nmax").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0));
+        casts.arg("nmax").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0));
 
         casts.arg("sep").allowNull().mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value");
 
@@ -115,9 +113,9 @@ public abstract class Scan extends RBuiltinNode {
 
         casts.arg("quote").defaultError(RError.Message.INVALID_QUOTE_SYMBOL).mapNull(constant("")).mustBe(stringValue()).asStringVector().findFirst("");
 
-        casts.arg("skip").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0));
+        casts.arg("skip").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0));
 
-        casts.arg("nlines").asIntegerVector().findFirst(0).notNA(0).mapIf(lt(0), constant(0));
+        casts.arg("nlines").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0));
 
         casts.arg("na.strings").mustBe(stringValue());
 
@@ -127,19 +125,19 @@ public abstract class Scan extends RBuiltinNode {
 
         casts.arg("strip.white").mustBe(logicalValue());
 
-        casts.arg("quiet").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA(RRuntime.LOGICAL_FALSE).map(toBoolean());
+        casts.arg("quiet").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).replaceNA(RRuntime.LOGICAL_FALSE).map(toBoolean());
 
-        casts.arg("blank.lines.skip").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE).map(toBoolean());
+        casts.arg("blank.lines.skip").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).replaceNA(RRuntime.LOGICAL_TRUE).map(toBoolean());
 
-        casts.arg("multi.line").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).notNA(RRuntime.LOGICAL_TRUE).map(toBoolean());
+        casts.arg("multi.line").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).replaceNA(RRuntime.LOGICAL_TRUE).map(toBoolean());
 
-        casts.arg("comment.char").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map(charAt0(RRuntime.INT_NA)).notNA(NO_COMCHAR);
+        casts.arg("comment.char").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map(charAt0(RRuntime.INT_NA)).replaceNA(NO_COMCHAR);
 
-        casts.arg("allowEscapes").asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg("allowEscapes").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
         casts.arg("encoding").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
 
-        casts.arg("skipNull").asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg("skipNull").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
     }
 
@@ -164,8 +162,7 @@ public abstract class Scan extends RBuiltinNode {
         data.naStrings = naStringsVec;
 
         if (stripVec.getLength() != 1 && stripVec.getLength() != what.getLength()) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.INVALID_LENGTH, "strip.white");
+            throw error(RError.Message.INVALID_LENGTH, "strip.white");
         }
         byte strip = stripVec.getDataAt(0);
 
@@ -199,7 +196,7 @@ public abstract class Scan extends RBuiltinNode {
                 return scanVector(what, nmax, nlines, flush, strip == RRuntime.LOGICAL_TRUE, blSkip, data);
             }
         } catch (IOException x) {
-            throw RError.error(this, RError.Message.CANNOT_READ_CONNECTION);
+            throw error(RError.Message.CANNOT_READ_CONNECTION);
         }
     }
 
@@ -322,15 +319,14 @@ public abstract class Scan extends RBuiltinNode {
 
         int nc = what.getLength();
         if (nc == 0) {
-            throw RError.error(this, RError.Message.EMPTY_WHAT);
+            throw error(RError.Message.EMPTY_WHAT);
         }
         int blockSize = maxRecords > 0 ? maxRecords : (maxLines > 0 ? maxLines : SCAN_BLOCKSIZE);
 
         RList list = RDataFactory.createList(new Object[nc]);
         for (int i = 0; i < nc; i++) {
             if (what.getDataAt(i) == RNull.instance) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "what");
+                throw error(RError.Message.INVALID_ARGUMENT, "what");
             } else {
                 RAbstractVector vec = castVector(what.getDataAt(i));
                 list.updateDataAt(i, vec.createEmptySameType(blockSize, RDataFactory.COMPLETE_VECTOR), null);
@@ -367,7 +363,7 @@ public abstract class Scan extends RBuiltinNode {
                         n = 0;
                         break;
                     } else if (!multiLine) {
-                        throw RError.error(this, RError.Message.LINE_ELEMENTS, lines + 1, nc);
+                        throw error(RError.Message.LINE_ELEMENTS, lines + 1, nc);
                     } else {
                         strItems = getItems(data, blSkip);
                         // Checkstyle: stop modified control variable check
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 9ab484de26..b776d9c389 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -357,7 +357,7 @@ public final class SeqFunctions {
         }
 
         CastNode createLengthResultCast() {
-            return newCastBuilder().defaultError(NO_CALLER, Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).asIntegerVector(false, false, false).findFirst().mustBe(
+            return newCastBuilder(null).defaultError(Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).asIntegerVector(false, false, false).findFirst().mustBe(
                             gte(0).and(notIntNA())).buildCastNode();
         }
     }
@@ -603,7 +603,7 @@ public final class SeqFunctions {
             if (directionProfile.profile(from < to)) {
                 if (by < 0) {
                     error.enter();
-                    throw RError.error(this, RError.Message.WRONG_SIGN_IN_BY);
+                    throw error(RError.Message.WRONG_SIGN_IN_BY);
                 }
                 result = RDataFactory.createIntSequence(from, by, (to - from) / by + 1);
             } else {
@@ -612,7 +612,7 @@ public final class SeqFunctions {
                 }
                 if (by > 0) {
                     error.enter();
-                    throw RError.error(this, RError.Message.WRONG_SIGN_IN_BY);
+                    throw error(RError.Message.WRONG_SIGN_IN_BY);
                 }
                 result = RDataFactory.createIntSequence(from, by, (from - to) / (-by) + 1);
             }
@@ -669,7 +669,7 @@ public final class SeqFunctions {
                 } else {
                     error.enter();
                     // This should go away in an upcoming GNU R release
-                    throw RError.error(this, seqFastPath ? RError.Message.INVALID_TFB_SD : RError.Message.INVALID_TFB);
+                    throw error(seqFastPath ? RError.Message.INVALID_TFB_SD : RError.Message.INVALID_TFB);
                 }
             }
             double dd = Math.abs(del) / Math.max(Math.abs(to), Math.abs(from));
@@ -679,11 +679,11 @@ public final class SeqFunctions {
             }
             if (n > Integer.MAX_VALUE) {
                 error.enter();
-                throw RError.error(this, RError.Message.BY_TOO_SMALL);
+                throw error(RError.Message.BY_TOO_SMALL);
             }
             if (n < -FEPS) {
                 error.enter();
-                throw RError.error(this, RError.Message.WRONG_SIGN_IN_BY);
+                throw error(RError.Message.WRONG_SIGN_IN_BY);
             }
             RAbstractVector result;
             if (allInt) {
@@ -921,7 +921,7 @@ public final class SeqFunctions {
         @Fallback
         protected RAbstractVector seqFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith) {
             error.enter();
-            throw RError.error(this, RError.Message.TOO_MANY_ARGS);
+            throw error(RError.Message.TOO_MANY_ARGS);
         }
 
         // Guard methods
@@ -972,7 +972,7 @@ public final class SeqFunctions {
         private int validateIntParam(int v, String vName) {
             if (RRuntime.isNA(v)) {
                 error.enter();
-                throw RError.error(this, RError.Message.CANNOT_BE_INVALID, vName);
+                throw error(RError.Message.CANNOT_BE_INVALID, vName);
             }
             return v;
         }
@@ -985,7 +985,7 @@ public final class SeqFunctions {
             if (vObj != RMissing.instance) {
                 if (!isFinite(v)) {
                     error.enter();
-                    throw RError.error(this, RError.Message.CANNOT_BE_INVALID, vName);
+                    throw error(RError.Message.CANNOT_BE_INVALID, vName);
                 }
             }
             return v;
@@ -998,7 +998,7 @@ public final class SeqFunctions {
             if (obj != RMissing.instance) {
                 if (getLength(frame, obj) != 1) {
                     error.enter();
-                    throw RError.error(this, RError.Message.MUST_BE_SCALAR, vName);
+                    throw error(RError.Message.MUST_BE_SCALAR, vName);
                 }
             }
         }
@@ -1007,7 +1007,7 @@ public final class SeqFunctions {
             double len = asRealLen.execute(lengthOut);
             if (RRuntime.isNAorNaN(len) || len <= -0.5) {
                 error.enter();
-                throw RError.error(this, seqFastPath ? RError.Message.MUST_BE_POSITIVE_SD : RError.Message.MUST_BE_POSITIVE, seqFastPath ? "length" : "length.out");
+                throw error(seqFastPath ? RError.Message.MUST_BE_POSITIVE_SD : RError.Message.MUST_BE_POSITIVE, seqFastPath ? "length" : "length.out");
             }
             if (getLength(frame, lengthOut) != 1) {
                 RError.warning(this, RError.Message.FIRST_ELEMENT_USED, "length.out");
@@ -1042,7 +1042,7 @@ public final class SeqFunctions {
             double r = Math.abs(to - from);
             if (r > Integer.MAX_VALUE) {
                 error.enter();
-                throw RError.error(this, RError.Message.TOO_LONG_VECTOR);
+                throw error(RError.Message.TOO_LONG_VECTOR);
             }
             int length = (int) (r + 1 + FLT_EPSILON);
             return length;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
index 82f063958e..16de9b7570 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
@@ -54,11 +54,11 @@ public class SerializeFunctions {
         protected Object doUnserializeFromConnBase(int connIndex, @SuppressWarnings("unused") REnvironment refhook) {
             try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen("rb")) {
                 if (!openConn.canRead()) {
-                    throw RError.error(this, RError.Message.CONNECTION_NOT_OPEN_READ);
+                    throw error(RError.Message.CONNECTION_NOT_OPEN_READ);
                 }
                 return RSerialize.unserialize(openConn);
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+                throw error(RError.Message.GENERIC, ex.getMessage());
             }
         }
 
@@ -73,15 +73,15 @@ public class SerializeFunctions {
             // xdr is only relevant if ascii is false
             try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen(type != RSerialize.XDR ? "wt" : "wb")) {
                 if (!openConn.canWrite()) {
-                    throw RError.error(this, RError.Message.CONNECTION_NOT_OPEN_WRITE);
+                    throw error(RError.Message.CONNECTION_NOT_OPEN_WRITE);
                 }
                 if (type == RSerialize.XDR && openConn.isTextMode()) {
-                    throw RError.error(this, RError.Message.BINARY_CONNECTION_REQUIRED);
+                    throw error(RError.Message.BINARY_CONNECTION_REQUIRED);
                 }
                 RSerialize.serialize(openConn, object, type, RSerialize.DEFAULT_VERSION, null);
                 return RNull.instance;
             } catch (IOException ex) {
-                throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+                throw error(RError.Message.GENERIC, ex.getMessage());
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
index 49a67b4f48..93fa6d8ce7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
@@ -47,9 +47,9 @@ public abstract class SetS4Object extends RBuiltinNode {
     static {
         Casts casts = new Casts(SetS4Object.class);
         casts.arg("object").asAttributable(true, true, true);
-        casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "flag").findFirst().map(toBoolean());
+        casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.Message.INVALID_ARGUMENT, "flag").findFirst().map(toBoolean());
         // "complete" can be a vector, unlike "flag"
-        casts.arg("complete").asIntegerVector().findFirst(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "complete");
+        casts.arg("complete").asIntegerVector().findFirst(RError.Message.INVALID_ARGUMENT, "complete");
     }
 
     @Specialization
@@ -61,7 +61,7 @@ public abstract class SetS4Object extends RBuiltinNode {
             boolean wasS4 = RContext.getInstance().isNullS4Object();
             RContext.getInstance().setNullS4Object(false);
             if (wasS4) {
-                throw RError.error(this, RError.Message.GENERIC, "object of class \"NULL\" does not correspond to a valid S3 object");
+                throw error(RError.Message.GENERIC, "object of class \"NULL\" does not correspond to a valid S3 object");
             }
         }
         return object;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
index 4c4abf4a6b..42c91558b5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.CHAR_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
@@ -44,7 +43,7 @@ public abstract class Setwd extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Setwd.class);
-        casts.arg("path").defaultError(SHOW_CALLER, CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
+        casts.arg("path").defaultError(CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
     }
 
     @Specialization
@@ -56,7 +55,7 @@ public abstract class Setwd extends RBuiltinNode {
         String nwd = Utils.tildeExpand(path);
         int rc = setwdNode.execute(nwd);
         if (rc != 0) {
-            throw RError.error(this, RError.Message.CANNOT_CHANGE_DIRECTORY);
+            throw error(RError.Message.CANNOT_CHANGE_DIRECTORY);
         } else {
             String nwdAbs = getwdNode.execute();
             Utils.updateCurwd(nwdAbs);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
index eed5de7dd1..d06c25acbd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
@@ -45,7 +45,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 public abstract class ShortRowNames extends RBuiltinNode {
 
     private final BranchProfile naValueMet = BranchProfile.create();
-    private final BranchProfile errorProfile = BranchProfile.create();
     private final ValueProfile operandTypeProfile = ValueProfile.createClassProfile();
 
     @Child private GetRowNamesAttributeNode getRowNamesNode = GetRowNamesAttributeNode.create();
@@ -98,8 +97,7 @@ public abstract class ShortRowNames extends RBuiltinNode {
         } else if (rowNames instanceof RAbstractContainer) {
             return ((RAbstractContainer) rowNames).getLength();
         } else {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "type");
+            throw error(RError.Message.INVALID_ARGUMENT, "type");
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
index 9ae7473c5f..c187408a6a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
@@ -46,9 +46,9 @@ public class SinkFunctions {
         static {
             Casts casts = new Casts(Sink.class);
             casts.arg("file").mustBe(integerValue()).asIntegerVector().findFirst();
-            casts.arg("closeOnExit").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("split").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("closeOnExit").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("type").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("split").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -62,7 +62,7 @@ public class SinkFunctions {
                 try {
                     StdConnections.popDivertOut();
                 } catch (IOException ex) {
-                    throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+                    throw error(RError.Message.GENERIC, ex.getMessage());
                 }
             } else {
                 RConnection conn = RConnection.fromIndex(file);
@@ -81,7 +81,7 @@ public class SinkFunctions {
 
         static {
             Casts casts = new Casts(SinkNumber.class);
-            casts.arg("type").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("type").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
index b785bc5ddd..b52efc144f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
@@ -61,7 +61,7 @@ public abstract class Slot extends RBuiltinNode {
             }
         }
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.GENERIC, "invalid type or length for slot name");
+        throw error(RError.Message.GENERIC, "invalid type or length for slot name");
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index 7ae1a1ce6e..b5e9e5689a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL;
 import static com.oracle.truffle.r.runtime.RError.Message.ONLY_ATOMIC_CAN_BE_SORTED;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
@@ -60,11 +59,11 @@ public class SortFunctions {
 
     private abstract static class Adapter extends RBuiltinNode {
         protected static void addCastForX(Casts casts) {
-            casts.arg("x").allowNull().mustBe(abstractVectorValue(), SHOW_CALLER, ONLY_ATOMIC_CAN_BE_SORTED);
+            casts.arg("x").allowNull().mustBe(abstractVectorValue(), ONLY_ATOMIC_CAN_BE_SORTED);
         }
 
         protected static void addCastForDecreasing(Casts casts) {
-            casts.arg("decreasing").defaultError(SHOW_CALLER, INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
+            casts.arg("decreasing").defaultError(INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
         }
 
         @TruffleBoundary
@@ -244,7 +243,7 @@ public class SortFunctions {
         static {
             Casts casts = new Casts(RadixSort.class);
             casts.arg("na.last").asLogicalVector().findFirst();
-            casts.arg("decreasing").mustBe(numericValue(), SHOW_CALLER, INVALID_LOGICAL, "decreasing").asLogicalVector();
+            casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector();
             casts.arg("retgrp").asLogicalVector().findFirst().map(toBoolean());
             casts.arg("sortstr").asLogicalVector().findFirst().map(toBoolean());
         }
@@ -262,7 +261,7 @@ public class SortFunctions {
                 return RNull.instance;
             }
             if (nargs != decreasingVec.getLength()) {
-                throw RError.error(this, RError.Message.RADIX_SORT_DEC_MATCH);
+                throw error(RError.Message.RADIX_SORT_DEC_MATCH);
             }
             /*
              * Order takes a single decreasing argument that applies to all the vectors. We
@@ -274,7 +273,7 @@ public class SortFunctions {
             for (int i = 0; i < nargs; i++) {
                 byte db = decreasingVec.getDataAt(i);
                 if (RRuntime.isNA(db)) {
-                    throw RError.error(this, RError.Message.RADIX_SORT_DEC_NOT_LOGICAL);
+                    throw error(RError.Message.RADIX_SORT_DEC_NOT_LOGICAL);
                 }
                 if (lastdb != RRuntime.LOGICAL_NA && db != lastdb) {
                     throw RError.nyi(this, "radixsort: args > 1 with differing 'decreasing' values not implemented");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
index 1a47d84f96..cb0c9bd89a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
@@ -114,7 +114,7 @@ public abstract class Sprintf extends RBuiltinNode {
             if (Math.floor(x) == x) {
                 return format(fmt, (long) x);
             }
-            throw RError.error(this, RError.Message.INVALID_FORMAT_DOUBLE, fmt);
+            throw error(RError.Message.INVALID_FORMAT_DOUBLE, fmt);
         }
         return format(fmt, x);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
index 9ca4d012ee..ab924501ec 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
@@ -67,12 +67,8 @@ public abstract class StandardGeneric extends RBuiltinNode {
     @Child private CollectGenericArgumentsNode collectArgumentsNode;
     @Child private DispatchGeneric dispatchGeneric = DispatchGenericNodeGen.create();
 
-    @Child private CastNode castIntScalar;
-    @Child private CastNode castStringScalar;
-    {
-        castIntScalar = newCastBuilder().asIntegerVector().findFirst(RRuntime.INT_NA).buildCastNode();
-        castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
-    }
+    @Child private CastNode castIntScalar = newCastBuilder(null).asIntegerVector().findFirst(RRuntime.INT_NA).buildCastNode();
+    @Child private CastNode castStringScalar = newCastBuilder(null).asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
 
     private final BranchProfile noGenFunFound = BranchProfile.create();
     private final ConditionProfile sameNamesProfile = ConditionProfile.createBinaryProfile();
@@ -82,7 +78,7 @@ public abstract class StandardGeneric extends RBuiltinNode {
         casts.arg("f").defaultError(RError.Message.GENERIC, "argument to 'standardGeneric' must be a non-empty character string").mustBe(
                         stringValue()).asStringVector().findFirst().mustBe(lengthGt(0));
         Function<Object, Object> argClass = ClassHierarchyScalarNode::get;
-        casts.arg("fdef").defaultError(RError.SHOW_CALLER, RError.Message.EXPECTED_GENERIC, argClass).allowMissing().asAttributable(true, true, true).mustBe(instanceOf(RFunction.class));
+        casts.arg("fdef").defaultError(RError.Message.EXPECTED_GENERIC, argClass).allowMissing().asAttributable(true, true, true).mustBe(instanceOf(RFunction.class));
     }
 
     private Object stdGenericInternal(VirtualFrame frame, String fname, RFunction fdef) {
@@ -99,7 +95,7 @@ public abstract class StandardGeneric extends RBuiltinNode {
         RList sigArgs = (RList) readSigARgs.execute(null, fnFrame);
         int sigLength = (int) castIntScalar.execute(readSigLength.execute(null, fnFrame));
         if (sigLength > sigArgs.getLength()) {
-            throw RError.error(this, RError.Message.GENERIC, "'.SigArgs' is shorter than '.SigLength' says it should be");
+            throw error(RError.Message.GENERIC, "'.SigArgs' is shorter than '.SigLength' says it should be");
         }
         if (collectArgumentsNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -173,6 +169,6 @@ public abstract class StandardGeneric extends RBuiltinNode {
                 return fnObj;
             }
         }
-        throw RError.error(this, RError.Message.STD_GENERIC_WRONG_CALL, fname);
+        throw error(RError.Message.STD_GENERIC_WRONG_CALL, fname);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
index 32242b09d4..37fc9f60f7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
@@ -43,7 +43,7 @@ public class StartsEndsWithFunctions {
         private final ConditionProfile singlePrefixProfile = ConditionProfile.createBinaryProfile();
 
         private static void argCast(Casts casts, String name) {
-            casts.arg(name).mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.NON_CHARACTER_OBJECTS).asStringVector();
+            casts.arg(name).mustBe(stringValue(), RError.Message.NON_CHARACTER_OBJECTS).asStringVector();
         }
 
         protected static Casts createCasts(Class<? extends Adapter> extCls) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
index 6710bae7b4..262d39af1b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
@@ -67,7 +67,7 @@ public abstract class Strrep extends RBuiltinNode {
                 data[i] = RRuntime.STRING_NA;
             } else {
                 if (times < 0) {
-                    throw RError.error(this, RError.Message.INVALID_VALUE, "times");
+                    throw error(RError.Message.INVALID_VALUE, "times");
                 }
                 if (times == 1) {
                     data[i] = x;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
index 9fb1980325..66943ed06e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
@@ -50,13 +50,13 @@ public abstract class Strtrim extends RBuiltinNode {
         int nw = width.getLength();
         if (nw == 0 || nw < len && (len % nw != 0)) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "width");
+            throw error(RError.Message.INVALID_ARGUMENT, "width");
         }
         for (int i = 0; i < nw; i++) {
             assert RRuntime.INT_NA < 0; // check for NA folded into < 0
             if (width.getDataAt(i) < 0) {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "width");
+                throw error(RError.Message.INVALID_ARGUMENT, "width");
             }
         }
         BiFunction<String, Integer, String> function = (element, i) -> {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
index b55b50f943..a69ab8d054 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
@@ -140,7 +140,7 @@ public abstract class Substr extends RBuiltinNode {
 
     protected boolean wrongParams(RAbstractIntVector start, RAbstractIntVector stop) {
         if (start.getLength() == 0 || stop.getLength() == 0) {
-            throw RError.error(this, RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring");
+            throw error(RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring");
         }
         return false;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
index d1af871ffb..805cf422b4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
@@ -66,7 +66,7 @@ public abstract class Switch extends RBuiltinNode {
     @Specialization
     protected Object doSwitch(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) {
         if (x.getLength() != 1) {
-            throw RError.error(this, RError.Message.EXPR_NOT_LENGTH_ONE);
+            throw error(RError.Message.EXPR_NOT_LENGTH_ONE);
         }
         return prepareResult(frame, doSwitchString(frame, x, optionalArgs));
     }
@@ -116,7 +116,7 @@ public abstract class Switch extends RBuiltinNode {
                 suppliedArgNameIsNull.enter();
                 Object optionalArg = optionalArgValues[i];
                 if (currentDefaultProfile.profile(currentDefault != null)) {
-                    throw RError.error(this, RError.Message.DUPLICATE_SWITCH_DEFAULT, deparseDefault(currentDefault), deparseDefault(optionalArg));
+                    throw error(RError.Message.DUPLICATE_SWITCH_DEFAULT, deparseDefault(currentDefault), deparseDefault(optionalArg));
                 } else {
                     currentDefault = optionalArg;
                 }
@@ -162,7 +162,7 @@ public abstract class Switch extends RBuiltinNode {
     @Specialization
     protected Object doSwitch(RMissing x, RMissing optionalArgs) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.EXPR_MISSING);
+        throw error(RError.Message.EXPR_MISSING);
     }
 
     private Object doSwitchInt(VirtualFrame frame, int index, RArgsValuesAndNames optionalArgs) {
@@ -176,7 +176,7 @@ public abstract class Switch extends RBuiltinNode {
             if (value != null) {
                 return value;
             }
-            throw RError.error(this, RError.Message.NO_ALTERNATIVE_IN_SWITCH);
+            throw error(RError.Message.NO_ALTERNATIVE_IN_SWITCH);
         }
         return null;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
index cc35e6facb..79b06579bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
@@ -172,7 +172,7 @@ public class SysFunctions {
         @Specialization
         protected RLogicalVector doSysSetEnv(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values) {
             if (names.getLength() != values.getLength()) {
-                throw RError.error(this, RError.Message.ARGUMENT_WRONG_LENGTH);
+                throw error(RError.Message.ARGUMENT_WRONG_LENGTH);
             }
             checkNSLoad(frame, names, values, true);
             return doSysSetEnv(names, values);
@@ -297,7 +297,7 @@ public class SysFunctions {
             Casts casts = new Casts(SysChmod.class);
             casts.arg("paths").mustBe(stringValue());
             casts.arg("octmode").asIntegerVector().mustBe(notEmpty(), RError.Message.MODE_LENGTH_ONE);
-            casts.arg("use_umask").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("use_umask").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -375,7 +375,7 @@ public class SysFunctions {
         static {
             Casts casts = new Casts(SysGlob.class);
             casts.arg("paths").mustBe(stringValue()).asStringVector();
-            casts.arg("dirmask").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("dirmask").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -404,7 +404,7 @@ public class SysFunctions {
         static {
             Casts casts = new Casts(SysSetFileTime.class);
             casts.arg("path").mustBe(stringValue()).asStringVector().findFirst();
-            casts.arg("time").asIntegerVector().findFirst().notNA();
+            casts.arg("time").asIntegerVector().findFirst().mustNotBeNA();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
index bbe48d983e..7aacea27ab 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
@@ -32,8 +32,8 @@ public abstract class Tabulate extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Tabulate.class);
-        casts.arg("bin").defaultError(RError.NO_CALLER, RError.Message.INVALID_INPUT).mustBe(integerValue()).asIntegerVector();
-        casts.arg("nbins").defaultError(RError.NO_CALLER, RError.Message.INVALID_ARGUMENT, "nbin").asIntegerVector().findFirst().mustBe(gte(0));
+        casts.arg("bin").defaultError(RError.Message.INVALID_INPUT).mustBe(integerValue()).asIntegerVector();
+        casts.arg("nbins").defaultError(RError.Message.INVALID_ARGUMENT, "nbin").asIntegerVector().findFirst().mustBe(gte(0));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
index 2bb1e17c5c..6140aefe45 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
@@ -43,9 +43,9 @@ public abstract class TempFile extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(TempFile.class);
-        casts.arg("pattern").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_FILENAME_PATTERN).mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.NO, "pattern");
-        casts.arg("tempdir").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "tempdir").findFirst(RError.SHOW_CALLER, RError.Message.NO, "tempdir");
-        casts.arg("fileext").asVector().mustBe(stringValue(), RError.SHOW_CALLER, RError.Message.INVALID_FILE_EXT).mustBe(notEmpty(), RError.SHOW_CALLER, RError.Message.NO, "fileext");
+        casts.arg("pattern").asVector().mustBe(stringValue(), RError.Message.INVALID_FILENAME_PATTERN).mustBe(notEmpty(), RError.Message.NO, "pattern");
+        casts.arg("tempdir").asVector().mustBe(stringValue(), RError.Message.INVALID_VALUE, "tempdir").findFirst(RError.Message.NO, "tempdir");
+        casts.arg("fileext").asVector().mustBe(stringValue(), RError.Message.INVALID_FILE_EXT).mustBe(notEmpty(), RError.Message.NO, "fileext");
     }
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
index 5521a01b4d..c14e83f92a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
@@ -27,7 +27,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
@@ -71,7 +70,7 @@ public class TraceFunctions {
 
         protected static Casts createCasts(Class<? extends PrimTraceAdapter> extCls) {
             Casts casts = new Casts(extCls);
-            casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), SHOW_CALLER, Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(),
+            casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(),
                             chain(asStringVector()).with(findFirst().stringElement()).end());
             return casts;
         }
@@ -103,7 +102,7 @@ public class TraceFunctions {
             if (!func.isBuiltin()) {
                 TraceHandling.enableTrace(func);
             } else {
-                throw RError.error(this, RError.Message.GENERIC, "builtin functions cannot be traced");
+                throw error(RError.Message.GENERIC, "builtin functions cannot be traced");
             }
             return RNull.instance;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index a234a6ce6d..b75bd4453b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -161,6 +160,6 @@ public abstract class Transpose extends RBuiltinNode {
 
     @Fallback
     protected RVector<?> transpose(@SuppressWarnings("unused") Object x) {
-        throw RError.error(RError.SHOW_CALLER, Message.ARGUMENT_NOT_MATRIX);
+        throw error(Message.ARGUMENT_NOT_MATRIX);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index 9839f2e54c..e310690641 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -307,7 +307,7 @@ public class TrigExpFunctions {
 
         @Override
         public RComplex op(double re, double im) {
-            throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX_FUN);
+            throw error(RError.Message.UNIMPLEMENTED_COMPLEX_FUN);
         }
     }
 
@@ -571,7 +571,7 @@ public class TrigExpFunctions {
             if (x instanceof RAbstractComplexVector || y instanceof RAbstractComplexVector) {
                 throw RInternalError.unimplemented("atan2 for complex values");
             }
-            throw RError.error(this, RError.Message.NON_NUMERIC_MATH);
+            throw error(RError.Message.NON_NUMERIC_MATH);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
index 9b4faf6eaf..32488e0035 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
@@ -73,7 +73,7 @@ public abstract class Unique extends RBuiltinNode {
     static {
         Casts casts = new Casts(Unique.class);
         // these are similar to those in DuplicatedFunctions.java
-        casts.arg("x").defaultError(RError.SHOW_CALLER, RError.Message.APPLIES_TO_VECTORS, "unique()").allowNull().mustBe(abstractVectorValue()).asVector();
+        casts.arg("x").defaultError(RError.Message.APPLIES_TO_VECTORS, "unique()").allowNull().mustBe(abstractVectorValue()).asVector();
         // not much more can be done for incomparables as it is either a vector of incomparable
         // values or a (single) logical value
         // TODO: coercion error must be handled by specialization as it depends on type of x (much
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index aa74c71def..24ed77fce4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.MUST_BE_NONNULL_STRING;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -34,7 +33,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
@@ -64,8 +62,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 @RBuiltin(name = "attr<-", kind = PRIMITIVE, parameterNames = {"x", "which", "value"}, behavior = PURE)
 public abstract class UpdateAttr extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     @Child private UpdateNames updateNames;
     @Child private UpdateDimNames updateDimNames;
     @Child private CastIntegerNode castInteger;
@@ -100,7 +96,7 @@ public abstract class UpdateAttr extends RBuiltinNode {
         // Note: cannot check 'attributability' easily because atomic values, e.g int, are not
         // RAttributable.
         casts.arg("x"); // disallows null
-        casts.arg("which").defaultError(SHOW_CALLER, MUST_BE_NONNULL_STRING, "name").mustBe(stringValue()).asStringVector().findFirst();
+        casts.arg("which").defaultError(MUST_BE_NONNULL_STRING, "name").mustBe(stringValue()).asStringVector().findFirst();
     }
 
     private RAbstractContainer updateNames(RAbstractContainer container, Object o) {
@@ -191,8 +187,7 @@ public abstract class UpdateAttr extends RBuiltinNode {
         if (internedName == RRuntime.DIM_ATTR_KEY) {
             RAbstractIntVector dimsVector = castInteger(castVector(value));
             if (dimsVector.getLength() == 0) {
-                errorProfile.enter();
-                throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID);
+                throw error(RError.Message.LENGTH_ZERO_DIM_INVALID);
             }
             if (setDimNode == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 8ec7de0523..7bcf40f60e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -129,7 +129,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
                     @Cached("create()") GetNonSharedNode nonShared) {
         Object listNamesObject = getNamesNode.getNames(list);
         if (listNamesObject == null || listNamesObject == RNull.instance) {
-            throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
+            throw error(RError.Message.ATTRIBUTES_NAMED);
         }
         RStringVector listNames = (RStringVector) listNamesObject;
         RAbstractContainer result = ((RAbstractContainer) nonShared.execute(container)).materialize();
@@ -144,7 +144,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
             }
             // has to be reported if no other name is undefined
             if (listNames.getDataAt(0).equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)) {
-                throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE);
+                throw error(RError.Message.ZERO_LENGTH_VARIABLE);
             }
             // set the dim attribute first
             setDimAttribute(result, list);
@@ -162,7 +162,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
         for (int i = 1; i < length; i++) {
             String attrName = listNames.getDataAt(i);
             if (attrName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)) {
-                throw RError.error(this, RError.Message.ALL_ATTRIBUTES_NAMES, i + 1);
+                throw error(RError.Message.ALL_ATTRIBUTES_NAMES, i + 1);
             }
         }
     }
@@ -186,7 +186,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
                 } else {
                     RAbstractIntVector dimsVector = castInteger(castVector(value));
                     if (dimsVector.getLength() == 0) {
-                        throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID);
+                        throw error(RError.Message.LENGTH_ZERO_DIM_INVALID);
                     }
                     setDimNode.setDimensions(result, dimsVector.materialize().getDataCopy());
                 }
@@ -261,17 +261,17 @@ public abstract class UpdateAttributes extends RBuiltinNode {
             RList list = (RList) operand;
             RStringVector listNames = list.getNames();
             if (listNames == null) {
-                throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
+                throw error(RError.Message.ATTRIBUTES_NAMED);
             }
             for (int i = 0; i < list.getLength(); i++) {
                 String attrName = listNames.getDataAt(i);
                 if (attrName == null) {
-                    throw RError.error(this, RError.Message.ATTRIBUTES_NAMED);
+                    throw error(RError.Message.ATTRIBUTES_NAMED);
                 }
                 if (RRuntime.CLASS_ATTR_KEY.equals(attrName)) {
                     Object attrValue = list.getDataAt(i);
                     if (attrValue == null) {
-                        throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR);
+                        throw error(RError.Message.SET_INVALID_CLASS_ATTR);
                     }
                     attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
                 } else {
@@ -284,7 +284,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
 
     private void checkAttributable(Object obj) {
         if (!(obj instanceof RAttributable)) {
-            throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index 7fd8850a96..20f38f2b25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -106,14 +106,14 @@ public abstract class UpdateClass extends RBuiltinNode {
                 }
                 CompilerDirectives.transferToInterpreter();
                 int[] dimensions = resultVector.getDimensions();
-                throw RError.error(this, RError.Message.NOT_A_MATRIX_UPDATE_CLASS, dimensions == null ? 0 : dimensions.length);
+                throw error(RError.Message.NOT_A_MATRIX_UPDATE_CLASS, dimensions == null ? 0 : dimensions.length);
             }
             if (RType.Array.getName().equals(className)) {
                 if (resultVector.isArray()) {
                     return setClass(resultVector, RNull.instance);
                 }
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.NOT_ARRAY_UPDATE_CLASS);
+                throw error(RError.Message.NOT_ARRAY_UPDATE_CLASS);
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index 6b63fbccde..c0f0bca8f3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -121,6 +121,6 @@ public abstract class UpdateDimNames extends RBuiltinNode {
     @Specialization(guards = "!isRList(c)")
     protected RAbstractContainer updateDimnamesError(@SuppressWarnings("unused") RAbstractContainer container, @SuppressWarnings("unused") Object c) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.DIMNAMES_LIST);
+        throw error(RError.Message.DIMNAMES_LIST);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
index fd018457e0..95f8752c97 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
@@ -20,7 +20,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -67,6 +66,6 @@ public abstract class UpdateLevels extends RBuiltinNode {
 
     @Specialization(guards = "!isRNull(levels)")
     protected RAbstractVector updateLevels(@SuppressWarnings("unused") RNull vector, @SuppressWarnings("unused") Object levels) {
-        throw RError.error(this, Message.SET_ATTRIBUTES_ON_NULL);
+        throw error(Message.SET_ATTRIBUTES_ON_NULL);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
index 0a619c54c7..d1ab1ea7f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
@@ -34,7 +34,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -82,7 +81,7 @@ public abstract class UpdateNames extends RBuiltinNode {
         if (stringVector.getLength() < result.getLength()) {
             stringVector = (RStringVector) stringVector.copyResized(result.getLength(), true);
         } else if (stringVector.getLength() > result.getLength()) {
-            throw RError.error(this, Message.NAMES_LONGER, stringVector.getLength(), result.getLength());
+            throw error(Message.NAMES_LONGER, stringVector.getLength(), result.getLength());
         } else if (stringVector == names) {
             stringVector = (RStringVector) stringVector.copy();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
index 9dcc170b84..97584d822e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
@@ -77,11 +77,11 @@ public abstract class UpdateSlot extends RBuiltinNode {
         } else if (rep instanceof ReadVariableNode) {
             return ((ReadVariableNode) rep).getIdentifier();
         } else if (rep instanceof RCallNode) {
-            throw RError.error(this, RError.Message.SLOT_INVALID_TYPE, "language");
+            throw error(RError.Message.SLOT_INVALID_TYPE, "language");
         }
         // TODO: this is not quite correct, but I wonder if we even reach here (can also be
         // augmented on demand)
-        throw RError.error(this, RError.Message.SLOT_INVALID_TYPE, nameObj.getClass().toString());
+        throw error(RError.Message.SLOT_INVALID_TYPE, nameObj.getClass().toString());
     }
 
     private void checkSlotAssign(VirtualFrame frame, Object object, String name, Object value) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
index 6901189972..0b45cc5ea9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
@@ -18,7 +18,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
@@ -49,8 +48,6 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
     @Child private IsFactorNode isFactor;
     @Child private SetClassAttributeNode setClassAttrNode;
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     static {
         Casts.noCasts(UpdateStorageMode.class);
     }
@@ -61,8 +58,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
                     @Cached("create()") SetAttributeNode setAttrNode) {
         RType mode = typeFromMode.execute(value);
         if (mode == RType.DefunctReal || mode == RType.DefunctSingle) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.USE_DEFUNCT, mode.getName(), mode == RType.DefunctSingle ? "mode<-" : "double");
+            throw error(RError.Message.USE_DEFUNCT, mode.getName(), mode == RType.DefunctSingle ? "mode<-" : "double");
         }
         initTypeOfNode();
         RType typeX = typeof.execute(x);
@@ -71,8 +67,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
         }
         initFactorNode();
         if (isFactor.executeIsFactor(x)) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.INVALID_STORAGE_MODE_UPDATE);
+            throw error(RError.Message.INVALID_STORAGE_MODE_UPDATE);
         }
         initCastTypeNode();
         if (mode != null) {
@@ -108,8 +103,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
                 return result;
             }
         }
-        errorProfile.enter();
-        throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE);
+        throw error(RError.Message.INVALID_UNNAMED_VALUE);
     }
 
     private void initCastTypeNode() {
@@ -137,6 +131,6 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
     @Specialization
     protected Object update(Object x, Object value) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.MUST_BE_NONNULL_STRING, "value");
+        throw error(RError.Message.MUST_BE_NONNULL_STRING, "value");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
index 0211c6ed55..b5955ec823 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
@@ -109,14 +109,14 @@ public abstract class UpdateSubstr extends RBuiltinNode {
     @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)"})
     @TruffleBoundary
     protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RNull value) {
-        throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE);
+        throw error(RError.Message.INVALID_UNNAMED_VALUE);
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "wrongValue(value)"})
     protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RAbstractVector value) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.INVALID_UNNAMED_VALUE);
+        throw error(RError.Message.INVALID_UNNAMED_VALUE);
     }
 
     @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "!wrongValue(value)"})
@@ -149,7 +149,7 @@ public abstract class UpdateSubstr extends RBuiltinNode {
 
     protected boolean wrongParams(RAbstractIntVector start, RAbstractIntVector stop) {
         if (start.getLength() == 0 || stop.getLength() == 0) {
-            throw RError.error(this, RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring");
+            throw error(RError.Message.INVALID_ARGUMENTS_NO_QUOTE, "substring");
         }
         return false;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
index 50aa92742d..52001186a8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
@@ -41,8 +41,8 @@ public abstract class Utf8ToInt extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Utf8ToInt.class);
-        casts.arg(0, "x").defaultError(RError.SHOW_CALLER, RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE, "x").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(size(1),
-                        RError.SHOW_CALLER, RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE).findFirst();
+        casts.arg(0, "x").defaultError(RError.Message.ARG_MUST_BE_CHARACTER_VECTOR_LENGTH_ONE, "x").mustBe(stringValue()).asStringVector().mustBe(notEmpty()).shouldBe(size(1),
+                        RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE).findFirst();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index 033f63f94e..48fae23d07 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notLogicalNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
@@ -98,14 +97,11 @@ public abstract class VApply extends RBuiltinNode {
     @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
     static {
-        // @formatter:off
         Casts casts = new Casts(VApply.class);
         casts.arg("X").mapNull(emptyList());
-        casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION);
-        casts.arg("FUN.VALUE").defaultError(RError.SHOW_CALLER, RError.Message.MUST_BE_VECTOR, "FUN.VALUE").mustBe(abstractVectorValue()).asVector(true);
-        casts.arg("USE.NAMES").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_VALUE, "USE.NAMES").
-                mustBe(numericValue()).asLogicalVector().findFirst().mustBe(notLogicalNA()).map(toBoolean());
-        // @formatter:on
+        casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.APPLY_NON_FUNCTION);
+        casts.arg("FUN.VALUE").defaultError(RError.Message.MUST_BE_VECTOR, "FUN.VALUE").mustBe(abstractVectorValue()).asVector(true);
+        casts.arg("USE.NAMES").defaultError(RError.Message.INVALID_VALUE, "USE.NAMES").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     private Object castComplex(Object operand, boolean preserveAllAttr) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
index ee217670d4..001e65fd2c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
@@ -46,14 +46,14 @@ public abstract class Vector extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Vector.class);
-        casts.arg("mode").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "mode").asStringVector().mustBe(singleElement()).findFirst();
-        casts.arg("length").defaultError(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "length").asIntegerVector().mustBe(singleElement()).findFirst();
+        casts.arg("mode").defaultError(RError.Message.INVALID_ARGUMENT, "mode").asStringVector().mustBe(singleElement()).findFirst();
+        casts.arg("length").defaultError(RError.Message.INVALID_ARGUMENT, "length").asIntegerVector().mustBe(singleElement()).findFirst();
     }
 
     protected RType modeToType(String mode) {
         RType type = typeFromMode.execute(mode);
         if (type != RType.PairList && !type.isVector()) {
-            throw RError.error(this, RError.Message.CANNOT_MAKE_VECTOR_OF_MODE, mode);
+            throw error(RError.Message.CANNOT_MAKE_VECTOR_OF_MODE, mode);
         }
         return type;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
index fa52a36dfc..4db217cd40 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
@@ -87,7 +87,7 @@ public abstract class WithVisible extends RBuiltinNode {
         Object value = promiseHelper.evaluate(frame, x);
         if (value == RMissing.instance) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, Message.ARGUMENT_MISSING, "x");
+            throw error(Message.ARGUMENT_MISSING, "x");
         }
         return RDataFactory.createList(new Object[]{value, RRuntime.asLogical(visibility.execute(frame))}, LISTNAMES);
     }
@@ -99,6 +99,6 @@ public abstract class WithVisible extends RBuiltinNode {
     @Specialization
     protected RList withVisible(@SuppressWarnings("unused") RMissing x) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, Message.ARGUMENT_MISSING, "x");
+        throw error(Message.ARGUMENT_MISSING, "x");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 1eae282329..396a987bbe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -61,7 +61,7 @@ import com.oracle.truffle.r.library.tools.DirChmodNodeGen;
 import com.oracle.truffle.r.library.tools.Rmd5NodeGen;
 import com.oracle.truffle.r.library.tools.ToolsTextFactory.CodeFilesAppendNodeGen;
 import com.oracle.truffle.r.library.tools.ToolsTextFactory.DoTabExpandNodeGen;
-import com.oracle.truffle.r.library.utils.CountFields;
+import com.oracle.truffle.r.library.utils.CountFieldsNodeGen;
 import com.oracle.truffle.r.library.utils.Crc64NodeGen;
 import com.oracle.truffle.r.library.utils.DownloadNodeGen;
 import com.oracle.truffle.r.library.utils.MenuNodeGen;
@@ -706,7 +706,7 @@ public class CallAndExternalFunctions {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName);
+                throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName);
             }
             return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), args.getArguments());
         }
@@ -750,7 +750,7 @@ public class CallAndExternalFunctions {
                     return new CompleteCases();
                 // utils
                 case "countfields":
-                    return new CountFields();
+                    return CountFieldsNodeGen.create();
                 case "readtablehead":
                     return ReadTableHeadNodeGen.create();
                 case "download":
@@ -811,7 +811,7 @@ public class CallAndExternalFunctions {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External", packageName);
+                throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External", packageName);
             }
             Object list = encodeArgumentPairList(args, symbol);
             return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), new Object[]{list});
@@ -893,7 +893,7 @@ public class CallAndExternalFunctions {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External2", packageName);
+                throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External2", packageName);
             }
             Object list = encodeArgumentPairList(args, symbol);
             // TODO: provide proper values for the CALL, OP and RHO parameters
@@ -957,7 +957,7 @@ public class CallAndExternalFunctions {
             DLL.SymbolHandle func = findSymbolNode.execute(name, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name);
+                throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, name);
             }
             Object list = encodeArgumentPairList(args, name);
             return callRFFINode.execute(new NativeCallInfo(name, func, rns.getDllInfo()), new Object[]{list});
@@ -1020,7 +1020,7 @@ public class CallAndExternalFunctions {
             DLL.SymbolHandle func = findSymbolNode.execute(name, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name);
+                throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, name);
             }
             return callRFFINode.execute(new NativeCallInfo(name, func, rns.getDllInfo()), args.getArguments());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
index 3ef382aa94..93d2a21472 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
@@ -70,8 +70,7 @@ public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 {
             return RDataFactory.createList(data, DQRCF_NAMES);
 
         } catch (ClassCastException | ArrayIndexOutOfBoundsException ex) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.INCORRECT_ARG, "dqrcf");
+            throw error(RError.Message.INCORRECT_ARG, "dqrcf");
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
index 9ccae9e8ae..401b82d01e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java
@@ -53,8 +53,7 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 {
                 int n = zVec.getLength();
                 factorNode.execute(n, maxf, maxp);
                 if (maxf[0] == 0) {
-                    errorProfile.enter();
-                    throw RError.error(this, RError.Message.FFT_FACTORIZATION);
+                    throw error(RError.Message.FFT_FACTORIZATION);
                 }
                 double[] work = new double[4 * maxf[0]];
                 int[] iwork = new int[maxp[0]];
@@ -68,8 +67,7 @@ public abstract class Fft extends RExternalBuiltinNode.Arg2 {
                     if (d[i] > 1) {
                         factorNode.execute(d[i], maxf, maxp);
                         if (maxf[0] == 0) {
-                            errorProfile.enter();
-                            throw RError.error(this, RError.Message.FFT_FACTORIZATION);
+                            throw error(RError.Message.FFT_FACTORIZATION);
                         }
                         if (maxf[0] > maxmaxf) {
                             maxmaxf = maxf[0];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
index d3d6625fa2..e0f6af2d15 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
@@ -107,7 +107,7 @@ public class FortranAndCFunctions {
                     argTypes[i] = SCALAR_LOGICAL;
                     nativeArgs[i] = checkNAs(node, i + 1, new int[]{RRuntime.isNA((byte) arg) ? RRuntime.INT_NA : (byte) arg});
                 } else {
-                    throw RError.error(node, RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1);
+                    throw node.error(RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1);
                 }
             }
             invokeCNode.execute(nativeCallInfo, nativeArgs);
@@ -156,7 +156,7 @@ public class FortranAndCFunctions {
             CompilerAsserts.neverPartOfCompilation();
             for (int i = 0; i < data.length; i++) {
                 if (RRuntime.isNA(data[i])) {
-                    throw RError.error(node, RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex);
+                    throw node.error(RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex);
                 }
             }
             return data;
@@ -166,7 +166,7 @@ public class FortranAndCFunctions {
             CompilerAsserts.neverPartOfCompilation();
             for (int i = 0; i < data.length; i++) {
                 if (!RRuntime.isFinite(data[i])) {
-                    throw RError.error(node, RError.Message.NA_NAN_INF_IN_FOREIGN_FUNCTION_CALL, argIndex);
+                    throw node.error(RError.Message.NA_NAN_INF_IN_FOREIGN_FUNCTION_CALL, argIndex);
                 }
             }
             return data;
@@ -233,7 +233,7 @@ public class FortranAndCFunctions {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol);
+                throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol);
             }
             return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args);
         }
@@ -275,14 +275,14 @@ public class FortranAndCFunctions {
                 libName = RRuntime.asString(rPackage);
                 if (libName == null) {
                     errorProfile.enter();
-                    throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
+                    throw error(RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
                 }
             }
             DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.C, null, null);
             DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol);
+                throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol);
             }
             return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index e71e6060a3..8eb161fc90 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -133,7 +133,7 @@ abstract class LookupAdapter extends RBuiltinNode {
             libName = RRuntime.asString(rPackage);
             if (libName == null) {
                 errorProfile.enter();
-                throw RError.error(this, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
+                throw error(RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
             }
         }
         return libName;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
index 71b34f1465..aa4b0da4d8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
@@ -38,8 +38,7 @@ public abstract class ReadTableHead extends RExternalBuiltinNode.Arg7 {
         try (RConnection openConn = RConnection.fromIndex(con).forceOpen("r")) {
             return RDataFactory.createStringVector(openConn.readLines(nlines, true, false), RDataFactory.COMPLETE_VECTOR);
         } catch (IOException ex) {
-            errorProfile.enter();
-            throw RError.error(this, RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
+            throw error(RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
index 3dda72b068..f03b6574e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
@@ -55,9 +55,9 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         // file
         casts.arg(1).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         // nrows
-        casts.arg(2).mustNotBeNull().asIntegerVector().findFirst().notNA();
+        casts.arg(2).mustNotBeNull().asIntegerVector().findFirst().mustNotBeNA();
         // nc
-        casts.arg(3).mustNotBeNull().asIntegerVector().findFirst().notNA();
+        casts.arg(3).mustNotBeNull().asIntegerVector().findFirst().mustNotBeNA();
         // rnames
         casts.arg(4).allowNull().mustBe(stringValue()).asStringVector();
         // sep
@@ -71,7 +71,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         // quote
         casts.arg(9).mustNotBeMissing().mustBe(nullValue().not()).asIntegerVector();
         // qmethod
-        casts.arg(10).mustNotBeNull().asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg(10).mustNotBeNull().asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     // Transcribed from GnuR, library/utils/src/io.c
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
index d89fdf7ecc..c1677176ce 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
@@ -103,7 +103,7 @@ public abstract class AccessField extends RBuiltinNode {
     protected Object access(VirtualFrame frame, Object container, String field) {
         if (!invalidAtomicVector.profile(container instanceof RAbstractListVector) && container instanceof RAbstractVector) {
             error.enter();
-            throw RError.error(this, RError.Message.DOLLAR_ATOMIC_VECTORS);
+            throw error(RError.Message.DOLLAR_ATOMIC_VECTORS);
         }
         return extract.applyAccessField(frame, container, field);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index f99feb45d8..daf9a1dac7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -223,13 +223,13 @@ public abstract class Subscript extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization(guards = "indexes.isEmpty()")
     protected Object getNoInd(Object x, RArgsValuesAndNames indexes, RAbstractLogicalVector exact, RAbstractLogicalVector drop) {
-        throw RError.error(this, RError.Message.NO_INDEX);
+        throw error(RError.Message.NO_INDEX);
     }
 
     @SuppressWarnings("unused")
     @Specialization
     protected Object get(Object x, RMissing indexes, RAbstractLogicalVector exact, RAbstractLogicalVector drop) {
-        throw RError.error(this, RError.Message.NO_INDEX);
+        throw error(RError.Message.NO_INDEX);
     }
 
     @Specialization(guards = "!indexes.isEmpty()")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
index d2d7c567ba..12835f2b47 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
@@ -123,7 +123,7 @@ public abstract class UpdateField extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(UpdateField.class);
-        casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue(), RError.NO_CALLER, Message.INVALID_SUBSCRIPT_TYPE, Predef.typeName()).asStringVector().findFirst();
+        casts.arg(1).defaultError(Message.INVALID_SUBSCRIPT).mustBe(stringValue(), Message.INVALID_SUBSCRIPT_TYPE, Predef.typeName()).asStringVector().findFirst();
     }
 
     public static RNode createSpecial(ArgumentsSignature signature, RNode[] arguments, @SuppressWarnings("unused") boolean inReplacement) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index 80d27c0f38..3eb7a8278f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -199,6 +199,6 @@ public abstract class UpdateSubscript extends RBuiltinNode {
     @Specialization(guards = "args.isEmpty()")
     @SuppressWarnings("unused")
     protected Object getNoInd(Object x, RArgsValuesAndNames args) {
-        throw RError.error(this, RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs");
+        throw error(RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 98021bea82..51f38ff79a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -84,6 +84,6 @@ public abstract class UpdateSubset extends RBuiltinNode {
     @Specialization(guards = "args.isEmpty()")
     @SuppressWarnings("unused")
     protected Object getNoInd(Object x, RArgsValuesAndNames args) {
-        throw RError.error(this, RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs");
+        throw error(RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
index ad08dd85ae..5d0ab412d0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
@@ -42,7 +42,7 @@ public abstract class SystemFunction extends RBuiltinNode {
     static {
         Casts casts = new Casts(SystemFunction.class);
         casts.arg("command").mustBe(stringValue(), RError.Message.SYSTEM_CHAR_ARG).asStringVector().findFirst();
-        casts.arg("intern").asLogicalVector().findFirst().notNA(RError.Message.SYSTEM_INTERN_NOT_NA).map(toBoolean());
+        casts.arg("intern").asLogicalVector().findFirst().mustNotBeNA(RError.Message.SYSTEM_INTERN_NOT_NA).map(toBoolean());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 4086dcad74..f05e725df8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -66,12 +66,12 @@ public class FastRContext {
         }
 
         private static void kind(Casts casts) {
-            casts.arg("kind").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().notNA().mustBe(
+            casts.arg("kind").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustNotBeNA().mustBe(
                             equalTo(RContext.ContextKind.SHARE_NOTHING.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RW.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RO.name()))));
         }
 
         private static void pc(Casts casts) {
-            casts.arg("pc").asIntegerVector().findFirst().notNA().mustBe(gt(0));
+            casts.arg("pc").asIntegerVector().findFirst().mustNotBeNA().mustBe(gt(0));
         }
 
         private static void key(Casts casts) {
@@ -152,7 +152,7 @@ public class FastRContext {
                     }
                 }
             } catch (InterruptedException ex) {
-                throw RError.error(this, RError.Message.GENERIC, "error finishing eval thread");
+                throw error(RError.Message.GENERIC, "error finishing eval thread");
 
             }
             return RNull.instance;
@@ -214,7 +214,7 @@ public class FastRContext {
                         results[i] = threads[i].getEvalResult();
                     }
                 } catch (InterruptedException ex) {
-                    throw RError.error(this, RError.Message.GENERIC, "error finishing eval thread");
+                    throw error(RError.Message.GENERIC, "error finishing eval thread");
                 }
             }
             return RDataFactory.createList(results);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index 16cc34b1b5..90f9307588 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -77,7 +77,7 @@ public class FastRInterop {
             try {
                 return RContext.getInstance().getEnv().parse(sourceObject);
             } catch (Throwable t) {
-                throw RError.error(this, Message.GENERIC, "Error while parsing: " + t.getMessage());
+                throw error(Message.GENERIC, "Error while parsing: " + t.getMessage());
             }
         }
 
@@ -122,9 +122,9 @@ public class FastRInterop {
                 Source sourceObject = sourceBuilder.build();
                 return RContext.getInstance().getEnv().parse(sourceObject);
             } catch (IOException e) {
-                throw RError.error(this, Message.GENERIC, "Error reading file: " + e.getMessage());
+                throw error(Message.GENERIC, "Error reading file: " + e.getMessage());
             } catch (Throwable t) {
-                throw RError.error(this, Message.GENERIC, "Error while parsing: " + t.getMessage());
+                throw error(Message.GENERIC, "Error while parsing: " + t.getMessage());
             }
         }
 
@@ -154,7 +154,7 @@ public class FastRInterop {
         @TruffleBoundary
         protected Object exportSymbol(String name, RTypedValue value) {
             if (name == null) {
-                throw RError.error(this, RError.Message.INVALID_ARG_TYPE, "name");
+                throw error(RError.Message.INVALID_ARG_TYPE, "name");
             }
             RContext.getInstance().getExportedSymbols().put(name, value);
             return RNull.instance;
@@ -163,13 +163,13 @@ public class FastRInterop {
         @Specialization
         @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) {
-            throw RError.error(this, Message.ARGUMENT_MISSING, "value");
+            throw error(Message.ARGUMENT_MISSING, "value");
         }
 
         @Fallback
         @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") Object name, @SuppressWarnings("unused") Object value) {
-            throw RError.error(this, Message.GENERIC, "only R language objects can be exported");
+            throw error(Message.GENERIC, "only R language objects can be exported");
         }
     }
 
@@ -186,7 +186,7 @@ public class FastRInterop {
         protected Object importSymbol(String name) {
             Object object = RContext.getInstance().getEnv().importSymbol(name);
             if (object == null) {
-                throw RError.error(this, RError.Message.NO_IMPORT_OBJECT, name);
+                throw error(RError.Message.NO_IMPORT_OBJECT, name);
             }
             return object;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
index 0a1b33acec..eaa4f18e37 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
@@ -73,7 +73,7 @@ public abstract class FastRPkgSource extends RBuiltinNode {
     static {
         Casts casts = new Casts(FastRPkgSource.class);
         casts.arg("pkgs").allowNull().mustBe(stringValue());
-        casts.arg("verbose").asLogicalVector().findFirst().notNA().map(toBoolean());
+        casts.arg("verbose").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     @Specialization
@@ -136,7 +136,7 @@ public abstract class FastRPkgSource extends RBuiltinNode {
         try {
             StdConnections.getStdout().writeString(msg, nl);
         } catch (IOException ex) {
-            throw RError.error(this, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
     }
 
@@ -151,7 +151,7 @@ public abstract class FastRPkgSource extends RBuiltinNode {
     }
 
     @TruffleBoundary
-    private static void saveSource(String pkg, String fname, String deparseResult) {
+    private void saveSource(String pkg, String fname, String deparseResult) {
         RSerialize.setSaveDeparse(false);
         try {
             Path target = targetPath(pkg, fname);
@@ -159,7 +159,7 @@ public abstract class FastRPkgSource extends RBuiltinNode {
                 wr.write(deparseResult);
             }
         } catch (IOException ex) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage());
+            throw error(RError.Message.GENERIC, ex.getMessage());
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
index 16abbd8f16..fd22a2f70e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
@@ -68,7 +68,7 @@ public class FastRStats {
         }
 
         private static void append(Casts casts) {
-            casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).notNA().map(toBoolean());
+            casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
         }
     }
 
@@ -108,7 +108,7 @@ public class FastRStats {
                     AttributeTracer.addListener(this);
                     AttributeTracer.setTracingState(true);
                 } catch (IOException ex) {
-                    throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
+                    throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
                 }
             }
             return RNull.instance;
@@ -193,7 +193,7 @@ public class FastRStats {
                     RDataFactory.addListener(this);
                     RDataFactory.setTracingState(true);
                 } catch (IOException ex) {
-                    throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
+                    throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
                 }
             }
             return RNull.instance;
@@ -299,9 +299,9 @@ public class FastRStats {
             Casts casts = new Casts(FastRProfFuncounts.class);
             CastsHelper.filename(casts);
             CastsHelper.append(casts);
-            casts.arg("timing").asLogicalVector().findFirst().notNA().map(toBoolean());
-            casts.arg("threshold").asIntegerVector().findFirst().notNA();
-            casts.arg("histograms").asLogicalVector().findFirst().notNA().map(toBoolean());
+            casts.arg("timing").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("threshold").asIntegerVector().findFirst().mustNotBeNA();
+            casts.arg("histograms").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @SuppressWarnings("unused")
@@ -328,7 +328,7 @@ public class FastRStats {
                     profiler.setCollecting(true);
                     profiler.setTiming(timing);
                 } catch (IOException ex) {
-                    throw RError.error(this, RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
+                    throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
                 }
             }
             return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
index 8817ee3bcf..5e1c4403e3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
@@ -161,7 +161,7 @@ public abstract class FastRSyntaxTree extends RBuiltinNode {
                 break;
 
             default:
-                throw RError.error(this, RError.Message.INVALID_ARGUMENT, "visitMode");
+                throw error(RError.Message.INVALID_ARGUMENT, "visitMode");
 
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
index aa63c26945..f1a6f7d4cc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
@@ -63,7 +63,7 @@ public abstract class FastRThrowIt extends RBuiltinNode {
             case "BRQ":
                 throw new JumpToTopLevelException();
             default:
-                throw RError.error(this, RError.Message.GENERIC, "unknown case: " + name);
+                throw error(RError.Message.GENERIC, "unknown case: " + name);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index d29aa74c9b..e719605f9e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -90,7 +90,7 @@ public class FastRTrace {
 
         protected void checkWhat(Object what) {
             if (what == RMissing.instance) {
-                throw RError.error(this, RError.Message.ARGUMENT_MISSING, "what");
+                throw error(RError.Message.ARGUMENT_MISSING, "what");
             }
         }
 
@@ -98,12 +98,12 @@ public class FastRTrace {
             if (what instanceof RFunction) {
                 RFunction func = (RFunction) what;
                 if (func.isBuiltin()) {
-                    throw RError.error(this, RError.Message.GENERIC, "builtin functions cannot be traced");
+                    throw error(RError.Message.GENERIC, "builtin functions cannot be traced");
                 } else {
                     return func;
                 }
             } else {
-                throw RError.error(this, RError.Message.ARG_MUST_BE_CLOSURE);
+                throw error(RError.Message.ARG_MUST_BE_CLOSURE);
             }
         }
     }
@@ -171,7 +171,7 @@ public class FastRTrace {
             } else if (tracerObj instanceof RLanguage) {
                 tracer = (RLanguage) tracerObj;
             } else {
-                throw RError.error(this, RError.Message.GENERIC, "tracer is unexpected type");
+                throw error(RError.Message.GENERIC, "tracer is unexpected type");
             }
             TraceHandling.enableStatementTrace(func, tracer, exit, at, print);
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
index a51b5f5d90..6863e8959d 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
@@ -55,9 +55,9 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustBe;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustNotBeNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
@@ -66,7 +66,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElemen
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -130,7 +129,7 @@ public class CastBuilderTest {
 
     @Before
     public void setUp() {
-        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class), RError.NO_CALLER);
         arg = cb.arg("x");
         castNode = null;
     }
@@ -301,7 +300,7 @@ public class CastBuilderTest {
 
     @Test
     public void testSizeWarning() {
-        arg.defaultWarning(SHOW_CALLER, RError.Message.LENGTH_GT_1).asIntegerVector().shouldBe(singleElement());
+        arg.defaultWarning(RError.Message.LENGTH_GT_1).asIntegerVector().shouldBe(singleElement());
         RIntVector intVector = RDataFactory.createIntVector(new int[]{1, 2}, true);
         assertCastWarning(intVector, intVector, RError.Message.LENGTH_GT_1.message);
         testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES);
@@ -324,7 +323,7 @@ public class CastBuilderTest {
     @Test
     public void testFindFirstWithDefaultError() {
         // findFirst takes the explicitly specified default error from pipeline
-        arg.defaultError(SHOW_CALLER, RError.Message.SEED_NOT_VALID_INT).asIntegerVector().findFirst();
+        arg.defaultError(RError.Message.SEED_NOT_VALID_INT).asIntegerVector().findFirst();
         assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message);
     }
 
@@ -344,7 +343,7 @@ public class CastBuilderTest {
 
     @Test
     public void testNoLogicalNA() {
-        arg.asLogicalVector().findFirst().notNA(RRuntime.LOGICAL_TRUE);
+        arg.asLogicalVector().findFirst().replaceNA(RRuntime.LOGICAL_TRUE);
 
         assertCastPreserves(RRuntime.LOGICAL_FALSE);
         assertEquals(RRuntime.LOGICAL_TRUE, cast(RRuntime.LOGICAL_NA));
@@ -353,7 +352,7 @@ public class CastBuilderTest {
 
     @Test
     public void testNoIntegerNA() {
-        arg.asIntegerVector().findFirst().notNA(1);
+        arg.asIntegerVector().findFirst().replaceNA(1);
 
         assertCastPreserves(42);
         assertEquals(1, cast(RRuntime.INT_NA));
@@ -362,7 +361,7 @@ public class CastBuilderTest {
 
     @Test
     public void testNoDoubleNA() {
-        arg.asDoubleVector().findFirst().notNA(1.1);
+        arg.asDoubleVector().findFirst().replaceNA(1.1);
 
         assertCastPreserves(3.142);
         assertEquals(1.1, cast(RRuntime.DOUBLE_NA));
@@ -371,7 +370,7 @@ public class CastBuilderTest {
 
     @Test
     public void testNoStringNA() {
-        arg.asStringVector().findFirst().notNA("A");
+        arg.asStringVector().findFirst().replaceNA("A");
 
         assertCastPreserves("hello world");
         assertEquals("A", cast(RRuntime.DOUBLE_NA));
@@ -475,7 +474,7 @@ public class CastBuilderTest {
             mapIf(instanceOf(RList.class).not(),
                chain(asLogicalVector()).
                   with(findFirst().logicalElement()).
-                  with(notNA()).
+                  with(mustNotBeNA()).
                   with(map(toBoolean())).
                   with(mustBe(instanceOf(Boolean.class))).
                   with(shouldBe(instanceOf(Object.class))).
@@ -541,7 +540,7 @@ public class CastBuilderTest {
     @Test
     public void testMessageArgumentAsLambda() {
         Function<Object, Object> argMsg = name -> "something";
-        arg.mustNotBeMissing(SHOW_CALLER, RError.Message.GENERIC, argMsg).mustBe(stringValue(), RError.Message.GENERIC, argMsg);
+        arg.mustNotBeMissing(RError.Message.GENERIC, argMsg).mustBe(stringValue(), RError.Message.GENERIC, argMsg);
 
         assertCastPreserves("abc");
         assertCastFail(RMissing.instance, "something");
@@ -643,7 +642,7 @@ public class CastBuilderTest {
 
     @Test
     public void testSampleNonNASequence() {
-        arg.notNA(RError.Message.GENERIC, "Error");
+        arg.mustNotBeNA(RError.Message.GENERIC, "Error");
         RIntSequence seq = RDataFactory.createIntSequence(1, 1, 1);
         Object res = cast(seq);
         Assert.assertSame(seq, res);
@@ -651,7 +650,7 @@ public class CastBuilderTest {
 
     @Test
     public void testSampleNAVector() {
-        arg.notNA("REPLACEMENT");
+        arg.replaceNA("REPLACEMENT");
         RDoubleVector vec = RDataFactory.createDoubleVector(new double[]{0, 1, RRuntime.DOUBLE_NA, 3}, false);
         Object res = cast(vec);
         Assert.assertEquals("REPLACEMENT", res);
@@ -674,7 +673,7 @@ public class CastBuilderTest {
 
     @Test
     public void defaultErrorForMustNotBeNull() {
-        arg.defaultError(RError.SHOW_CALLER, Message.SEED_NOT_VALID_INT).mustNotBeNull();
+        arg.defaultError(Message.SEED_NOT_VALID_INT).mustNotBeNull();
         assertCastFail(RNull.instance, Message.SEED_NOT_VALID_INT.message);
     }
 
@@ -857,7 +856,7 @@ public class CastBuilderTest {
     public void testWarningInElseBranchOfMapIf() {
         arg.mapIf(numericValue(),
                         chain(asIntegerVector()).with(findFirst().integerElement()).end(),
-                        chain(asIntegerVector()).with(Predef.shouldBe(anyValue().not(), RError.NO_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end());
+                        chain(asIntegerVector()).with(Predef.shouldBe(anyValue().not(), RError.Message.NA_INTRODUCED_COERCION)).end());
 
         Assert.assertEquals(1, cast(1));
         Assert.assertEquals(1, cast("1"));
@@ -867,7 +866,7 @@ public class CastBuilderTest {
     @Test
     public void testWarningInTrueBranchOfMapIf() {
         arg.allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(),
-                        RError.SHOW_CALLER, RError.Message.NA_INTRODUCED_COERCION)).end(),
+                        RError.Message.NA_INTRODUCED_COERCION)).end(),
                         asIntegerVector());
         Assert.assertEquals("1", cast("1"));
         Assert.assertEquals(RError.Message.NA_INTRODUCED_COERCION.message, CastNode.getLastWarning());
@@ -928,11 +927,11 @@ public class CastBuilderTest {
      * This tests the pipeline sampling process: all positive samples are successful and all
      * negative cause an error.
      */
-    private void testPipeline() {
+    private static void testPipeline() {
         testPipeline(false);
     }
 
-    private void testPipeline(boolean emptyPositiveSamplesAllowed) {
+    private static void testPipeline(boolean emptyPositiveSamplesAllowed) {
         if (!TEST_SAMPLING) {
             return;
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
index 3c2e35c7e5..b3bb49ecc4 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
@@ -103,7 +103,7 @@ public class ResultTypesAnalyserTest {
     @Before
     public void setUp() {
         MarkLookup.clear();
-        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class), RError.NO_CALLER);
         arg = cb.arg("x");
     }
 
@@ -374,7 +374,7 @@ public class ResultTypesAnalyserTest {
 
     @Test
     public void testNonNA() {
-        arg.mustBe(atomicIntegerValue()).notNA(RError.Message.GENERIC, "abc");
+        arg.mustBe(atomicIntegerValue()).mustNotBeNA(RError.Message.GENERIC, "abc");
         // the type representation of the wildcard result type is the nonNA step
         PipelineStep<?, ?> notNAStep = cb.getPipelineBuilders()[0].getFirstStep().getNext();
         assertTypes(atom(Integer.class).lower(notNAStep));
@@ -464,8 +464,8 @@ public class ResultTypesAnalyserTest {
 
     @Test
     public void testAnalyseRealPipeline() {
-        arg.mustBe(numericValue()).asVector().mustBe(matrix(), RError.ROOTNODE, RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)), RError.ROOTNODE,
-                        RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.ROOTNODE, RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
+        arg.mustBe(numericValue()).asVector().mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)),
+                        RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
         assertTypes(TypeExpr.union(RAbstractDoubleVector.class, RAbstractIntVector.class, RAbstractLogicalVector.class), true);
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
index d2af2ddcde..094fd88648 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
@@ -83,7 +83,7 @@ public class SampleCollectorTest {
 
     @Before
     public void setUp() {
-        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class), RError.NO_CALLER);
         arg = cb.arg("x");
     }
 
@@ -367,7 +367,7 @@ public class SampleCollectorTest {
 
     @Test
     public void testNonNA() {
-        arg.mustBe(atomicIntegerValue()).notNA(RError.Message.GENERIC, "abc");
+        arg.mustBe(atomicIntegerValue()).mustNotBeNA(RError.Message.GENERIC, "abc");
         assertSamples(RRuntime.STRING_NA);
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index 5905be7bfb..dd12608d0b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -56,6 +56,7 @@ import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.test.TestBase;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -134,7 +135,7 @@ public class TestCasts extends TestBase {
     }
 
     private static CastNode setupAndGetCast(Consumer<CastBuilder> setup) {
-        CastBuilder builder = new CastBuilder(1);
+        CastBuilder builder = new CastBuilder(1, RError.NO_CALLER);
         setup.accept(builder);
         return builder.getCasts()[0];
     }
@@ -370,7 +371,7 @@ public class TestCasts extends TestBase {
 
             protected Root(String name) {
                 super(name, setupAndGetCast(b -> b.arg(0).mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustBe(lengthLte(1)).map(
-                                charAt0(RRuntime.INT_NA)).notNA(100000)));
+                                charAt0(RRuntime.INT_NA)).replaceNA(100000)));
             }
 
             @Override
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
index a719c9d363..7c3135d422 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
@@ -83,7 +83,7 @@ public class PipelineToCastNodeTests {
     }
 
     private static CastNode createPipeline(PipelineStep<?, ?> lastStep) {
-        PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x");
+        PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x", null);
         configBuilder.setValueForwarding(false);
         return PipelineToCastNode.convert(configBuilder.build(), lastStep, Optional.empty());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index 828f41b479..443c3db50c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
@@ -72,6 +73,11 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
         casts.arg(1).boxPrimitive();
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return this;
+    }
+
     public static BinaryArithmeticNode create(BinaryArithmeticFactory binary, UnaryArithmeticFactory unary) {
         return BinaryArithmeticNodeGen.create(binary, unary);
     }
@@ -111,7 +117,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
 
     protected final UnaryArithmeticNode createUnaryArithmeticNode() {
         if (unary == null) {
-            throw RError.error(this, RError.Message.ARGUMENT_EMPTY, 2);
+            throw error(RError.Message.ARGUMENT_EMPTY, 2);
         } else {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             return UnaryArithmeticNodeGen.create(unary, RError.Message.INVALID_ARG_TYPE_UNARY);
@@ -141,7 +147,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
 
     @Fallback
     protected Object doInvalidType(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) {
-        throw RError.error(this, Message.NON_NUMERIC_BINARY);
+        throw error(Message.NON_NUMERIC_BINARY);
     }
 
     protected static BinaryMapNode createCached(BinaryArithmetic innerArithmetic, Object left, Object right) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index 1101328086..ef597fbc7c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.BinaryLogic;
 import com.oracle.truffle.r.runtime.ops.BinaryLogic.And;
 import com.oracle.truffle.r.runtime.ops.BinaryLogic.Or;
@@ -72,6 +73,11 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         casts.arg(1).boxPrimitive();
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return this;
+    }
+
     private static boolean isLogicOp(BooleanOperation op) {
         return op instanceof And || op instanceof Or;
     }
@@ -159,7 +165,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization(guards = {"(isRMissing(left) || isRMissing(right))"})
     protected Object doOneArg(Object left, Object right) {
-        throw RError.error(this, RError.Message.IS_OF_WRONG_ARITY, 1, factory.createOperation().opName(), 2);
+        throw error(RError.Message.IS_OF_WRONG_ARITY, 1, factory.createOperation().opName(), 2);
     }
 
     protected static boolean isRNullOrEmptyAndNotMissing(Object left, Object right) {
@@ -177,7 +183,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Fallback
     protected Object doInvalidType(Object left, Object right) {
-        throw RError.error(this, Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
+        throw error(Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
     }
 
     protected static BinaryMapNode createCached(BooleanOperation operation, Object left, Object right) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index c511166d15..cfd2bdd2cc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -61,6 +61,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -82,17 +83,18 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public final class CastBuilder {
 
     private static final PipelineBuilder[] EMPTY_BUILDERS = new PipelineBuilder[0];
 
     private final RBuiltin builtin;
+    private final ErrorContext callObj;
     private final String[] argumentNames;
     private PipelineBuilder[] argumentBuilders;
 
-    public CastBuilder(RBuiltin builtin) {
+    public CastBuilder(RBuiltin builtin, ErrorContext callObj) {
+        this.callObj = callObj;
         // Note: if we have the builtin metadata, we pre-allocate the arrays, builtinNode != null is
         // used to determine, if the arrays are pre-allocated or if they can grow
         if (builtin == null) {
@@ -106,14 +108,16 @@ public final class CastBuilder {
         }
     }
 
-    public CastBuilder(int argumentsCount) {
+    public CastBuilder(int argumentsCount, ErrorContext callObj) {
+        this.callObj = callObj;
         assert argumentsCount >= 0 : "argumentsCount must be non-negative";
         builtin = null;
         argumentNames = null;
         argumentBuilders = new PipelineBuilder[argumentsCount];
     }
 
-    public CastBuilder() {
+    public CastBuilder(ErrorContext callObj) {
+        this.callObj = callObj;
         builtin = null;
         argumentNames = null;
         argumentBuilders = EMPTY_BUILDERS;
@@ -253,7 +257,7 @@ public final class CastBuilder {
             argumentBuilders = Arrays.copyOf(argumentBuilders, argumentIndex + 1);
         }
         if (argumentBuilders[argumentIndex] == null) {
-            argumentBuilders[argumentIndex] = new PipelineBuilder(argumentName);
+            argumentBuilders[argumentIndex] = new PipelineBuilder(argumentName, callObj);
         }
         return argumentBuilders[argumentIndex];
     }
@@ -287,16 +291,16 @@ public final class CastBuilder {
             return filter1.or(filter2);
         }
 
-        public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-            return new FilterStep<>(argFilter, new MessageData(callObj, message, messageArgs), false);
+        public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter, RError.Message message, Object... messageArgs) {
+            return new FilterStep<>(argFilter, new MessageData(message, messageArgs), false);
         }
 
         public static <T, R extends T> PipelineStep<T, R> mustBe(Filter<T, R> argFilter) {
             return new FilterStep<>(argFilter, null, false);
         }
 
-        public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-            return new FilterStep<>(argFilter, new MessageData(callObj, message, messageArgs), true);
+        public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter, RError.Message message, Object... messageArgs) {
+            return new FilterStep<>(argFilter, new MessageData(message, messageArgs), true);
         }
 
         public static <T> PipelineStep<T, T> shouldBe(Filter<T, ? extends T> argFilter) {
@@ -331,50 +335,26 @@ public final class CastBuilder {
             return new CoercionStep<>(RType.Integer, false);
         }
 
-        public static <T> PipelineStep<T, Integer> asInteger(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Integer, false, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector() {
             return new CoercionStep<>(RType.Integer, true);
         }
 
-        public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Integer, true, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, null);
-        }
-
-        public static <T> PipelineStep<T, RAbstractIntVector> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj);
+            return new CoercionStep<>(RType.Integer, true, preserveNames, preserveDimensions, preserveAttributes, true);
         }
 
         public static <T> PipelineStep<T, Double> asDouble() {
             return new CoercionStep<>(RType.Double, false);
         }
 
-        public static <T> PipelineStep<T, Double> asDouble(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Double, false, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector() {
             return new CoercionStep<>(RType.Double, true);
         }
 
-        public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Double, true, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
             return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes);
         }
 
-        public static <T> PipelineStep<T, RAbstractDoubleVector> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Double, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, String> asString() {
             return new CoercionStep<>(RType.Character, false);
         }
@@ -391,10 +371,6 @@ public final class CastBuilder {
             return new CoercionStep<>(RType.Complex, true);
         }
 
-        public static <T> PipelineStep<T, RAbstractComplexVector> asComplex(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Complex, false, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractRawVector> asRawVector() {
             return new CoercionStep<>(RType.Raw, true);
         }
@@ -403,24 +379,12 @@ public final class CastBuilder {
             return new CoercionStep<>(RType.Logical, false);
         }
 
-        public static <T> PipelineStep<T, Byte> asLogical(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Logical, false, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector() {
             return new CoercionStep<>(RType.Logical, true);
         }
 
-        public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Logical, true, false, false, false, true, messageCallerObj);
-        }
-
         public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false, null);
-        }
-
-        public static <T> PipelineStep<T, RAbstractLogicalVector> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-            return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj);
+            return new CoercionStep<>(RType.Logical, true, preserveNames, preserveDimensions, preserveAttributes, false);
         }
 
         public static PipelineStep<Byte, Boolean> asBoolean() {
@@ -432,15 +396,7 @@ public final class CastBuilder {
         }
 
         public static <T> PipelineStep<T, RAbstractVector> asVector(boolean preserveNonVector) {
-            return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector, null);
-        }
-
-        /**
-         * Version of {@code findFirst} step that can be used in {@code chain}, must be followed by
-         * call for {@code xyzElement()}.
-         */
-        public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) {
-            return new FindFirstNodeBuilder(new MessageData(callObj, message, messageArgs));
+            return new CoercionStep<>(RType.Any, true, false, false, false, preserveNonVector);
         }
 
         /**
@@ -448,7 +404,7 @@ public final class CastBuilder {
          * call for {@code xyzElement()}.
          */
         public static <V extends RAbstractVector> FindFirstNodeBuilder findFirst(RError.Message message, Object... messageArgs) {
-            return new FindFirstNodeBuilder(new MessageData(null, message, messageArgs));
+            return new FindFirstNodeBuilder(new MessageData(message, messageArgs));
         }
 
         /**
@@ -459,27 +415,19 @@ public final class CastBuilder {
             return new FindFirstNodeBuilder(null);
         }
 
-        public static <T> PipelineStep<T, T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) {
-            return notNA(null, callObj, message, messageArgs);
-        }
-
-        public static <T> PipelineStep<T, T> notNA(RError.Message message, Object... messageArgs) {
-            return notNA(null, null, message, messageArgs);
-        }
-
-        public static <T> PipelineStep<T, T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-            return new NotNAStep<>(naReplacement, new MessageData(callObj, message, messageArgs));
+        public static <T> PipelineStep<T, T> mustNotBeNA(RError.Message message, Object... messageArgs) {
+            return new NotNAStep<>(null, new MessageData(message, messageArgs));
         }
 
-        public static <T> PipelineStep<T, T> notNA(T naReplacement, RError.Message message, Object... messageArgs) {
-            return notNA(naReplacement, null, message, messageArgs);
+        public static <T> PipelineStep<T, T> shouldNotBeNA(T naReplacement, RError.Message message, Object... messageArgs) {
+            return new NotNAStep<>(naReplacement, new MessageData(message, messageArgs));
         }
 
-        public static <T> PipelineStep<T, T> notNA(T naReplacement) {
+        public static <T> PipelineStep<T, T> replaceNA(T naReplacement) {
             return new NotNAStep<>(naReplacement, null);
         }
 
-        public static <T> PipelineStep<T, T> notNA() {
+        public static <T> PipelineStep<T, T> mustNotBeNA() {
             return new NotNAStep<>(null, null);
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
index 2567981144..16fcfdc90b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
@@ -29,6 +29,8 @@ import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
@@ -50,24 +52,35 @@ public interface NodeWithArgumentCasts {
 
     final class Casts {
         private static final ConcurrentHashMap<Class<?>, Casts> castsMap = new ConcurrentHashMap<>();
-        private static final Casts empty = new Casts(false);
+        private static final Casts empty = new Casts();
 
         protected final CastBuilder casts;
         private final boolean declaresNoCasts;
 
-        private Casts(boolean noCasts) {
-            casts = new CastBuilder();
-            this.declaresNoCasts = noCasts;
+        private Casts() {
+            casts = new CastBuilder(RError.NO_CALLER);
+            this.declaresNoCasts = false;
         }
 
-        private Casts(Class<? extends NodeWithArgumentCasts> cls, boolean noCasts) {
+        public Casts(Class<? extends NodeWithArgumentCasts> cls) {
             castsMap.put(cls, this);
-            casts = new CastBuilder(cls.getAnnotation(RBuiltin.class));
-            this.declaresNoCasts = noCasts;
+            RBuiltin builtin = cls.getAnnotation(RBuiltin.class);
+            ErrorContext callObj = RError.contextForBuiltin(builtin);
+            casts = new CastBuilder(builtin, callObj);
+            this.declaresNoCasts = false;
         }
 
-        public Casts(Class<? extends NodeWithArgumentCasts> cls) {
-            this(cls, false);
+        public Casts(Class<? extends NodeWithArgumentCasts> cls, ErrorContext callObj) {
+            castsMap.put(cls, this);
+            RBuiltin annotation = cls.getAnnotation(RBuiltin.class);
+            casts = new CastBuilder(annotation, callObj);
+            this.declaresNoCasts = false;
+        }
+
+        private Casts(Class<? extends NodeWithArgumentCasts> cls, boolean declaresNoCasts) {
+            RBuiltin annotation = cls.getAnnotation(RBuiltin.class);
+            casts = new CastBuilder(annotation, null);
+            this.declaresNoCasts = declaresNoCasts;
         }
 
         public static void noCasts(Class<? extends NodeWithArgumentCasts> cls) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index 579352ce12..bba7cfda29 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -22,16 +22,13 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
-import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.RootCallTarget;
-import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.RCallNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
@@ -39,14 +36,14 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypes;
-import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.builtin.RBuiltinBaseNode;
 
 @TypeSystemReference(RTypes.class)
-public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgumentCasts {
+public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithArgumentCasts {
 
     public abstract Object executeBuiltin(VirtualFrame frame, Object... args);
 
@@ -60,22 +57,6 @@ public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgument
         return EMPTY_OBJECT_ARRAY;
     }
 
-    static RootCallTarget createArgumentsCallTarget(RBuiltinFactory builtin) {
-        CompilerAsserts.neverPartOfCompilation();
-
-        RBuiltinNode node = builtin.getConstructor().get();
-        FormalArguments formals = FormalArguments.createForBuiltin(node.getDefaultParameterValues(), builtin.getSignature());
-        if (builtin.getKind() == RBuiltinKind.INTERNAL) {
-            assert node.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values";
-            assert builtin.getSignature().getVarArgCount() == 0 || builtin.getSignature().getVarArgIndex() == builtin.getSignature().getLength() - 1 : "only last argument can be vararg";
-        }
-
-        FrameDescriptor frameDescriptor = new FrameDescriptor();
-        RBuiltinRootNode root = new RBuiltinRootNode(builtin, node, formals, frameDescriptor, null);
-        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor);
-        return Truffle.getRuntime().createCallTarget(root);
-    }
-
     public static final RBuiltinNode inline(RBuiltinDescriptor factory) {
         // static number of arguments
         return ((RBuiltinFactory) factory).getConstructor().get();
@@ -122,4 +103,9 @@ public abstract class RBuiltinNode extends RBaseNode implements NodeWithArgument
         return (getRBuiltin() == null ? getClass().getSimpleName() : getRBuiltin().name());
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        ErrorContext context = RError.contextForBuiltin(getRBuiltin());
+        return context == null ? this : context;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
index 8f4ad0a026..801f347157 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.unary.CastComplexNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
@@ -46,9 +45,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.builtin.RBuiltinBaseNode;
 
 @TypeSystemReference(RTypes.class)
-public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWithArgumentCasts {
+public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements NodeWithArgumentCasts {
 
     public Object call(@SuppressWarnings("unused") VirtualFrame frame, RArgsValuesAndNames args) {
         return call(args);
@@ -56,6 +56,11 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith
 
     protected abstract Object call(RArgsValuesAndNames args);
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return RError.NO_CALLER;
+    }
+
     // TODO: these should be in the build nodes
     @Child private CastLogicalNode castLogical;
     @Child private CastIntegerNode castInt;
@@ -64,8 +69,6 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith
     @Child private CastToVectorNode castVector;
     @Children private final CastNode[] argumentCasts;
 
-    protected final BranchProfile errorProfile = BranchProfile.create();
-
     public RExternalBuiltinNode() {
         this.argumentCasts = getCasts();
     }
@@ -123,6 +126,7 @@ public abstract class RExternalBuiltinNode extends RBaseNode implements NodeWith
             if (name.endsWith("NodeGen")) {
                 name = name.substring(0, name.length() - 7);
             }
+            // this error always shows the .Call itself
             throw RError.error(this, Message.INCORRECT_NOF_ARGS, args.getLength(), expectedLength, name.toLowerCase());
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
index 1639997b9f..a2d9d2158f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
@@ -35,6 +35,13 @@ public final class MessageData {
     private final RError.Message message;
     private final Object[] messageArgs;
 
+    public MessageData(Message message, Object... messageArgs) {
+        this.callObj = null;
+        this.message = message;
+        this.messageArgs = messageArgs;
+        assert message != null;
+    }
+
     public MessageData(RBaseNode callObj, Message message, Object... messageArgs) {
         this.callObj = callObj;
         this.message = message;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
index 42146741e4..39e2f8a790 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
@@ -22,14 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts;
 
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentFilterFactory;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentFilterFactoryImpl;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactory;
-import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode.ArgumentMapperFactoryImpl;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 
 /**
  * Immutable class with configuration of the pipeline. Create using {@link PipelineConfigBuilder}.
@@ -38,30 +33,18 @@ import com.oracle.truffle.r.runtime.data.RNull;
  * warning if RNull/RMissing occurs.
  */
 public class PipelineConfig {
-    private static ArgumentFilterFactory filterFactory = ArgumentFilterFactoryImpl.INSTANCE;
-    private static ArgumentMapperFactory mapperFactory = ArgumentMapperFactoryImpl.INSTANCE;
-
     private final String argumentName;
+    private final ErrorContext callObj;
     private final MessageData defaultError;
     private final MessageData defaultWarning;
-    private final Mapper<? super RMissing, ?> missingMapper;
-    private final Mapper<? super RNull, ?> nullMapper;
-    private final MessageData missingMsg;
-    private final MessageData nullMsg;
     private boolean valueForwarding;
 
-    public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, Mapper<? super RMissing, ?> missingMapper, Mapper<? super RNull, ?> nullMapper,
-                    boolean valueForwarding,
-                    MessageData missingMsg,
-                    MessageData nullMsg) {
+    public PipelineConfig(String argumentName, ErrorContext callObj, MessageData defaultError, MessageData defaultWarning, boolean valueForwarding) {
         this.defaultError = defaultError;
         this.defaultWarning = defaultWarning;
-        this.missingMapper = missingMapper;
-        this.nullMapper = nullMapper;
         this.valueForwarding = valueForwarding;
-        this.missingMsg = missingMsg;
-        this.nullMsg = nullMsg;
         this.argumentName = argumentName;
+        this.callObj = callObj;
     }
 
     /**
@@ -69,7 +52,11 @@ public class PipelineConfig {
      * time being this is not configurable.
      */
     public MessageData getDefaultDefaultMessage() {
-        return new MessageData(null, RError.Message.INVALID_ARGUMENT, argumentName);
+        return new MessageData(RError.Message.INVALID_ARGUMENT, argumentName);
+    }
+
+    public ErrorContext getCallObj() {
+        return callObj;
     }
 
     public MessageData getDefaultError() {
@@ -80,39 +67,7 @@ public class PipelineConfig {
         return defaultWarning;
     }
 
-    public Mapper<? super RMissing, ?> getMissingMapper() {
-        return missingMapper;
-    }
-
-    public Mapper<? super RNull, ?> getNullMapper() {
-        return nullMapper;
-    }
-
-    public MessageData getMissingMessage() {
-        return missingMsg;
-    }
-
-    public MessageData getNullMessage() {
-        return nullMsg;
-    }
-
     public boolean getValueForwarding() {
         return valueForwarding;
     }
-
-    public static ArgumentFilterFactory getFilterFactory() {
-        return filterFactory;
-    }
-
-    public static ArgumentMapperFactory getMapperFactory() {
-        return mapperFactory;
-    }
-
-    public static void setFilterFactory(ArgumentFilterFactory ff) {
-        filterFactory = ff;
-    }
-
-    public static void setMapperFactory(ArgumentMapperFactory mf) {
-        mapperFactory = mf;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
index cf58d823b6..7f4776692e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineStep.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts;
 
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -98,6 +99,7 @@ public abstract class PipelineStep<T, R> {
         private final Object replacement;
 
         public NotNAStep(Object replacement, MessageData message) {
+            assert !(replacement instanceof RBaseNode || replacement instanceof RError.Message);
             this.replacement = replacement;
             this.message = message;
         }
@@ -163,7 +165,6 @@ public abstract class PipelineStep<T, R> {
         public final boolean preserveNames;
         public final boolean preserveDimensions;
         public final boolean preserveAttributes;
-        public final RBaseNode messageCallObj;
 
         /**
          * Whether RNull/RMissing should be preserved, or converted to an empty list.
@@ -176,31 +177,26 @@ public abstract class PipelineStep<T, R> {
         public final boolean vectorCoercion;
 
         public CoercionStep(RType type, boolean vectorCoercion) {
-            this(type, vectorCoercion, false, false, false, true, null);
+            this(type, vectorCoercion, false, false, false, true);
         }
 
         public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-            this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true, null);
+            this(type, vectorCoercion, preserveNames, preserveDimensions, preserveAttributes, true);
         }
 
-        public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector, RBaseNode messageCallObj) {
+        public CoercionStep(RType type, boolean vectorCoercion, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) {
             this.type = type;
             this.vectorCoercion = vectorCoercion;
             this.preserveNames = preserveNames;
             this.preserveAttributes = preserveAttributes;
             this.preserveDimensions = preserveDimensions;
             this.preserveNonVector = preserveNonVector;
-            this.messageCallObj = messageCallObj;
         }
 
         public RType getType() {
             return type;
         }
 
-        public RBaseNode getMessageCallObj() {
-            return messageCallObj;
-        }
-
         @Override
         public <D> D accept(PipelineStepVisitor<D> visitor, D previous) {
             return visitor.visit(this, previous);
@@ -285,7 +281,7 @@ public abstract class PipelineStep<T, R> {
             if (!returns) {
                 return this;
             }
-            return new MapIfStep<T, R>(filter, trueBranch, falseBranch, false);
+            return new MapIfStep<>(filter, trueBranch, falseBranch, false);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 728e2bd70d..84f6a59c7a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -87,6 +87,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -95,6 +96,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 /**
@@ -106,12 +108,7 @@ public final class PipelineToCastNode {
         // nop: static class
     }
 
-    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStep, Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
-        return convert(config, firstStep, PipelineConfig.getFilterFactory(), PipelineConfig.getMapperFactory(), fwdAnalysisResult);
-    }
-
-    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStepIn, ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory,
-                    Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
+    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStepIn, Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
         if (firstStepIn == null) {
             return null;
         }
@@ -119,9 +116,9 @@ public final class PipelineToCastNode {
         // if the pipeline is only single return, we change it to map to avoid needing to catch
         // the PipelineReturnException, otherwise the exception is caught by ChainedCastNode
         boolean singleMapStep = firstStepIn.getNext() == null && firstStepIn instanceof MapIfStep;
-        PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep) firstStepIn).withoutReturns() : firstStepIn;
+        PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep<?, ?>) firstStepIn).withoutReturns() : firstStepIn;
 
-        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(filterFactory, mapperFactory, config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage()));
+        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage(), config.getCallObj()));
 
         if (!config.getValueForwarding()) {
             return originalPipelineFactory.get();
@@ -162,19 +159,25 @@ public final class PipelineToCastNode {
     }
 
     private static final class CastNodeFactory implements PipelineStepVisitor<CastNode> {
-        private final ArgumentFilterFactory filterFactory;
-        private final ArgumentMapperFactory mapperFactory;
         private boolean boxPrimitives = false;
 
         private final MessageData defaultError;
         private final MessageData defaultWarning;
+        private final RBaseNode callObj;
 
-        CastNodeFactory(ArgumentFilterFactory filterFactory, ArgumentMapperFactory mapperFactory, MessageData defaultError, MessageData defaultWarning, MessageData defaultMessage) {
+        CastNodeFactory(MessageData defaultError, MessageData defaultWarning, MessageData defaultMessage, ErrorContext callObj) {
             assert defaultMessage != null : "defaultMessage is null";
-            this.filterFactory = filterFactory;
-            this.mapperFactory = mapperFactory;
             this.defaultError = MessageData.getFirstNonNull(defaultError, defaultMessage);
             this.defaultWarning = MessageData.getFirstNonNull(defaultWarning, defaultMessage);
+            this.callObj = callObj;
+        }
+
+        private MessageData process(MessageData data) {
+            if (data == null || callObj == null) {
+                return data;
+            } else {
+                return new MessageData(callObj, data.getMessage(), data.getMessageArgs());
+            }
         }
 
         @Override
@@ -191,15 +194,15 @@ public final class PipelineToCastNode {
                 MessageData msg = step.getError();
                 if (msg == null) {
                     // Note: intentional direct use of defaultError
-                    msg = defaultError != null ? defaultError : new MessageData(null, RError.Message.LENGTH_ZERO);
+                    msg = defaultError != null ? defaultError : new MessageData(RError.Message.LENGTH_ZERO);
                 }
-                return FindFirstNodeGen.create(step.getElementClass(), msg, step.getDefaultValue());
+                return FindFirstNodeGen.create(step.getElementClass(), process(msg), step.getDefaultValue());
             } else {
                 MessageData warning = step.getError();
                 if (warning == null) {
                     return FindFirstNodeGen.create(step.getElementClass(), step.getDefaultValue());
                 } else {
-                    return FindFirstNodeGen.create(step.getElementClass(), warning, step.getDefaultValue());
+                    return FindFirstNodeGen.create(step.getElementClass(), process(warning), step.getDefaultValue());
                 }
             }
         }
@@ -207,23 +210,23 @@ public final class PipelineToCastNode {
         @Override
         public CastNode visit(FilterStep<?, ?> step, CastNode previous) {
             @SuppressWarnings("unchecked")
-            ArgumentFilter<Object, Object> filter = (ArgumentFilter<Object, Object>) filterFactory.createFilter(step.getFilter());
+            ArgumentFilter<Object, Object> filter = (ArgumentFilter<Object, Object>) ArgumentFilterFactoryImpl.INSTANCE.createFilter(step.getFilter());
             MessageData msg = getDefaultIfNull(step.getMessage(), step.isWarning());
-            return FilterNode.create(filter, step.isWarning(), msg, boxPrimitives, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
-                            ResultForArg.TRUE.equals(step.getFilter().resultForMissing()));
+            return FilterNode.create(filter, step.isWarning(), process(msg), boxPrimitives, step.getFilter().resultForNull() == ResultForArg.TRUE,
+                            step.getFilter().resultForMissing() == ResultForArg.TRUE);
         }
 
         @Override
         public CastNode visit(NotNAStep<?> step, CastNode previous) {
             if (step.getReplacement() == null) {
-                MessageData msg = getDefaultErrorIfNull(step.getMessage());
-                return NonNANodeGen.create(msg, step.getReplacement());
+                MessageData msg = getDefaultIfNull(step.getMessage(), false);
+                return NonNANodeGen.create(process(msg), step.getReplacement());
             } else {
                 MessageData msg = step.getMessage();
                 if (msg == null) {
                     return NonNANodeGen.create(null, step.getReplacement());
                 } else {
-                    return NonNANodeGen.create(msg, step.getReplacement());
+                    return NonNANodeGen.create(process(msg), step.getReplacement());
                 }
             }
         }
@@ -235,19 +238,19 @@ public final class PipelineToCastNode {
             RType type = step.getType();
             switch (type) {
                 case Integer:
-                    return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj())
-                                    : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj());
+                    return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj)
+                                    : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
                 case Double:
-                    return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj())
-                                    : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj());
+                    return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj)
+                                    : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
                 case Character:
                     return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
                                     : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Logical:
-                    return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj())
-                                    : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj());
+                    return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj)
+                                    : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
                 case Complex:
-                    return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, step.getMessageCallObj());
+                    return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
                 case Raw:
                     return CastRawNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Any:
@@ -264,29 +267,21 @@ public final class PipelineToCastNode {
 
         @Override
         public CastNode visit(MapStep<?, ?> step, CastNode previous) {
-            return MapNode.create(mapperFactory.createMapper(step.getMapper()));
+            return MapNode.create(ArgumentMapperFactoryImpl.INSTANCE.createMapper(step.getMapper()));
         }
 
         @Override
         public CastNode visit(MapIfStep<?, ?> step, CastNode previous) {
             @SuppressWarnings("unchecked")
-            ArgumentFilter<Object, Object> condition = (ArgumentFilter<Object, Object>) filterFactory.createFilter(step.getFilter());
+            ArgumentFilter<Object, Object> condition = (ArgumentFilter<Object, Object>) ArgumentFilterFactoryImpl.INSTANCE.createFilter(step.getFilter());
             CastNode trueCastNode = PipelineToCastNode.convert(step.getTrueBranch(), this);
             CastNode falseCastNode = PipelineToCastNode.convert(step.getFalseBranch(), this);
             return ConditionalMapNode.create(condition, trueCastNode, falseCastNode, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
                             ResultForArg.TRUE.equals(step.getFilter().resultForMissing()), step.isReturns());
         }
 
-        private MessageData getDefaultErrorIfNull(MessageData message) {
-            return MessageData.getFirstNonNull(message, defaultError);
-        }
-
-        private MessageData getDefaultWarningIfNull(MessageData message) {
-            return MessageData.getFirstNonNull(message, defaultWarning);
-        }
-
         private MessageData getDefaultIfNull(MessageData message, boolean isWarning) {
-            return isWarning ? getDefaultWarningIfNull(message) : getDefaultErrorIfNull(message);
+            return MessageData.getFirstNonNull(message, isWarning ? defaultWarning : defaultError);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
index 739b5aafc7..13fa1d39b4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/ArgCastBuilder.java
@@ -27,7 +27,6 @@ import java.util.function.Function;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Defines fluent API methods for building cast pipeline steps that are available in every phase of
@@ -51,13 +50,8 @@ public class ArgCastBuilder<T, THIS> {
         return (THIS) this;
     }
 
-    public THIS shouldBe(Filter<? super T, ?> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendShouldBeStep(argFilter, callObj, message, messageArgs);
-        return (THIS) this;
-    }
-
     public THIS shouldBe(Filter<? super T, ?> argFilter) {
-        pipelineBuilder().appendShouldBeStep(argFilter, null, null, null);
+        pipelineBuilder().appendShouldBeStep(argFilter, null, null);
         return (THIS) this;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java
index aae3576a5a..24f7569eed 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java
@@ -22,16 +22,14 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
+
 /**
  * Can be used to construct a cast node outside of the FastR builtins framework. The cast node can
  * be then used to cast anything, not only arguments.
  */
 public final class CastNodeBuilder {
-    public static PreinitialPhaseBuilder newCastBuilder(String argName) {
-        return new PipelineBuilder(argName).fluent();
-    }
-
-    public static PreinitialPhaseBuilder newCastBuilder() {
-        return newCastBuilder("");
+    public static PreinitialPhaseBuilder newCastBuilder(ErrorContext callObj) {
+        return new PipelineBuilder("", callObj).fluent();
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
index 15df4300f2..b9e980973b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
@@ -27,7 +27,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.Filter;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Defines fluent API methods for building cast pipeline steps for argument that has been cast to a
@@ -50,12 +49,7 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg
      * reports the warning message.
      */
     public HeadPhaseBuilder<S> findFirst(S defaultValue, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
-    }
-
-    public HeadPhaseBuilder<S> findFirst(S defaultValue, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendFindFirst(defaultValue, elementClass, callObj, message, messageArgs);
+        pipelineBuilder().appendFindFirst(defaultValue, elementClass, message, messageArgs);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
@@ -63,12 +57,7 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg
      * The inserted cast node raises an error if the input vector is empty.
      */
     public HeadPhaseBuilder<S> findFirst(RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendFindFirst(null, elementClass, null, message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
-    }
-
-    public HeadPhaseBuilder<S> findFirst(RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendFindFirst(null, elementClass, callObj, message, messageArgs);
+        pipelineBuilder().appendFindFirst(null, elementClass, message, messageArgs);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
@@ -77,7 +66,7 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg
      * error if the input vector is empty.
      */
     public HeadPhaseBuilder<S> findFirst() {
-        pipelineBuilder().appendFindFirst(null, elementClass, null, null, null);
+        pipelineBuilder().appendFindFirst(null, elementClass, null, null);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
@@ -87,22 +76,17 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg
      */
     public HeadPhaseBuilder<S> findFirst(S defaultValue) {
         assert defaultValue != null : "defaultValue cannot be null";
-        pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, null, null);
+        pipelineBuilder().appendFindFirst(defaultValue, elementClass, null, null);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
     public HeadPhaseBuilder<S> findFirstOrNull() {
-        pipelineBuilder().appendFindFirst(RNull.instance, elementClass, null, null, null);
+        pipelineBuilder().appendFindFirst(RNull.instance, elementClass, null, null);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
-    public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendMustBeStep(argFilter, callObj, message, messageArgs);
-        return this;
-    }
-
     public CoercedPhaseBuilder<T, S> mustBe(Filter<? super T, ? extends T> argFilter, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendMustBeStep(argFilter, null, message, messageArgs);
+        pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs);
         return this;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
index 54e31bfbf8..5402c62bf2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
@@ -27,7 +27,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.Filter;
 import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Defines fluent API methods for building cast pipeline steps for a value that has been taken as a
@@ -91,13 +90,8 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendMustBeStep(argFilter, callObj, message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
-    }
-
     public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendMustBeStep(argFilter, null, message, messageArgs);
+        pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs);
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
@@ -115,11 +109,6 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        shouldBe(Predef.instanceOf(cls), callObj, message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
-    }
-
     public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) {
         shouldBe(Predef.instanceOf(cls), message, messageArgs);
         return new HeadPhaseBuilder<>(pipelineBuilder());
@@ -130,33 +119,23 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde
         return new HeadPhaseBuilder<>(pipelineBuilder());
     }
 
-    public HeadPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(null, callObj, message, messageArgs);
-        return this;
-    }
-
-    public HeadPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(null, null, message, messageArgs);
-        return this;
-    }
-
-    public HeadPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(naReplacement, callObj, message, messageArgs);
+    public HeadPhaseBuilder<T> mustNotBeNA(RError.Message message, Object... messageArgs) {
+        pipelineBuilder().appendNotNA(null, message, messageArgs);
         return this;
     }
 
-    public HeadPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(naReplacement, null, message, messageArgs);
+    public HeadPhaseBuilder<T> shouldNotBeNA(T naReplacement, RError.Message message, Object... messageArgs) {
+        pipelineBuilder().appendNotNA(naReplacement, message, messageArgs);
         return this;
     }
 
-    public HeadPhaseBuilder<T> notNA() {
-        pipelineBuilder().appendNotNA(null, null, null, null);
+    public HeadPhaseBuilder<T> mustNotBeNA() {
+        pipelineBuilder().appendNotNA(null, null, null);
         return this;
     }
 
-    public HeadPhaseBuilder<T> notNA(T naReplacement) {
-        pipelineBuilder().appendNotNA(naReplacement, null, null, null);
+    public HeadPhaseBuilder<T> replaceNA(T naReplacement) {
+        pipelineBuilder().appendNotNA(naReplacement, null, null);
         return this;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
index 57d3ea046e..39790fdd69 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Defines fluent API methods for building cast pipeline steps for generic argument, which was not
@@ -51,22 +50,13 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
         super(builder);
     }
 
-    public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendMustBeStep(argFilter, callObj, message, messageArgs);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
-    }
-
     public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RError.Message message, Object... messageArgs) {
-        return mustBe(argFilter, null, message, messageArgs);
+        pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs);
+        return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
     public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter) {
-        return mustBe(argFilter, null, null, (Object[]) null);
-    }
-
-    public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        mustBe(Predef.instanceOf(cls), callObj, message, messageArgs);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return mustBe(argFilter, null, (Object[]) null);
     }
 
     public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) {
@@ -79,11 +69,6 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
-    public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        shouldBe(Predef.instanceOf(cls), callObj, message, messageArgs);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
-    }
-
     public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) {
         shouldBe(Predef.instanceOf(cls), message, messageArgs);
         return new InitialPhaseBuilder<>(pipelineBuilder());
@@ -144,28 +129,18 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
         return new InitialPhaseBuilder<>(pipelineBuilder());
     }
 
-    public InitialPhaseBuilder<T> notNA(RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(null, callObj, message, messageArgs);
-        return this;
-    }
-
-    public InitialPhaseBuilder<T> notNA(RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(null, null, message, messageArgs);
+    public InitialPhaseBuilder<T> mustNotBeNA(RError.Message message, Object... messageArgs) {
+        pipelineBuilder().appendNotNA(null, message, messageArgs);
         return this;
     }
 
-    public InitialPhaseBuilder<T> notNA(T naReplacement, RBaseNode callObj, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(naReplacement, callObj, message, messageArgs);
+    public InitialPhaseBuilder<T> shouldNotBeNA(T naReplacement, RError.Message message, Object... messageArgs) {
+        pipelineBuilder().appendNotNA(naReplacement, message, messageArgs);
         return this;
     }
 
-    public InitialPhaseBuilder<T> notNA(T naReplacement, RError.Message message, Object... messageArgs) {
-        pipelineBuilder().appendNotNA(naReplacement, null, message, messageArgs);
-        return this;
-    }
-
-    public InitialPhaseBuilder<T> notNA(T naReplacement) {
-        pipelineBuilder().appendNotNA(naReplacement, null, null, null);
+    public InitialPhaseBuilder<T> replaceNA(T naReplacement) {
+        pipelineBuilder().appendNotNA(naReplacement, null, null);
         return this;
     }
 
@@ -175,50 +150,26 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
     }
 
     public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        return asIntegerVector(preserveNames, preserveDimensions, preserveAttributes, null);
-    }
-
-    public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        pipelineBuilder().appendAsVector(RType.Integer, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj);
+        pipelineBuilder().appendAsVector(RType.Integer, preserveNames, preserveDimensions, preserveAttributes);
         return new CoercedPhaseBuilder<>(pipelineBuilder(), Integer.class);
     }
 
-    public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector(RBaseNode messageCallerObj) {
-        return asIntegerVector(false, false, false, messageCallerObj);
-    }
-
     public CoercedPhaseBuilder<RAbstractIntVector, Integer> asIntegerVector() {
         return asIntegerVector(false, false, false);
     }
 
     public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        return asDoubleVector(preserveNames, preserveDimensions, preserveAttributes, null);
-    }
-
-    public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        pipelineBuilder().appendAsVector(RType.Double, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj);
+        pipelineBuilder().appendAsVector(RType.Double, preserveNames, preserveDimensions, preserveAttributes);
         return new CoercedPhaseBuilder<>(pipelineBuilder(), Double.class);
     }
 
-    public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector(RBaseNode messageCallerObj) {
-        return asDoubleVector(false, false, false, messageCallerObj);
-    }
-
     public CoercedPhaseBuilder<RAbstractDoubleVector, Double> asDoubleVector() {
         return asDoubleVector(false, false, false);
     }
 
-    public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        pipelineBuilder().appendAsVector(RType.Logical, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj);
-        return new CoercedPhaseBuilder<>(pipelineBuilder(), Byte.class);
-    }
-
     public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        return asLogicalVector(preserveNames, preserveDimensions, preserveAttributes, null);
-    }
-
-    public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector(RBaseNode messageCallerObj) {
-        return asLogicalVector(false, false, false, messageCallerObj);
+        pipelineBuilder().appendAsVector(RType.Logical, preserveNames, preserveDimensions, preserveAttributes);
+        return new CoercedPhaseBuilder<>(pipelineBuilder(), Byte.class);
     }
 
     public CoercedPhaseBuilder<RAbstractLogicalVector, Byte> asLogicalVector() {
@@ -235,18 +186,10 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
     }
 
     public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        return asComplexVector(preserveNames, preserveDimensions, preserveAttributes, null);
-    }
-
-    public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        pipelineBuilder().appendAsVector(RType.Complex, preserveNames, preserveDimensions, preserveAttributes, messageCallerObj);
+        pipelineBuilder().appendAsVector(RType.Complex, preserveNames, preserveDimensions, preserveAttributes);
         return new CoercedPhaseBuilder<>(pipelineBuilder(), RComplex.class);
     }
 
-    public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector(RBaseNode messageCallerObj) {
-        return asComplexVector(false, false, false, messageCallerObj);
-    }
-
     public CoercedPhaseBuilder<RAbstractComplexVector, RComplex> asComplexVector() {
         return asComplexVector(false, false, false);
     }
@@ -261,17 +204,17 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
     }
 
     public CoercedPhaseBuilder<RAbstractVector, Object> asVector() {
-        pipelineBuilder().appendAsVector(false, false, false, true, null);
+        pipelineBuilder().appendAsVector(false, false, false, true);
         return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class);
     }
 
     public CoercedPhaseBuilder<RAbstractVector, Object> asVector(boolean preserveNonVector) {
-        pipelineBuilder().appendAsVector(false, false, false, preserveNonVector, null);
+        pipelineBuilder().appendAsVector(false, false, false, preserveNonVector);
         return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class);
     }
 
     public CoercedPhaseBuilder<RAbstractVector, Object> asVectorPreserveAttrs(boolean preserveNonVector) {
-        pipelineBuilder().appendAsVector(false, false, true, preserveNonVector, null);
+        pipelineBuilder().appendAsVector(false, false, true, preserveNonVector);
         return new CoercedPhaseBuilder<>(pipelineBuilder(), Object.class);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index 2d98ed5f3f..19d2e3b397 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -40,9 +40,9 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Class that holds the data for a pipeline for a single parameter. It holds the cast pipeline steps
@@ -55,8 +55,8 @@ public final class PipelineBuilder {
     private ChainBuilder<?> chainBuilder;
     private final AtomicReference<Optional<ForwardingAnalysisResult>> fwdAnalysisResult = new AtomicReference<>();
 
-    public PipelineBuilder(String argumentName) {
-        this.pcb = new PipelineConfigBuilder(argumentName);
+    public PipelineBuilder(String argumentName, ErrorContext callObj) {
+        this.pcb = new PipelineConfigBuilder(argumentName, callObj);
     }
 
     public CastNode buildNode() {
@@ -71,29 +71,25 @@ public final class PipelineBuilder {
         append(new PipelineStep.BoxPrimitiveStep<>());
     }
 
-    public void appendFindFirst(Object defaultValue, Class<?> elementClass, RBaseNode callObj, Message message, Object[] messageArgs) {
-        append(new FindFirstStep<>(defaultValue, elementClass, createMessage(callObj, message, messageArgs)));
+    public void appendFindFirst(Object defaultValue, Class<?> elementClass, Message message, Object[] messageArgs) {
+        append(new FindFirstStep<>(defaultValue, elementClass, createMessage(message, messageArgs)));
     }
 
     public void appendAsAttributable(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         append(new AttributableCoercionStep<>(preserveNames, preserveDimensions, preserveAttributes));
     }
 
-    public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector, RBaseNode messageCallerObj) {
-        append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector, messageCallerObj));
-    }
-
-    public void appendAsVector(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw;
-        append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true, messageCallerObj));
+    public void appendAsVector(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean preserveNonVector) {
+        append(new CoercionStep<>(RType.Any, true, preserveNames, preserveDimensions, preserveAttributes, preserveNonVector));
     }
 
     public void appendAsVector(RType type, boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        appendAsVector(type, preserveNames, preserveDimensions, preserveAttributes, null);
+        assert type == RType.Integer || type == RType.Double || type == RType.Complex || type == RType.Character || type == RType.Logical || type == RType.Raw;
+        append(new CoercionStep<>(type, true, preserveNames, preserveDimensions, preserveAttributes, true));
     }
 
-    public void appendNotNA(Object naReplacement, RBaseNode callObj, Message message, Object[] messageArgs) {
-        append(new NotNAStep<>(naReplacement, createMessage(callObj, message, messageArgs)));
+    public void appendNotNA(Object naReplacement, Message message, Object[] messageArgs) {
+        append(new NotNAStep<>(naReplacement, createMessage(message, messageArgs)));
     }
 
     public void appendMapIf(Filter<?, ?> argFilter, Mapper<?, ?> trueBranchMapper, boolean returns) {
@@ -116,20 +112,16 @@ public final class PipelineBuilder {
         append(new MapStep<>(mapFn));
     }
 
-    public void appendMustBeStep(Filter<?, ?> argFilter, RBaseNode callObj, Message message, Object[] messageArgs) {
-        append(new FilterStep<>(argFilter, createMessage(callObj, message, messageArgs), false));
+    public void appendMustBeStep(Filter<?, ?> argFilter, Message message, Object[] messageArgs) {
+        append(new FilterStep<>(argFilter, createMessage(message, messageArgs), false));
     }
 
     public void appendShouldBeStep(Filter<?, ?> argFilter, Message message, Object[] messageArgs) {
-        appendShouldBeStep(argFilter, null, message, messageArgs);
-    }
-
-    public void appendShouldBeStep(Filter<?, ?> argFilter, RBaseNode callObj, Message message, Object[] messageArgs) {
-        append(new FilterStep<>(argFilter, createMessage(callObj, message, messageArgs), true));
+        append(new FilterStep<>(argFilter, createMessage(message, messageArgs), true));
     }
 
-    private static MessageData createMessage(RBaseNode callObj, Message message, Object[] messageArgs) {
-        return message == null ? null : new MessageData(callObj, message, messageArgs);
+    private static MessageData createMessage(Message message, Object[] messageArgs) {
+        return message == null ? null : new MessageData(message, messageArgs);
     }
 
     PipelineConfigBuilder getPipelineConfig() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
index 2492ae8922..b6efd44e4e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
@@ -22,10 +22,10 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -39,20 +39,18 @@ public final class PipelineConfigBuilder {
     private MessageData defaultError;
     private MessageData defaultWarning;
 
-    private Mapper<? super RMissing, ?> missingMapper;
-    private Mapper<? super RNull, ?> nullMapper;
-    private MessageData missingMsg;
-    private MessageData nullMsg;
     private boolean valueForwarding = true;
+    private final ErrorContext callObj;
 
-    public PipelineConfigBuilder(String argumentName) {
+    public PipelineConfigBuilder(String argumentName, ErrorContext callObj) {
         this.argumentName = argumentName;
-        defaultError = new MessageData(null, RError.Message.INVALID_ARGUMENT, argumentName);
+        this.callObj = callObj;
+        defaultError = new MessageData(RError.Message.INVALID_ARGUMENT, argumentName);
         defaultWarning = defaultError;
     }
 
     public PipelineConfig build() {
-        return new PipelineConfig(argumentName, defaultError, defaultWarning, missingMapper, nullMapper, valueForwarding, missingMsg, nullMsg);
+        return new PipelineConfig(argumentName, callObj, defaultError, defaultWarning, valueForwarding);
     }
 
     void setDefaultError(MessageData defaultError) {
@@ -67,5 +65,4 @@ public final class PipelineConfigBuilder {
         this.valueForwarding = flag;
         return this;
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
index 3f06baa1eb..598db1e749 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Adds methods to {@link InitialPhaseBuilder} that allow to set up the pipeline configuration.
@@ -63,11 +62,7 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> {
     }
 
     public InitialPhaseBuilder<Object> mustNotBeNull(RError.Message errorMsg, Object... msgArgs) {
-        return mustBe(nullValue().not(), null, errorMsg, msgArgs);
-    }
-
-    public InitialPhaseBuilder<Object> mustNotBeNull(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) {
-        return mustBe(nullValue().not(), callObj, errorMsg, msgArgs);
+        return mustBe(nullValue().not(), errorMsg, msgArgs);
     }
 
     public InitialPhaseBuilder<Object> mapNull(Mapper<RNull, ?> mapper) {
@@ -83,11 +78,7 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> {
     }
 
     public InitialPhaseBuilder<Object> mustNotBeMissing(RError.Message errorMsg, Object... msgArgs) {
-        return mustBe(missingValue().not(), null, errorMsg, msgArgs);
-    }
-
-    public InitialPhaseBuilder<Object> mustNotBeMissing(RBaseNode callObj, RError.Message errorMsg, Object... msgArgs) {
-        return mustBe(missingValue().not(), callObj, errorMsg, msgArgs);
+        return mustBe(missingValue().not(), errorMsg, msgArgs);
     }
 
     public InitialPhaseBuilder<Object> mapMissing(Mapper<RMissing, ?> mapper) {
@@ -98,18 +89,13 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> {
         return returnIf(nullValue().or(missingValue()));
     }
 
-    public PreinitialPhaseBuilder defaultError(RBaseNode callObj, RError.Message message, Object... args) {
-        pipelineBuilder().getPipelineConfig().setDefaultError(new MessageData(callObj, message, args));
-        return this;
-    }
-
-    public PreinitialPhaseBuilder defaultError(Message message, Object... args) {
-        defaultError(null, message, args);
+    public PreinitialPhaseBuilder defaultError(RError.Message message, Object... args) {
+        pipelineBuilder().getPipelineConfig().setDefaultError(new MessageData(message, args));
         return this;
     }
 
-    public PreinitialPhaseBuilder defaultWarning(RBaseNode callObj, Message message, Object... args) {
-        pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(callObj, message, args));
+    public PreinitialPhaseBuilder defaultWarning(Message message, Object... args) {
+        pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(message, args));
         return this;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java
index 25920e4044..8668018df1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java
@@ -23,12 +23,11 @@ public abstract class GetPrimName extends RExternalBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(GetPrimName.class);
-        casts.arg(0).defaultError(RError.NO_CALLER, RError.Message.GENERIC, "'R_get_primname' called on a non-primitive").mustBe(builtin());
+        casts.arg(0).defaultError(RError.Message.GENERIC, "'R_get_primname' called on a non-primitive").mustBe(builtin());
     }
 
     @Specialization(guards = "f.isBuiltin()")
     protected String getPrimName(RFunction f) {
         return f.getName();
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
index 44d51c9a1b..f32c80724f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
@@ -13,6 +13,7 @@
 package com.oracle.truffle.r.nodes.objects;
 
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -39,17 +40,13 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 {
     @Child private GetFixedAttributeNode pckgAttrAccess = GetFixedAttributeNode.create(RRuntime.PCKG_ATTR_KEY);
     @Child private SetClassAttributeNode setClassAttrNode;
 
-    @Child private CastNode castStringScalar;
-    @Child private CastNode castLogicalScalar;
-    {
-        castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
-        castLogicalScalar = newCastBuilder().asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode();
-    }
+    @Child private CastNode castStringScalar = newCastBuilder(NO_CALLER).asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
+    @Child private CastNode castLogicalScalar = newCastBuilder(NO_CALLER).asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode();
 
     static {
         Casts casts = new Casts(NewObject.class);
         // TODO: should we change the message to (incompatible) "Java level ..."?
-        casts.arg(0).mustNotBeNull(RError.NO_CALLER, RError.Message.GENERIC, "C level NEW macro called with null class definition pointer");
+        casts.arg(0).mustNotBeNull(RError.Message.GENERIC, "C level NEW macro called with null class definition pointer");
     }
 
     @Specialization
@@ -58,15 +55,14 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 {
         Object e = accessSlotVirtual.executeAccess(classDef, RRuntime.S_VIRTUAL);
         if (((byte) castLogicalScalar.execute(e)) != RRuntime.LOGICAL_FALSE) {
             e = accessSlotClassName.executeAccess(classDef, RRuntime.S_CLASSNAME);
-            throw RError.error(this, RError.Message.OBJECT_FROM_VIRTUAL, castStringScalar.execute(e));
+            throw error(RError.Message.OBJECT_FROM_VIRTUAL, castStringScalar.execute(e));
         }
         e = accessSlotClassName.executeAccess(classDef, RRuntime.S_CLASSNAME);
         Object prototype = accessSlotPrototypeName.executeAccess(classDef, RRuntime.S_PROTOTYPE);
         Object value = duplicate.executeObject(prototype);
         assert value instanceof RAttributable;
         RAttributable valueAttr = (RAttributable) value;
-        if (valueAttr instanceof RS4Object ||
-                        (e instanceof RAttributable && ((RAttributable) e).getAttributes() != null && pckgAttrAccess.execute(((RAttributable) e).getAttributes()) != null)) {
+        if (valueAttr instanceof RS4Object || (e instanceof RAttributable && ((RAttributable) e).getAttributes() != null && pckgAttrAccess.execute(((RAttributable) e).getAttributes()) != null)) {
 
             if (setClassAttrNode == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
index 1d28787a26..ab41637a83 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
@@ -209,6 +209,6 @@ public abstract class UnaryNotNode extends RBuiltinNode {
 
     @Fallback
     protected Object invalidArgType(@SuppressWarnings("unused") Object operand) {
-        throw RError.error(this, RError.Message.INVALID_ARG_TYPE);
+        throw error(RError.Message.INVALID_ARG_TYPE);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 9ec55327d1..993c3565a1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -18,6 +18,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -68,32 +70,50 @@ public final class RError extends RuntimeException {
         }
     }
 
+    public abstract static class ErrorContext extends RBaseNode {
+        private ErrorContext() {
+            // private constructor
+        }
+    }
+
+    private static final class ErrorContextImpl extends ErrorContext {
+
+    }
+
+    public static ErrorContext contextForBuiltin(RBuiltin builtin) {
+        ErrorContext callObj;
+        if (builtin == null) {
+            callObj = RError.NO_CALLER;
+        } else if (builtin.kind() == RBuiltinKind.INTERNAL) {
+            callObj = RError.SHOW_CALLER;
+        } else {
+            callObj = null;
+        }
+        return callObj;
+    }
+
     /**
      * This flags a call to {@code error} or {@code warning} where the error message should show the
      * caller's caller.
      */
-    public static final RBaseNode SHOW_CALLER2 = new RBaseNode() {
-    };
+    public static final ErrorContext SHOW_CALLER2 = new ErrorContextImpl();
     /**
      * This flags a call to {@code error} or {@code warning} where the error message should show the
      * caller of the current function.
      */
-    public static final RBaseNode SHOW_CALLER = new RBaseNode() {
-    };
+    public static final ErrorContext SHOW_CALLER = new ErrorContextImpl();
 
     /**
      * A very special case that ensures that no caller is output in the error/warning message. This
      * is needed where, even if there is a caller, GnuR does not show it.
      */
-    public static final RBaseNode NO_CALLER = new RBaseNode() {
-    };
+    public static final ErrorContext NO_CALLER = new ErrorContextImpl();
 
     /**
      * This is a workaround for a case in {@code RCallNode} where an error might be thrown while
      * executing a {@code RootNode}, which is not a subclass of {@link RBaseNode}.
      */
-    public static final RBaseNode ROOTNODE = new RBaseNode() {
-    };
+    public static final ErrorContext ROOTNODE = new ErrorContextImpl();
 
     /**
      * TODO the string is not really needed as all output is performed prior to the throw.
@@ -112,6 +132,19 @@ public final class RError extends RuntimeException {
         return verboseStackTrace;
     }
 
+    public static RError error(ErrorContext node, Message msg) {
+        throw error(node, msg, new Object[]{});
+    }
+
+    public static RError error(ErrorContext node, Message msg, Object arg) {
+        throw error(node, msg, new Object[]{arg});
+    }
+
+    @TruffleBoundary
+    public static RError error(ErrorContext node, Message msg, Object... args) {
+        throw error0(node, msg, args);
+    }
+
     @TruffleBoundary
     public static RError error(RBaseNode node, Message msg, Object... args) {
         throw error0(node, msg, args);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java
new file mode 100644
index 0000000000..72082019ba
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.nodes.builtin;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.RErrorException;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+public abstract class RBuiltinBaseNode extends RBaseNode {
+
+    protected abstract RBaseNode getErrorContext();
+
+    public final RError error(RErrorException exception) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), exception);
+    }
+
+    public final RError error(RError.Message message) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message);
+    }
+
+    public final RError error(RError.Message message, Object arg) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg);
+    }
+
+    public final RError error(RError.Message message, Object arg1, Object arg2) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2);
+    }
+
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3);
+    }
+
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4);
+    }
+
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 30a6d6d91d..691383aecf 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -117,8 +117,9 @@ public class TestS4 extends TestRBase {
         assertEval("{ standardGeneric(42) }");
         assertEval("{ standardGeneric(character()) }");
         assertEval("{ standardGeneric(\"\") }");
-        assertEval("{ standardGeneric(\"foo\", 42) }");
-        assertEval("{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
+        // FastR produces better error contexts
+        assertEval(Output.IgnoreErrorContext, "{ standardGeneric(\"foo\", 42) }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
     }
 
     @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 8d04aedae7..b0ed490c98 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -69,6 +69,7 @@ public class TestBase {
      * See {@link com.oracle.truffle.r.test.builtins.TestTestBase} for examples.
      */
     public enum Output implements TestTrait {
+        ImprovedErrorContext, // FastR provides a more accurate error context
         IgnoreErrorContext, // the error context is ignored (e.g., "a+b" vs. "a + b")
         IgnoreErrorMessage, // the actual error message is ignored
         IgnoreWarningContext, // the warning context is ignored
@@ -591,7 +592,7 @@ public class TestBase {
             ignored.addAll(Arrays.asList(TestTrait.collect(traits, Ignored.class)));
             output.addAll(Arrays.asList(TestTrait.collect(traits, Output.class)));
             context.addAll(Arrays.asList(TestTrait.collect(traits, Context.class)));
-            containsError = (!FULL_COMPARE_ERRORS && (output.contains(Output.IgnoreErrorContext) || output.contains(Output.IgnoreErrorMessage)));
+            containsError = (!FULL_COMPARE_ERRORS && (output.contains(Output.IgnoreErrorContext) || output.contains(Output.ImprovedErrorContext) || output.contains(Output.IgnoreErrorMessage)));
             isIgnored = ignored.size() > 0 ^ (ProcessFailedTests && !(ignored.contains(Ignored.Unstable) || ignored.contains(Ignored.SideEffects)));
             assert !output.contains(Output.IgnoreWhitespace) || output.size() == 1 : "IgnoreWhitespace trait does not work with any other Output trait";
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
index 557d6a7a79..cc310553ac 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
@@ -29,8 +29,8 @@ public class TestBuiltin_Syssetlocale extends TestBase {
 
     @Test
     public void testSyssetlocaleInvalidArgs() {
-        assertEval(Output.IgnoreErrorContext, ".Internal(Sys.setlocale(4, c('more', 'elements')))");
-        assertEval(Output.IgnoreErrorContext, ".Internal(Sys.setlocale(4, 42))");
+        assertEval(".Internal(Sys.setlocale(4, c('more', 'elements')))");
+        assertEval(".Internal(Sys.setlocale(4, 42))");
         assertEval(Output.IgnoreErrorMessage, ".Internal(Sys.setlocale('3L', 'C'))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java
index 063819596e..c58d69b373 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asfunction.java
@@ -40,7 +40,7 @@ public class TestBuiltin_asfunction extends TestBase {
         assertEval("{ as.function(alist(\"foo\"))() }");
         assertEval("{ as.function(alist(7+42i))() }");
         assertEval("{ as.function(alist(as.raw(7)))() }");
-        assertEval("{ .Internal(as.function.default(alist(a+b), \"foo\")) }");
+        assertEval(Output.IgnoreErrorContext, "{ .Internal(as.function.default(alist(a+b), \"foo\")) }");
         assertEval(Output.IgnoreErrorContext, "{ .Internal(as.function.default(function() 42, parent.frame())) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
index 671161d6d8..35c8c1b6b1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
@@ -403,7 +403,7 @@ public class TestBuiltin_asvector extends TestBase {
         assertEval("{ as.vector(\"foo\", \"character\") }");
         assertEval("{ as.vector(\"foo\", \"list\") }");
         assertEval("{ as.vector(\"foo\") }");
-        assertEval(Output.IgnoreErrorContext, "{ as.vector(\"foo\", \"bar\") }");
+        assertEval(Output.ImprovedErrorContext, "{ as.vector(\"foo\", \"bar\") }");
         assertEval(Output.IgnoreWarningContext, "{ as.vector(c(\"foo\", \"bar\"), \"raw\") }");
         assertEval("x<-c(a=1.1, b=2.2); as.vector(x, \"raw\")");
         assertEval("x<-c(a=1L, b=2L); as.vector(x, \"complex\")");
@@ -422,9 +422,9 @@ public class TestBuiltin_asvector extends TestBase {
         assertEval("as.vector(x~z)");
         assertEval("as.vector(file(''))");
 
-        assertEval("{ as.vector(42, NULL) }");
-        assertEval("{ as.vector(42, c(\"character\", \"character\")) }");
-        assertEval("{ as.vector(42, character())  }");
+        assertEval(Output.ImprovedErrorContext, "{ as.vector(42, NULL) }");
+        assertEval(Output.ImprovedErrorContext, "{ as.vector(42, c(\"character\", \"character\")) }");
+        assertEval(Output.ImprovedErrorContext, "{ as.vector(42, character())  }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
index ee785542b9..341cea102c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
@@ -55,8 +55,9 @@ public class TestBuiltin_atan2 extends TestBase {
         assertEval("{ atan2(c(0.3,0.6,0.9), c(0.4, 0.3)) }");
         assertEval("{ atan2() }");
         assertEval("{ atan2(0.7) }");
-        assertEval("{ atan2(NULL, 1) }");
-        assertEval("{ atan2(2, new.env()) }");
-        assertEval("{ atan2(2, as.symbol('45')) }");
+
+        assertEval(Output.ImprovedErrorContext, "{ atan2(NULL, 1) }");
+        assertEval(Output.ImprovedErrorContext, "{ atan2(2, new.env()) }");
+        assertEval(Output.ImprovedErrorContext, "{ atan2(2, as.symbol('45')) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java
index 9162f20451..b5bbe5f6d2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java
@@ -40,7 +40,7 @@ public class TestBuiltin_attach extends TestBase {
     public void testArguments() {
         assertEval("attach('string')");
         assertEval(Output.IgnoreErrorMessage, "attach(list(x=42), pos='string')");
-        assertEval(Output.IgnoreErrorContext, "attach(list(), name=42)");
+        assertEval("attach(list(), name=42)");
         assertEval("detach('string')");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
index ab83f538b2..e26626578d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
@@ -106,7 +106,7 @@ public class TestBuiltin_attrassign extends TestBase {
 
     @Test
     public void testArgsCasts() {
-        assertEval(Output.IgnoreErrorContext, "x<-42; attr(x, NULL) <- NULL");
-        assertEval(Output.IgnoreErrorContext, "x<-42; attr(x, 42) <- NULL");
+        assertEval("x<-42; attr(x, NULL) <- NULL");
+        assertEval("x<-42; attr(x, 42) <- NULL");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java
index 256dbc9038..e3cee63390 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java
@@ -27,6 +27,6 @@ public class TestBuiltin_bitwiseNot extends TestBase {
         assertEval("{ bitwNot(c(17,24,34,48,51,66,72,99)) }");
         assertEval("{ bitwNot(c(0,100,200,50,70,20)) }");
 
-        assertEval(Output.IgnoreErrorContext, "{ bitwNot(TRUE) }");
+        assertEval("{ bitwNot(TRUE) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java
index de7b8be16c..7b92ea2e08 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java
@@ -91,9 +91,9 @@ public class TestBuiltin_cat extends TestBase {
     @Test
     public void testCatUnsupportedArgs() {
         assertEval("cat(list(), expression(), sep='this-should-be-ok')");
-        assertEval("cat(list(1,2,3))");
-        assertEval("cat(parse(text='42'))");
+        assertEval(Output.ImprovedErrorContext, "cat(list(1,2,3))");
+        assertEval(Output.ImprovedErrorContext, "cat(parse(text='42'))");
         assertEval("cat(quote(a))");
-        assertEval("cat(quote(3+3))");
+        assertEval(Output.ImprovedErrorContext, "cat(quote(3+3))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
index 254279ebb8..61a835aef8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
@@ -69,5 +69,7 @@ public class TestBuiltin_crossprod extends TestBase {
         assertEval("{ x <- matrix(c(NaN,2,3,4,5,NA), nrow=3); crossprod(x) }");
 
         assertEval(Ignored.Unknown, "{ x <- matrix(c(NaN,2+3i,3,4+1i,5,NA), nrow=3); crossprod(x) }");
+
+        assertEval(Output.ImprovedErrorContext, "{ crossprod('asdf', matrix(1:6, ncol=2)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
index 77fcee218b..7a7ba51168 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
@@ -209,8 +209,8 @@ public class TestBuiltin_inherits extends TestBase {
 
         assertEval("{ inherits(getClass(\"ClassUnionRepresentation\"), \"classRepresentation\") }");
 
-        assertEval(Output.IgnoreErrorContext, "{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, 2, c(TRUE)) ;}");
-        assertEval(Output.IgnoreErrorContext, "{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, \"a\", 1) ;}");
+        assertEval("{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, 2, c(TRUE)) ;}");
+        assertEval("{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, \"a\", 1) ;}");
 
         assertEval("inherits(NULL, 'NULL')");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java
index ceb2167bfc..fbead7016d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java
@@ -38,18 +38,18 @@ public class TestBuiltin_intToBits extends TestBase {
         assertEval("intToBits(-1.56)");
         assertEval("intToBits(-0.3)");
         assertEval("intToBits('123')");
-        assertEval(Output.IgnoreWarningContext, "intToBits(5+7i)");
+        assertEval("intToBits(5+7i)");
         assertEval("intToBits(NULL)");
         assertEval("intToBits(c(1,2,3))");
         assertEval("intToBits(c(5L,99L))");
         assertEval("intToBits(integer(0))");
         assertEval("intToBits(double(0))");
         assertEval("intToBits(6:9)");
-        assertEval(Output.IgnoreWarningContext, "intToBits('23rrff')");
+        assertEval("intToBits('23rrff')");
         assertEval("intToBits(new.env())");
         assertEval("intToBits(environment)");
         assertEval("intToBits(stdout())");
-        assertEval(Output.IgnoreErrorContext, "intToBits(list(c(5,5,7,8),88,6L))");
+        assertEval("intToBits(list(c(5,5,7,8),88,6L))");
         assertEval("intToBits(list(5,5,7,8))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
index 4cfb24acda..5eb2c4fbf5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
@@ -199,7 +199,8 @@ public class TestBuiltin_isvector extends TestBase {
         assertEval("{is.vector(c(TRUE,FALSE),\"logical\");}");
         assertEval("{x<-1;class(x)<-\"a\";is.vector(x);}");
         assertEval("{x<-1;names(x)<-\"a\";is.vector(x);}");
-        assertEval("{is.vector(c(1,2), c(\"sss\", \"dddd\"));}");
-        assertEval("{is.vector(c(1,2), TRUE);}");
+        // FastR produces better error contexts
+        assertEval(Output.IgnoreErrorContext, "{is.vector(c(1,2), c(\"sss\", \"dddd\"));}");
+        assertEval(Output.IgnoreErrorContext, "{is.vector(c(1,2), TRUE);}");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
index 20125e3e04..a4bf2ecafe 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
@@ -36,7 +36,7 @@ public class TestBuiltin_levels extends TestBase {
         assertEval("{ x <- 1 ; levels(x)<-c(\"cat\", \"dog\"); levels(x)}");
         assertEval("{ x <- 1 ; levels(x)<-c(3, \"cat\"); levels(x);}");
         assertEval("{ x <- 1 ; levels(x)<-c(1, \"cat\", 4.5, \"3\"); levels(x);}");
-        assertEval(Output.IgnoreErrorContext, "{ x <- 1 ; levels(x)<-NULL; levels(notx)}");
+        assertEval("{ x <- 1 ; levels(x)<-NULL; levels(notx)}");
         assertEval("{ x <- NULL; levels(x)<-\"dog\"; levels(x)}");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java
index cc92051e78..2164d33db1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java
@@ -36,14 +36,14 @@ public class TestBuiltin_ngettext extends TestBase {
         assertEval("{ ngettext(1, \"a\", c(\"b\")) }");
         assertEval("{ ngettext(c(1), \"a\", \"b\") }");
         assertEval("{ ngettext(c(1,2), \"a\", \"b\") }");
-        assertEval(Output.IgnoreWarningContext, "{ ngettext(1+1i, \"a\", \"b\") }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, NULL, \"b\") }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, \"a\", NULL) }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, NULL, NULL) }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, c(\"a\", \"c\"), \"b\") }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, \"a\", c(\"b\", \"c\")) }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, c(1), \"b\") }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(1, \"a\", c(1)) }");
-        assertEval(Output.IgnoreErrorContext, "{ ngettext(-1, \"a\", \"b\") }");
+        assertEval("{ ngettext(1+1i, \"a\", \"b\") }");
+        assertEval("{ ngettext(1, NULL, \"b\") }");
+        assertEval("{ ngettext(1, \"a\", NULL) }");
+        assertEval("{ ngettext(1, NULL, NULL) }");
+        assertEval("{ ngettext(1, c(\"a\", \"c\"), \"b\") }");
+        assertEval("{ ngettext(1, \"a\", c(\"b\", \"c\")) }");
+        assertEval("{ ngettext(1, c(1), \"b\") }");
+        assertEval("{ ngettext(1, \"a\", c(1)) }");
+        assertEval("{ ngettext(-1, \"a\", \"b\") }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
index 000d12c09f..a929a4004d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
@@ -39,7 +39,7 @@ public class TestBuiltin_pathexpand extends TestBase {
 
     @Test
     public void testArgsValidation() {
-        assertEval(Output.IgnoreErrorContext, "path.expand(NULL)");
-        assertEval(Output.IgnoreErrorContext, "path.expand(42)");
+        assertEval("path.expand(NULL)");
+        assertEval("path.expand(42)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
index d88d8ba695..019a276b8d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
@@ -62,7 +62,7 @@ public class TestBuiltin_pmatch extends TestBase {
         assertEval("pmatch(NULL, 1)");
         assertEval("pmatch(1, NULL)");
         assertEval("pmatch(1:5, c(1,3), nomatch=NULL)");
-        assertEval(Output.IgnoreWarningContext, "pmatch(1:5, c(1,3), nomatch='str')");
+        assertEval("pmatch(1:5, c(1,3), nomatch='str')");
         assertEval("pmatch(1:5, c(1,3), duplicates.ok=42)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
index ad1b4881be..5298a7200a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
@@ -113,7 +113,7 @@ public class TestBuiltin_pmax extends TestBase {
         assertEval("{ pmax(c(FALSE, TRUE), logical()) }");
         assertEval("{ pmax(c(FALSE, TRUE), c(FALSE, NA)) }");
 
-        assertEval(Output.IgnoreErrorContext, "{ pmax(as.raw(42)) }");
-        assertEval(Output.IgnoreErrorContext, "{ pmax(7+42i) }");
+        assertEval("{ pmax(as.raw(42)) }");
+        assertEval("{ pmax(7+42i) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
index 28c1a51ff1..6ea406f009 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
@@ -98,8 +98,8 @@ public class TestBuiltin_pmin extends TestBase {
         assertEval("{ pmin(c(FALSE, TRUE), logical()) }");
         assertEval("{ pmin(c(FALSE, TRUE), c(FALSE, NA)) }");
 
-        assertEval(Output.IgnoreErrorContext, "{ pmin(as.raw(42)) }");
-        assertEval(Output.IgnoreErrorContext, "{ pmin(7+42i) }");
+        assertEval("{ pmin(as.raw(42)) }");
+        assertEval("{ pmin(7+42i) }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java
index 67ced8d5a6..3a86e0a772 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java
@@ -24,6 +24,6 @@ public class TestBuiltin_primUntrace extends TestBase {
 
     @Test
     public void testArgsCasts() {
-        assertEval(Output.IgnoreErrorContext, ".primUntrace(42)");
+        assertEval(".primUntrace(42)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
index a4e57175dd..4adce90c62 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
@@ -44,7 +44,7 @@ public class TestBuiltin_qr extends TestBase {
         assertEval(Ignored.Unknown, "{ round( qr(matrix(1:6,nrow=2), LAPACK=TRUE)$qr, digits=5) }");
 
         // qr.coef
-        assertEval(Output.IgnoreErrorContext, "{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) }");
+        assertEval("{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) }");
         assertEval(Ignored.Unknown, " { x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; round( qr.coef(x, 1:10), digits=5 ) }");
         assertEval(Ignored.Unknown, "{ x <- qr(c(3,1,2), LAPACK=TRUE) ; round( qr.coef(x, c(1,3,2)), digits=5 ) }");
         // FIXME: GNU-R will print negative zero as zero
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java
index 28562baadd..7f5b2e1759 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quit.java
@@ -64,7 +64,7 @@ public class TestBuiltin_quit extends TestBase {
 
     @Test
     public void testQuitErrorSave() {
-        assertEval("{ quit(\"xx\") }");
+        assertEval(Output.ImprovedErrorContext, "{ quit(\"xx\") }");
     }
 
     @Test
@@ -75,7 +75,7 @@ public class TestBuiltin_quit extends TestBase {
     /**
      * Removes temporarily created files {@code .RData} and {@code .Rhistory} and restore backups if
      * available.
-     * 
+     *
      * @throws IOException
      */
     @AfterClass
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
index c634f9bcf0..fe634e2b20 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
@@ -164,14 +164,14 @@ public class TestBuiltin_repint extends TestBase {
         assertEval("{ rep.int(c(1,2,3),c(2,8,3)) }");
         assertEval("{ rep.int(seq_len(2), rep.int(8, 2)) }");
 
-        assertEval(Output.IgnoreErrorContext, "{ rep.int(c(1,2,3),c(2,8)) }");
+        assertEval("{ rep.int(c(1,2,3),c(2,8)) }");
 
         assertEval(Output.IgnoreErrorContext, "{ rep.int(function() 42, 7) }");
         assertEval("{ rep.int(7, character()) }");
         assertEval("{ rep.int(7, NULL) }");
         assertEval("{ rep.int(7, \"7\") }");
-        assertEval(Output.IgnoreErrorContext, "{ rep.int(7, c(7, 42)) }");
+        assertEval("{ rep.int(7, c(7, 42)) }");
         assertEval("{ rep_int(7, function() 42) }");
-        assertEval(Output.IgnoreErrorContext, "{ rep.int(7, NA)  }");
+        assertEval("{ rep.int(7, NA)  }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
index fa5190ed61..d21d73c43b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
@@ -93,12 +93,12 @@ public class TestBuiltin_sample extends TestBase {
         assertEval("set.seed(42); sample(2, 0)");
         assertEval("set.seed(42); sample(0, 0)");
         // replace
-        assertEval(Output.IgnoreErrorContext, "set.seed(42); sample(4, replace=c(T,F))");
+        assertEval("set.seed(42); sample(4, replace=c(T,F))");
         assertEval("set.seed(42); sample(4, replace=1)");
         assertEval("set.seed(42); sample(4, replace=1.2)");
         assertEval(Output.IgnoreErrorMessage, "set.seed(42); sample(4, replace='s')");
         // prob
-        assertEval(Output.IgnoreErrorContext, "set.seed(42); sample(4, prob=c(1,2))");
-        assertEval(Output.IgnoreErrorContext, "set.seed(42); sample(4, prob=c(-1,1,1,2))");
+        assertEval("set.seed(42); sample(4, prob=c(1,2))");
+        assertEval("set.seed(42); sample(4, prob=c(-1,1,1,2))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
index ad62fe7e4e..d317ae23a5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
@@ -33,7 +33,7 @@ public class TestBuiltin_scan extends TestBase {
         assertEval(Output.IgnoreWarningContext, "{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\")) }");
 
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), fill=TRUE) }");
-        assertEval(Output.IgnoreErrorContext, "{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), multi.line=FALSE) }");
+        assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), multi.line=FALSE) }");
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), fill=TRUE, multi.line=FALSE) }");
 
         assertEval("{ con<-textConnection(c(\"\\\"2\\\"\", \"\\\"11\\\"\")); scan(con, what=list(\"\")) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java
index f473c3d01c..e71494b48a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java
@@ -137,8 +137,8 @@ public class TestBuiltin_seq_along extends TestBase {
         assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 42; seq_along(x) }");
         assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) c(100, 200); seq_along(x) }");
         assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) '48'; seq_along(x) }");
-        assertEval("{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) }");
+        assertEval(Output.IgnoreWarningContext, Output.IgnoreErrorContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) }");
+        assertEval(Output.IgnoreWarningContext, Output.IgnoreErrorContext, "{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) }");
         assertEval("{ length <- function(x) 42; seq_along(c(1,2,3)) }");
         assertEval("{ assign('length.myclass', function(...) 42, envir=.__S3MethodsTable__.); x <- 1; class(x) <- 'myclass'; res <- seq_along(x); rm('length.myclass', envir=.__S3MethodsTable__.); res }");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java
index 6fc2c7ecc2..2a5519b8fd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_shortRowNames.java
@@ -129,7 +129,7 @@ public class TestBuiltin_shortRowNames extends TestBase {
 
     @Test
     public void testArgCasts() {
-        assertEval(Output.IgnoreErrorContext, ".Internal(shortRowNames(42, -2))");
+        assertEval(".Internal(shortRowNames(42, -2))");
         assertEval(".Internal(shortRowNames(42, '1'))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java
index 371431dcb3..4a5cff4415 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java
@@ -82,8 +82,8 @@ public class TestBuiltin_substr extends TestBase {
         assertEval("{ substr(1234L,2,3) }");
         assertEval("{ substr(1234,2,3) }");
         assertEval("{ substr(\"abcdef\",c(1,2),c(3L,5L)) }");
-        assertEval(Output.IgnoreErrorContext, "{ substr(c(\"abcdef\", \"aa\"), integer(), 2) }");
-        assertEval(Output.IgnoreErrorContext, "{ substr(c(\"abcdef\", \"aa\"), 2, integer()) }");
+        assertEval("{ substr(c(\"abcdef\", \"aa\"), integer(), 2) }");
+        assertEval("{ substr(c(\"abcdef\", \"aa\"), 2, integer()) }");
         assertEval("{ substr(character(), integer(), integer()) }");
         assertEval("{ substr(c(\"abcdef\", \"aa\"), NA, 4) }");
         assertEval("{ substr(c(\"abcdef\", \"aa\"), 3, NA) }");
@@ -101,10 +101,12 @@ public class TestBuiltin_substr extends TestBase {
         assertEval("{ x<-\"abcdef\"; substr(x,1,NA)<-\"0\"; x }");
         assertEval("{ x<-character(); substr(x,1,3)<-\"0\"; x }");
         assertEval("{ x<-c(\"abcdef\", \"ghijklm\"); substr(x, c(1,NA), 4)<-\"0\"; x }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,3,1)<-0; x }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-character(); x }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-NULL; x }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-\"abcdef\"; substr(x,integer(),3)<-NULL; x }");
+
+        assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,3,1)<-0; x }");
+        assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-character(); x }");
+        assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,1,3)<-NULL; x }");
+        assertEval(Output.ImprovedErrorContext, "{ x<-\"abcdef\"; substr(x,integer(),3)<-NULL; x }");
+
         assertEval("{ x<-character(); substr(x,1,3)<-0; x }");
         assertEval("{ x<-character(); substr(x,1,3)<-NULL; x }");
         assertEval("{ x<-character(); substr(x,integer(),3)<-NULL; x }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
index f1e24b620f..a1be9ab8d7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
@@ -382,8 +382,8 @@ public class TestFunctions extends TestBase {
 
     @Test
     public void testDefaultArgs() {
-        assertEval(Output.IgnoreErrorContext, "{ array(dim=c(-2,2)); }");
-        assertEval(Output.IgnoreErrorContext, "{ array(dim=c(-2,-2)); }");
+        assertEval("{ array(dim=c(-2,2)); }");
+        assertEval("{ array(dim=c(-2,-2)); }");
         assertEval("{ length(array(dim=c(1,0,2,3))) }");
         assertEval("{ dim(array(dim=c(2.1,2.9,3.1,4.7))) }");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java
index 1c0d9daf0f..9ccc585559 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java
@@ -89,10 +89,10 @@ public class TestSimpleArrays extends TestBase {
 
         // negative length vectors are not allowed is the error reported by gnu-r
         // negative dims not allowed by R, special GNU message
-        assertEval(Output.IgnoreErrorContext, "{ array(NA, dim=c(-2,2)); }");
+        assertEval("{ array(NA, dim=c(-2,2)); }");
 
         // negative dims not allowed
-        assertEval(Output.IgnoreErrorContext, "{ array(NA, dim=c(-2,-2)); }");
+        assertEval("{ array(NA, dim=c(-2,-2)); }");
 
         // zero dimension array has length 0
         assertEval("{ length(array(NA, dim=c(1,0,2,3))) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java
index d0add21697..88b2cbf42e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java
@@ -158,7 +158,7 @@ public class TestSimpleLists extends TestBase {
         assertEval("a<- NULL; a <- `$<-`(a, \"a\", 1); dput(a)");
         assertEval("a<- NULL; a <- `[[<-`(a, \"a\", 1); dput(a)");
         assertEval("a<- NULL; a <- `[[<-`(a, 1, 1); dput(a)");
-        assertEval("a<- NULL; a <- `$<-`(a, 1, 1); dput(a)");
+        // FastR produces a better error context
+        assertEval(Output.IgnoreErrorContext, "a<- NULL; a <- `$<-`(a, 1, 1); dput(a)");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
index 8c765123f6..c5ab5f2053 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
@@ -2224,7 +2224,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ c(\"1L\",\"hello\") %in% 1:10 }");
         assertEval("{ (1 + 2i) %in% c(1+10i, 1+4i, 2+2i, 1+2i) }");
         assertEval("{ as.logical(-1:1) %in% TRUE }");
-        assertEval(Output.IgnoreErrorContext, "{ x <- function(){1} ; x %in% TRUE }");
+        assertEval("{ x <- function(){1} ; x %in% TRUE }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java
index 2d8525a759..d4e60d100d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_BinDist.java
@@ -37,7 +37,7 @@ public class TestExternal_BinDist extends TestBase {
 
     @Test
     public void testBinDistWrongArgs() {
-        assertEval(Output.IgnoreWarningContext, ".Call(stats:::C_BinDist, 0, 0, 'string', 3, 5)");
+        assertEval(".Call(stats:::C_BinDist, 0, 0, 'string', 3, 5)");
         assertEval(".Call(stats:::C_BinDist, c(1,2,3), c(4,5,6), 0, 3, c(NA, 3L))");
         assertEval(".Call(stats:::C_BinDist, c(1,2,3), c(4,5,6), 0, 3, -5L)");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
index 904c869122..3098d53ec1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
@@ -92,7 +92,7 @@ public class TestRandGenerationFunctions extends TestBase {
         assertEval("set.seed(12); rmultinom('5', 3.1, c(2, 5, 10))");
         // test args validation
         assertEval("rmultinom(1, 1, -0.15)");
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreErrorMessage, "rmultinom('string', 1, 0.15)");
+        assertEval("rmultinom('string', 1, 0.15)");
         assertEval("rmultinom(1, NA, 0.2)");
         assertEval("rmultinom(NA, 1, 0.2)");
     }
-- 
GitLab


From 5450eed99f273155560035a7b33e4a7d0c105822 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 24 Feb 2017 15:00:19 +0100
Subject: [PATCH 057/402] use builtin error context for warnings as well

---
 .../library/methods/MethodsListDispatch.java  |   5 +-
 .../truffle/r/library/tools/ToolsText.java    |   2 +-
 .../oracle/truffle/r/library/utils/Rprof.java |   2 +-
 .../truffle/r/nodes/builtin/base/Assign.java  |  20 +--
 .../builtin/base/BaseGammaFunctions.java      |   2 +-
 .../r/nodes/builtin/base/ChooseBuiltin.java   |   3 +-
 .../truffle/r/nodes/builtin/base/Colon.java   |  16 +-
 .../builtin/base/ConnectionFunctions.java     |  10 +-
 .../truffle/r/nodes/builtin/base/Deparse.java |   2 +-
 .../r/nodes/builtin/base/FileFunctions.java   |  18 +--
 .../r/nodes/builtin/base/GrepFunctions.java   |   6 +-
 .../builtin/base/HiddenInternalFunctions.java |   2 +-
 .../truffle/r/nodes/builtin/base/IsNA.java    |   4 +-
 .../r/nodes/builtin/base/NormalizePath.java   |  22 ++-
 .../truffle/r/nodes/builtin/base/PMinMax.java |   4 +-
 .../truffle/r/nodes/builtin/base/Pretty.java  |   4 +-
 .../truffle/r/nodes/builtin/base/Quit.java    |   8 +-
 .../truffle/r/nodes/builtin/base/Rank.java    |   3 +-
 .../r/nodes/builtin/base/RawFunctions.java    |   2 +-
 .../r/nodes/builtin/base/ReadREnviron.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Rm.java      |   3 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |   2 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Switch.java  |   4 +-
 .../r/nodes/builtin/base/WithVisible.java     |   5 +-
 .../nodes/builtin/base/infix/UpdateField.java |   2 +-
 .../builtin/base/printer/VectorPrinter.java   |   4 +-
 .../r/nodes/builtin/fastr/FastRPkgSource.java |   4 +-
 .../access/ReadVariadicComponentNode.java     |  12 +-
 .../vector/CachedExtractVectorNode.java       |   6 +-
 .../vector/CachedReplaceVectorNode.java       |  24 ++-
 .../nodes/access/vector/CachedVectorNode.java |   4 +-
 .../SpecialAttributesFunctions.java           |  60 +++-----
 .../BinaryMapArithmeticFunctionNode.java      |   4 +-
 .../r/nodes/builtin/RList2EnvNode.java        |   4 +-
 .../truffle/r/nodes/control/IfNode.java       |   2 +-
 .../truffle/r/nodes/control/OperatorNode.java |   6 +
 .../control/ReplacementDispatchNode.java      |   9 +-
 .../r/nodes/function/ArgumentMatcher.java     |  12 +-
 .../truffle/r/nodes/function/RCallNode.java   |   8 +-
 .../r/nodes/function/RCallSpecialNode.java    |   6 +
 .../nodes/function/signature/MissingNode.java |   6 +-
 .../r/nodes/primitive/BinaryMapNode.java      |   4 +-
 .../r/nodes/unary/ConvertBooleanNode.java     |  20 ++-
 .../r/nodes/unary/FirstBooleanNode.java       |   6 +-
 .../truffle/r/nodes/unary/FirstIntNode.java   |   5 +-
 .../r/nodes/unary/UnaryArithmeticNode.java    |  18 ++-
 .../unary/UnaryArithmeticReduceNode.java      |  37 ++---
 .../com/oracle/truffle/r/runtime/RError.java  |  10 +-
 .../truffle/r/runtime/RErrorHandling.java     |  36 +++--
 .../truffle/r/runtime/data/RVector.java       |  19 ++-
 .../truffle/r/runtime/nodes/RBaseNode.java    | 142 ++++++++++++++++++
 .../nodes/builtin/RBuiltinBaseNode.java       |  44 ------
 .../r/runtime/ops/BinaryArithmetic.java       |  30 ++--
 .../truffle/r/runtime/ops/BinaryCompare.java  |   8 +-
 .../truffle/r/runtime/ops/BinaryLogic.java    |   4 +-
 .../r/test/builtins/TestBuiltin_all.java      |   5 +-
 .../r/test/builtins/TestBuiltin_aperm.java    |   2 +-
 .../r/test/builtins/TestBuiltin_array.java    |   2 +-
 .../builtins/TestBuiltin_bitwiseShiftL.java   |   4 +-
 .../builtins/TestBuiltin_bitwiseShiftR.java   |   2 +-
 .../test/builtins/TestBuiltin_copyDFattr.java |  36 ++---
 .../r/test/builtins/TestBuiltin_deparse.java  |   2 +-
 .../r/test/builtins/TestBuiltin_dfltWarn.java |  16 +-
 .../TestBuiltin_extract_dataframe.java        |   4 +-
 .../r/test/builtins/TestBuiltin_factor.java   |   8 +-
 .../r/test/builtins/TestBuiltin_gsub.java     |   2 +-
 .../r/test/builtins/TestBuiltin_isfactor.java |   2 +-
 .../r/test/builtins/TestBuiltin_isna.java     |   4 +-
 .../r/test/builtins/TestBuiltin_levels.java   |   2 +-
 .../r/test/builtins/TestBuiltin_max.java      |   8 +-
 .../r/test/builtins/TestBuiltin_mean.java     |   2 +-
 .../r/test/builtins/TestBuiltin_min.java      |   8 +-
 .../test/builtins/TestBuiltin_operators.java  |   2 +-
 .../r/test/builtins/TestBuiltin_pmax.java     |   2 +-
 .../r/test/builtins/TestBuiltin_pmin.java     |   4 +-
 .../builtins/TestBuiltin_rawConnection.java   |   4 +-
 .../r/test/builtins/TestBuiltin_rep.java      |   4 +-
 .../r/test/builtins/TestBuiltin_scan.java     |   4 +-
 .../r/test/builtins/TestBuiltin_strsplit.java |   3 +-
 .../r/test/builtins/TestBuiltin_sum.java      |   4 +-
 .../library/base/TestSimpleArithmetic.java    |  18 +--
 .../library/base/TestSimpleComparison.java    |  24 +--
 .../library/base/TestSimpleDataFrames.java    |   6 +-
 .../library/base/TestSimpleIfEvaluator.java   |  44 +++---
 .../r/test/library/base/TestSimpleLoop.java   |   2 +-
 .../test/library/base/TestSimpleTruffle.java  |   2 +-
 .../test/library/base/TestSimpleVectors.java  |  58 +++----
 88 files changed, 512 insertions(+), 487 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 8d0e66deea..0cec2ee980 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -130,7 +130,6 @@ public class MethodsListDispatch {
         static {
             Casts casts = new Casts(R_getClassFromCache.class);
             casts.arg(0, "klass").defaultError(RError.Message.GENERIC, "class should be either a character-string name or a class definition").mustBe(stringValue().or(instanceOf(RS4Object.class)));
-
             casts.arg(1, "table").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
         }
 
@@ -408,11 +407,11 @@ public class MethodsListDispatch {
                 }
                 String s = vec.getDataAt(0);
                 if (nonEmpty && s.length() == 0) {
-                    throw RError.error(node, RError.Message.NON_EMPTY_STRING, what);
+                    throw node.error(RError.Message.NON_EMPTY_STRING, what);
                 }
                 return s;
             } else {
-                throw RError.error(node, RError.Message.SINGLE_STRING_WRONG_TYPE, what, classHierarchyNode.executeString(o));
+                throw node.error(RError.Message.SINGLE_STRING_WRONG_TYPE, what, classHierarchyNode.executeString(o));
             }
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
index d412a0a76d..79f1b7df8b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java
@@ -110,7 +110,7 @@ public class ToolsText {
                             }
                             data[i] = RRuntime.LOGICAL_TRUE;
                         } catch (IOException ex) {
-                            RError.warning(this, RError.Message.GENERIC, "IO error during file append");
+                            warning(RError.Message.GENERIC, "IO error during file append");
                             // shouldn't happen, just continue with false result
                         }
                     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index 26a5862074..c074b2217e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -111,7 +111,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
             try {
                 PrintStream out = new PrintStream(new FileOutputStream(filename, append));
                 if (gcProfiling) {
-                    RError.warning(this, RError.Message.GENERIC, "Rprof: gc profiling not supported");
+                    warning(RError.Message.GENERIC, "Rprof: gc profiling not supported");
                 }
                 if (memProfiling) {
                     RDataFactory.addListener(this);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
index f313b51e44..42833c94fe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.LoopNode;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
@@ -56,8 +55,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 @RBuiltin(name = "assign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "envir", "inherits"}, behavior = COMPLEX)
 public abstract class Assign extends RBuiltinNode {
 
-    private final BranchProfile errorProfile = BranchProfile.create();
-    private final BranchProfile warningProfile = BranchProfile.create();
     private final boolean direct;
 
     protected Assign() {
@@ -68,8 +65,9 @@ public abstract class Assign extends RBuiltinNode {
         this.direct = direct;
     }
 
-    private RBaseNode errorContext() {
-        return direct ? this : RError.SHOW_CALLER;
+    @Override
+    protected RBaseNode getErrorContext() {
+        return direct ? this : super.getErrorContext();
     }
 
     /**
@@ -81,11 +79,9 @@ public abstract class Assign extends RBuiltinNode {
         if (len == 1) {
             return xVec.getDataAt(0);
         } else if (len == 0) {
-            errorProfile.enter();
-            throw RError.error(errorContext(), RError.Message.INVALID_FIRST_ARGUMENT);
+            throw error(RError.Message.INVALID_FIRST_ARGUMENT);
         } else {
-            warningProfile.enter();
-            RError.warning(errorContext(), RError.Message.ONLY_FIRST_VARIABLE_NAME);
+            warning(RError.Message.ONLY_FIRST_VARIABLE_NAME);
             return xVec.getDataAt(0);
         }
     }
@@ -125,15 +121,13 @@ public abstract class Assign extends RBuiltinNode {
                 LoopNode.reportLoopCount(this, -1);
             }
             if (env == REnvironment.emptyEnv()) {
-                errorProfile.enter();
-                throw RError.error(errorContext(), RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV);
+                throw error(RError.Message.CANNOT_ASSIGN_IN_EMPTY_ENV);
             }
         }
         try {
             env.put(x, share.execute(value));
         } catch (PutException ex) {
-            errorProfile.enter();
-            throw RError.error(errorContext(), ex);
+            throw error(ex);
         }
         return value;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index ab4304b426..42702fa5b1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -149,7 +149,7 @@ public class BaseGammaFunctions {
                 }
             }
             if (warnNaN) {
-                RError.warning(this, RError.Message.NAN_PRODUCED);
+                warning(RError.Message.NAN_PRODUCED);
             }
             return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
index cef52279d4..d74f7d1718 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
@@ -33,7 +33,6 @@ import java.util.function.IntUnaryOperator;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
@@ -93,7 +92,7 @@ public abstract class ChooseBuiltin extends RBuiltinNode {
 
         double result = Math.round(data);
         if (result != data) {
-            RError.warning(this, Message.CHOOSE_ROUNDING_WARNING, data, (int) result);
+            warning(Message.CHOOSE_ROUNDING_WARNING, data, (int) result);
         }
         return (int) result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index f70e479a57..c6eedfe836 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -201,11 +201,10 @@ public abstract class Colon extends RBuiltinNode {
 
         private void checkLength(int length) {
             if (lengthGreaterOne.profile(length > 1)) {
-                RError.warning(this, RError.Message.ONLY_FIRST_USED, length);
+                warning(RError.Message.ONLY_FIRST_USED, length);
             }
             if (lengthEqualsZero.profile(length == 0)) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, Message.ARGUMENT_LENGTH_0);
+                throw error(Message.ARGUMENT_LENGTH_0);
             }
         }
 
@@ -237,23 +236,20 @@ public abstract class Colon extends RBuiltinNode {
             checkLength(vector.getLength());
             String val = vector.getDataAt(0);
             if (RRuntime.isNA(val)) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.NA_OR_NAN);
+                throw error(RError.Message.NA_OR_NAN);
             }
             // TODO it might be a double or complex string
             int result = RRuntime.string2intNoCheck(val);
             if (RRuntime.isNA(result)) {
-                CompilerDirectives.transferToInterpreter();
-                RError.warning(this, RError.Message.NA_INTRODUCED_COERCION);
-                throw RError.error(this, RError.Message.NA_OR_NAN);
+                warning(RError.Message.NA_INTRODUCED_COERCION);
+                throw error(RError.Message.NA_OR_NAN);
             }
             return result;
         }
 
         @Fallback
         protected int doOther(@SuppressWarnings("unused") Object value) {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, Message.ARGUMENT_LENGTH_0);
+            throw error(Message.ARGUMENT_LENGTH_0);
         }
 
         protected static boolean isIntValue(double d) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index b4203c3d0f..c5c88dd46d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -220,14 +220,14 @@ public abstract class ConnectionFunctions {
                 } else {
                     if (!(open.equals("w+") || open.equals("w+b"))) {
                         open = "w+";
-                        RError.warning(RError.SHOW_CALLER, RError.Message.FILE_OPEN_TMP);
+                        warning(RError.Message.FILE_OPEN_TMP);
                     }
                 }
             }
             try {
                 return new FileRConnection(path, open).asVector();
             } catch (IOException ex) {
-                RError.warning(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
+                warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             }
         }
@@ -265,7 +265,7 @@ public abstract class ConnectionFunctions {
         }
 
         private RError reportError(String path, IOException ex) throws RError {
-            RError.warning(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage());
+            warning(RError.Message.CANNOT_OPEN_FILE, path, ex.getMessage());
             throw error(RError.Message.CANNOT_OPEN_CONNECTION);
         }
     }
@@ -506,7 +506,7 @@ public abstract class ConnectionFunctions {
                     throw error(RError.Message.INVALID_CONNECTION);
                 }
                 if (baseConn.isOpen()) {
-                    RError.warning(RError.SHOW_CALLER, RError.Message.ALREADY_OPEN_CONNECTION);
+                    warning(RError.Message.ALREADY_OPEN_CONNECTION);
                     return RNull.instance;
                 }
                 baseConn.open(open);
@@ -756,7 +756,7 @@ public abstract class ConnectionFunctions {
                     final int writeLen = Math.min(s.length(), nc);
                     int pad = nc - s.length();
                     if (pad > 0) {
-                        RError.warning(RError.SHOW_CALLER, RError.Message.MORE_CHARACTERS);
+                        warning(RError.Message.MORE_CHARACTERS);
                     }
                     openConn.writeChar(s.substring(0, writeLen), pad, getSepFor(sep, i), useBytes);
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
index e1abc2461e..c00c28bee4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
@@ -43,7 +43,7 @@ public abstract class Deparse extends RBuiltinNode {
     protected RStringVector deparse(Object expr, int widthCutoffArg, boolean backtick, int control, int nlines) {
         int widthCutoff = widthCutoffArg;
         if (widthCutoff == RRuntime.INT_NA || widthCutoff < RDeparse.MIN_Cutoff || widthCutoff > RDeparse.MAX_Cutoff) {
-            RError.warning(this, RError.Message.DEPARSE_INVALID_CUTOFF);
+            warning(RError.Message.DEPARSE_INVALID_CUTOFF);
             widthCutoff = RDeparse.DEFAULT_Cutoff;
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index bd1710371d..ef3d5d4f01 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -212,7 +212,7 @@ public class FileFunctions {
                     out.write(buf);
                     return true;
                 } catch (IOException ex) {
-                    RError.warning(this, RError.Message.FILE_APPEND_WRITE);
+                    warning(RError.Message.FILE_APPEND_WRITE);
                     return false;
                 }
             }
@@ -243,7 +243,7 @@ public class FileFunctions {
                     } catch (IOException ex) {
                         ok = false;
                         if (showWarnings == RRuntime.LOGICAL_TRUE) {
-                            RError.warning(this, RError.Message.FILE_CANNOT_CREATE, path);
+                            warning(RError.Message.FILE_CANNOT_CREATE, path);
                         }
                     }
                     status[i] = RRuntime.asLogical(ok);
@@ -461,7 +461,7 @@ public class FileFunctions {
                         }
                     } catch (UnsupportedOperationException | IOException ex) {
                         status[i] = RRuntime.LOGICAL_FALSE;
-                        RError.warning(this, RError.Message.FILE_CANNOT_LINK, from, to, ex.getMessage());
+                        warning(RError.Message.FILE_CANNOT_LINK, from, to, ex.getMessage());
                     }
                 }
             }
@@ -522,7 +522,7 @@ public class FileFunctions {
                     boolean ok = f.delete();
                     status[i] = RRuntime.asLogical(ok);
                     if (!ok) {
-                        RError.warning(this, RError.Message.FILE_CANNOT_REMOVE, path);
+                        warning(RError.Message.FILE_CANNOT_REMOVE, path);
                     }
                 }
             }
@@ -558,7 +558,7 @@ public class FileFunctions {
                     boolean ok = new File(Utils.tildeExpand(from)).renameTo(new File(Utils.tildeExpand(to)));
                     status[i] = RRuntime.asLogical(ok);
                     if (!ok) {
-                        RError.warning(this, RError.Message.FILE_CANNOT_RENAME, from, to);
+                        warning(RError.Message.FILE_CANNOT_RENAME, from, to);
                     }
                 }
             }
@@ -703,7 +703,7 @@ public class FileFunctions {
 
         private boolean check(boolean value, String argName) {
             if (value) {
-                RError.warning(this, RError.Message.GENERIC, "'" + argName + "'" + " is not implemented");
+                warning(RError.Message.GENERIC, "'" + argName + "'" + " is not implemented");
             }
             return value;
         }
@@ -940,7 +940,7 @@ public class FileFunctions {
                 }
                 if (recursive) {
                     if (toDir == null) {
-                        RError.warning(this, RError.Message.FILE_COPY_RECURSIVE_IGNORED);
+                        warning(RError.Message.FILE_COPY_RECURSIVE_IGNORED);
                         recursive = false;
                     }
                 }
@@ -978,7 +978,7 @@ public class FileFunctions {
                         }
                     } catch (UnsupportedOperationException | IOException ex) {
                         status[i] = RRuntime.LOGICAL_FALSE;
-                        RError.warning(this, RError.Message.FILE_CANNOT_COPY, from, to, ex.getMessage());
+                        warning(RError.Message.FILE_CANNOT_COPY, from, to, ex.getMessage());
                     }
                 }
             }
@@ -1243,7 +1243,7 @@ public class FileFunctions {
                 return true;
             } catch (IOException ex) {
                 if (showWarnings) {
-                    RError.warning(this, RError.Message.DIR_CANNOT_CREATE, path);
+                    warning(RError.Message.DIR_CANNOT_CREATE, path);
                 }
                 return false;
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 184c3dbf50..2bfc22099d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -125,13 +125,13 @@ public class GrepFunctions {
 
         protected void checkCaseFixed(boolean ignoreCase, boolean fixed) {
             if (ignoreCase && fixed) {
-                RError.warning(this, RError.Message.ARGUMENT_IGNORED, "ignore.case = TRUE");
+                warning(RError.Message.ARGUMENT_IGNORED, "ignore.case = TRUE");
             }
         }
 
         protected boolean checkPerlFixed(boolean perl, boolean fixed) {
             if (fixed && perl) {
-                RError.warning(this, RError.Message.ARGUMENT_IGNORED, "perl = TRUE");
+                warning(RError.Message.ARGUMENT_IGNORED, "perl = TRUE");
                 return false;
             } else {
                 return perl;
@@ -142,7 +142,7 @@ public class GrepFunctions {
             if (arg.getLength() < 1) {
                 throw error(RError.Message.INVALID_ARGUMENT, name);
             } else if (arg.getLength() > 1) {
-                RError.warning(this, RError.Message.ARGUMENT_ONLY_FIRST, name);
+                warning(RError.Message.ARGUMENT_ONLY_FIRST, name);
             }
             return arg.getDataAt(0);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index 0044450c3a..7c155fb9c0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -233,7 +233,7 @@ public class HiddenInternalFunctions {
                 if (compression == 2 || compression == 3) {
                     RCompression.Type type = RCompression.Type.fromTypeChar(dbData[4]);
                     if (type == null) {
-                        RError.warning(this, RError.Message.GENERIC, "unknown compression type");
+                        warning(RError.Message.GENERIC, "unknown compression type");
                         return RNull.instance;
                     }
                     byte[] data = new byte[length - 5];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
index 39826ee9a7..b2a9cb0863 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
@@ -191,7 +191,7 @@ public abstract class IsNA extends RBuiltinNode {
 
     @Specialization
     protected RLogicalVector isNA(RNull value) {
-        RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, value.getRType().getName());
+        warning(RError.Message.IS_NA_TO_NON_VECTOR, value.getRType().getName());
         return RDataFactory.createEmptyLogicalVector();
     }
 
@@ -199,7 +199,7 @@ public abstract class IsNA extends RBuiltinNode {
     // fallback
     @Fallback
     protected byte isNA(Object value) {
-        RError.warning(this, RError.Message.IS_NA_TO_NON_VECTOR, ((RTypedValue) value).getRType().getName());
+        warning(RError.Message.IS_NA_TO_NON_VECTOR, ((RTypedValue) value).getRType().getName());
         return RRuntime.LOGICAL_FALSE;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
index da6ed4bb29..501f00d7cc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
@@ -39,7 +39,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
@@ -77,20 +76,19 @@ public abstract class NormalizePath extends RBuiltinNode {
                 if (doesNotNeedToWork.profile(mustWork == RRuntime.LOGICAL_FALSE)) {
                     // no error or warning
                 } else {
-                    Object[] errorArgs;
-                    Message msg;
-                    if (e instanceof NoSuchFileException) {
-                        errorArgs = new Object[]{i + 1, expandPath};
-                        msg = Message.NORMALIZE_PATH_NOSUCH;
-                    } else {
-                        errorArgs = new Object[]{e.toString()};
-                        msg = Message.GENERIC;
-                    }
                     if (mustWork == RRuntime.LOGICAL_TRUE) {
-                        throw error(msg, errorArgs);
+                        if (e instanceof NoSuchFileException) {
+                            throw error(Message.NORMALIZE_PATH_NOSUCH, i + 1, expandPath);
+                        } else {
+                            throw error(Message.GENERIC, e.toString());
+                        }
                     } else {
                         // NA means warning
-                        RError.warning(this, msg, errorArgs);
+                        if (e instanceof NoSuchFileException) {
+                            warning(Message.NORMALIZE_PATH_NOSUCH, i + 1, expandPath);
+                        } else {
+                            warning(Message.GENERIC, e.toString());
+                        }
                     }
                 }
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index ac3c210e4d..8986a6ec19 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -176,7 +176,7 @@ public abstract class PMinMax extends RBuiltinNode {
                     RAbstractIntVector vec = (RAbstractIntVector) argValues[j];
                     na.enable(vec);
                     if (vec.getLength() > 1 && vec.getLength() < maxLength && !warningAdded) {
-                        RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED);
+                        warning(RError.Message.ARG_RECYCYLED);
                         warningAdded = true;
                     }
                     int v = vec.getDataAt(i % vec.getLength());
@@ -280,7 +280,7 @@ public abstract class PMinMax extends RBuiltinNode {
                 RAbstractDoubleVector vec = (RAbstractDoubleVector) argValues[j];
                 na.enable(vec);
                 if (vec.getLength() > 1 && vec.getLength() < maxLength && !warningAdded) {
-                    RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED);
+                    warning(RError.Message.ARG_RECYCYLED);
                     warningAdded = true;
                 }
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
index 0b099e7803..52f90c316f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
@@ -122,10 +122,10 @@ public abstract class Pretty extends RBuiltinNode {
         }
 
         if (cell < 20 * Double.MIN_VALUE) {
-            RError.warning(this, RError.Message.GENERIC, "Internal(pretty()): very small range.. corrected");
+            warning(RError.Message.GENERIC, "Internal(pretty()): very small range.. corrected");
             cell = 20 * Double.MIN_VALUE;
         } else if (cell * 10 > Double.MAX_VALUE) {
-            RError.warning(this, RError.Message.GENERIC, "Internal(pretty()): very large range.. corrected");
+            warning(RError.Message.GENERIC, "Internal(pretty()): very large range.. corrected");
             cell = .1 * Double.MAX_VALUE;
         }
         /*
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index a9e765ebd9..d3e1003add 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -54,19 +54,19 @@ public abstract class Quit extends RBuiltinNode {
     protected Object doQuit(String save, final int status, final byte runLastIn) {
         byte runLast = runLastIn;
         if (RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser()) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.BROWSER_QUIT);
+            warning(RError.Message.BROWSER_QUIT);
             return RNull.instance;
         }
         RStartParams.SA_TYPE ask = checkSaveValue(save);
         if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().getConsoleHandler().isInteractive()) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.QUIT_ASK_INTERACTIVE);
+            warning(RError.Message.QUIT_ASK_INTERACTIVE);
         }
         if (status == RRuntime.INT_NA) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.QUIT_INVALID_STATUS);
+            warning(RError.Message.QUIT_INVALID_STATUS);
             runLast = RRuntime.LOGICAL_FALSE;
         }
         if (runLast == RRuntime.LOGICAL_NA) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.QUIT_INVALID_RUNLAST);
+            warning(RError.Message.QUIT_INVALID_RUNLAST);
             runLast = RRuntime.LOGICAL_FALSE;
         }
         RCleanUp.cleanUp(ask, status, RRuntime.fromLogical(runLast));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
index bbb518539e..aa0fff3a30 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
@@ -20,7 +20,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_TIES_FOR_RANK;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_VALUE;
 import static com.oracle.truffle.r.runtime.RError.Message.RANK_LARGE_N;
@@ -95,7 +94,7 @@ public abstract class Rank extends RBuiltinNode {
         if (n > xa.getLength()) {
             errorProfile.enter();
             n = xa.getLength();
-            RError.warning(SHOW_CALLER, RANK_LARGE_N);
+            warning(RANK_LARGE_N);
         }
 
         TiesKind tiesKind = getTiesKind(tiesMethod);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
index 633373acf3..74712ceaeb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
@@ -60,7 +60,7 @@ public class RawFunctions {
         @Specialization
         protected RRawVector charToRaw(RAbstractStringVector x) {
             if (x.getLength() > 1) {
-                RError.warning(this, RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE);
+                warning(RError.Message.ARG_SHOULD_BE_CHARACTER_VECTOR_LENGTH_ONE);
             }
             String s = x.getDataAt(0);
             byte[] data = new byte[s.length()];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
index 0c126db0a0..0614534417 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
@@ -53,7 +53,7 @@ public abstract class ReadREnviron extends RBuiltinNode {
         try {
             RContext.getInstance().stateREnvVars.readEnvironFile(path);
         } catch (FileNotFoundException ex) {
-            RError.warning(this, RError.Message.GENERIC, ex.getMessage());
+            warning(RError.Message.GENERIC, ex.getMessage());
             result = RRuntime.LOGICAL_FALSE;
         } catch (IOException ex) {
             throw error(RError.Message.GENERIC, ex.getMessage());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
index 0eca527fe5..d1378ebf1b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_FIRST_ARGUMENT;
 import static com.oracle.truffle.r.runtime.RError.Message.USE_NULL_ENV_DEFUNCT;
@@ -101,7 +100,7 @@ public abstract class Rm extends RBuiltinNode {
             }
         }
         if (fs == null) {
-            RError.warning(SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, x);
+            warning(RError.Message.UNKNOWN_OBJECT, x);
         } else {
             // use null (not an R value) to represent "undefined"
             FrameSlotChangeMonitor.setObjectAndInvalidate(frame, fs, null, false, invalidateProfile);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 6942310e89..b6ae842dc0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -413,7 +413,7 @@ public abstract class Scan extends RBuiltinNode {
 
         if (n > 0 && n < nc) {
             if (!fill) {
-                RError.warning(this, RError.Message.ITEMS_NOT_MULTIPLE);
+                warning(RError.Message.ITEMS_NOT_MULTIPLE);
             }
             fillEmpty(n, nc, records, list, data);
             records++;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index b776d9c389..3fad457309 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -1010,7 +1010,7 @@ public final class SeqFunctions {
                 throw error(seqFastPath ? RError.Message.MUST_BE_POSITIVE_SD : RError.Message.MUST_BE_POSITIVE, seqFastPath ? "length" : "length.out");
             }
             if (getLength(frame, lengthOut) != 1) {
-                RError.warning(this, RError.Message.FIRST_ELEMENT_USED, "length.out");
+                warning(RError.Message.FIRST_ELEMENT_USED, "length.out");
             }
             return (int) Math.ceil(len);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
index 805cf422b4..c3e59f1710 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
@@ -73,7 +73,7 @@ public abstract class Switch extends RBuiltinNode {
 
     private Object doSwitchString(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) {
         if (noAlternativesProfile.profile(optionalArgs.getLength() == 0)) {
-            RError.warning(this, RError.Message.NO_ALTERNATIVES_IN_SWITCH);
+            warning(RError.Message.NO_ALTERNATIVES_IN_SWITCH);
             return null;
         }
         Object[] optionalArgValues = optionalArgs.getArguments();
@@ -167,7 +167,7 @@ public abstract class Switch extends RBuiltinNode {
 
     private Object doSwitchInt(VirtualFrame frame, int index, RArgsValuesAndNames optionalArgs) {
         if (noAlternativesProfile.profile(optionalArgs.getLength() == 0)) {
-            RError.warning(this, RError.Message.NO_ALTERNATIVES_IN_SWITCH);
+            warning(RError.Message.NO_ALTERNATIVES_IN_SWITCH);
             return null;
         }
         Object[] optionalArgValues = optionalArgs.getArguments();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
index 4db217cd40..87accb1d72 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.visibility.GetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -57,8 +56,7 @@ final class WithVisibleSpecial extends RNode {
     public Object execute(VirtualFrame frame) {
         Object value = delegate.visibleExecute(frame);
         if (value == RMissing.instance) {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, Message.ARGUMENT_MISSING, "x");
+            throw error(Message.ARGUMENT_MISSING, "x");
         }
         return RDataFactory.createList(new Object[]{value, RRuntime.asLogical(visibility.execute(frame))}, WithVisible.LISTNAMES);
     }
@@ -98,7 +96,6 @@ public abstract class WithVisible extends RBuiltinNode {
 
     @Specialization
     protected RList withVisible(@SuppressWarnings("unused") RMissing x) {
-        CompilerDirectives.transferToInterpreter();
         throw error(Message.ARGUMENT_MISSING, "x");
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
index 12835f2b47..5d55e54d97 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
@@ -142,7 +142,7 @@ public abstract class UpdateField extends RBuiltinNode {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 castList = insert(CastListNodeGen.create(true, true, false));
             }
-            RError.warning(this, RError.Message.COERCING_LHS_TO_LIST);
+            warning(RError.Message.COERCING_LHS_TO_LIST);
             return castList.executeList(vector);
         }
         return vector;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
index 8d22e642dc..611ee0d6ea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
@@ -262,10 +262,10 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
 
             /* PR#850 */
             if (rl != null && r > rl.getLength()) {
-                throw RError.error(printCtx.printerNode(), RError.Message.GENERIC, "too few row labels");
+                throw printCtx.printerNode().error(RError.Message.GENERIC, "too few row labels");
             }
             if (cl != null && c > cl.getLength()) {
-                throw RError.error(printCtx.printerNode(), RError.Message.GENERIC, "too few column labels");
+                throw printCtx.printerNode().error(RError.Message.GENERIC, "too few column labels");
             }
             if (r == 0 && c == 0) { // FIXME? names(dimnames(.)) :
                 out.print("<0 x 0 matrix>");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
index eaa4f18e37..b0a67b019a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
@@ -142,12 +142,12 @@ public abstract class FastRPkgSource extends RBuiltinNode {
 
     @TruffleBoundary
     private void notFound(String pkg) {
-        RError.warning(this, RError.Message.GENERIC, String.format("namespace '%s' not found - ignoring", pkg));
+        warning(RError.Message.GENERIC, String.format("namespace '%s' not found - ignoring", pkg));
     }
 
     @TruffleBoundary
     private void noDeparse(String pkg, String fname) {
-        RError.warning(this, RError.Message.GENERIC, String.format("function '%s::%s' failed to deparse - ignoring", pkg, fname));
+        warning(RError.Message.GENERIC, String.format("function '%s::%s' failed to deparse - ignoring", pkg, fname));
     }
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java
index 3b81ac8dd5..5b4dd38552 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.access;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
@@ -51,8 +50,6 @@ public class ReadVariadicComponentNode extends RSourceSectionNode implements RSy
     private final int index;
     private final String name;
 
-    private final BranchProfile errorBranch = BranchProfile.create();
-
     public ReadVariadicComponentNode(SourceSection src, int index) {
         super(src);
         this.index = index;
@@ -65,17 +62,14 @@ public class ReadVariadicComponentNode extends RSourceSectionNode implements RSy
 
         Object args = lookup.execute(frame);
         if (args == null) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.NO_DOT_DOT, index + 1);
+            throw error(RError.Message.NO_DOT_DOT, index + 1);
         }
         RArgsValuesAndNames argsValuesAndNames = (RArgsValuesAndNames) args;
         if (argsValuesAndNames.isEmpty()) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.NO_LIST_FOR_CDR);
+            throw error(RError.Message.NO_LIST_FOR_CDR);
         }
         if (argsValuesAndNames.getLength() <= index) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.DOT_DOT_SHORT, index + 1);
+            throw error(RError.Message.DOT_DOT_SHORT, index + 1);
         }
         Object ret = argsValuesAndNames.getArgument(index);
         return ret == null ? RMissing.instance : promiseHelper.checkEvaluate(frame, ret);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index 207a56eb78..611ad11ba4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -248,8 +248,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
 
     private Object doEnvironment(REnvironment env, Object[] positions) {
         if (mode.isSubset()) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName());
+            throw error(RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName());
         }
 
         String positionString = tryCastSingleString(positionsCheckNode, positions);
@@ -257,8 +256,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
             Object obj = env.get(positionString);
             return obj == null ? RNull.instance : obj;
         }
-        errorBranch.enter();
-        throw RError.error(this, RError.Message.WRONG_ARGS_SUBSET_ENV);
+        throw error(RError.Message.WRONG_ARGS_SUBSET_ENV);
     }
 
     private boolean isMissingSingleDimension() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
index 6e7fff3d2d..68c08d76c2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
@@ -275,11 +275,10 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
              */
             if ((this.numberOfDimensions > 1 && isNullValue()) || (replacementLength != valueLength && replacementLength % valueLength != 0)) {
                 if (this.numberOfDimensions > 1) {
-                    errorBranch.enter();
-                    throw RError.error(this, RError.Message.NOT_MULTIPLE_REPLACEMENT);
+                    throw error(RError.Message.NOT_MULTIPLE_REPLACEMENT);
                 } else {
                     warningBranch.enter();
-                    RError.warning(this, RError.Message.NOT_MULTIPLE_REPLACEMENT);
+                    warning(RError.Message.NOT_MULTIPLE_REPLACEMENT);
                 }
             }
         }
@@ -410,24 +409,21 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
     private void verifyValueLength(PositionProfile[] positionProfiles, int valueLength) {
         if (mode.isSubscript()) {
             if (!isList()) {
-                errorBranch.enter();
                 if (isNullValue()) {
-                    throw RError.error(this, RError.Message.MORE_SUPPLIED_REPLACE);
+                    throw error(RError.Message.MORE_SUPPLIED_REPLACE);
                 } else if (valueLength == 0) {
-                    throw RError.error(this, RError.Message.REPLACEMENT_0);
+                    throw error(RError.Message.REPLACEMENT_0);
                 } else {
-                    throw RError.error(this, RError.Message.MORE_SUPPLIED_REPLACE);
+                    throw error(RError.Message.MORE_SUPPLIED_REPLACE);
                 }
             }
         } else {
             assert mode.isSubset();
             if (!isNullValue() || this.numberOfDimensions == 1) {
                 if (valueLength == 0) {
-                    errorBranch.enter();
-                    throw RError.error(this, RError.Message.REPLACEMENT_0);
+                    throw error(RError.Message.REPLACEMENT_0);
                 } else if (positionsCheckNode.getContainsNA(positionProfiles)) {
-                    errorBranch.enter();
-                    throw RError.error(this, RError.Message.NA_SUBSCRIPTED);
+                    throw error(RError.Message.NA_SUBSCRIPTED);
                 }
             }
         }
@@ -461,14 +457,12 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
 
     private Object doEnvironment(REnvironment env, Object[] positions, Object originalValues) {
         if (mode.isSubset()) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName());
+            throw error(RError.Message.OBJECT_NOT_SUBSETTABLE, RType.Environment.getName());
         }
 
         String positionString = tryCastSingleString(positionsCheckNode, positions);
         if (positionString == null) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.WRONG_ARGS_SUBSET_ENV);
+            throw error(RError.Message.WRONG_ARGS_SUBSET_ENV);
         }
 
         try {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java
index ddd61957c7..7755156678 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -54,7 +53,6 @@ abstract class CachedVectorNode extends RBaseNode {
      */
     protected final boolean recursive;
 
-    protected final BranchProfile errorBranch = BranchProfile.create();
     protected final int numberOfDimensions;
     private final int filteredPositionsLength;
 
@@ -75,7 +73,7 @@ abstract class CachedVectorNode extends RBaseNode {
         }
         if (!isSubsetable(vectorType)) {
             error = () -> {
-                throw RError.error(this, RError.Message.OBJECT_NOT_SUBSETTABLE, vectorType.getName());
+                throw error(RError.Message.OBJECT_NOT_SUBSETTABLE, vectorType.getName());
             };
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
index 4eb7f700ca..cab5bc6f2b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
@@ -325,7 +325,6 @@ public final class SpecialAttributesFunctions {
 
         @Specialization(insertBefore = "setAttrInAttributable")
         protected void setNamesInVector(RAbstractVector x, RStringVector newNames,
-                        @Cached("create()") BranchProfile namesTooLongProfile,
                         @Cached("createBinaryProfile()") ConditionProfile useDimNamesProfile,
                         @Cached("create()") GetDimAttributeNode getDimNode,
                         @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
@@ -335,8 +334,8 @@ public final class SpecialAttributesFunctions {
                         @Cached("create()") ShareObjectNode updateRefCountNode) {
             RAbstractVector xProfiled = xTypeProfile.profile(x);
             if (newNames.getLength() > xProfiled.getLength()) {
-                namesTooLongProfile.enter();
-                throw RError.error(this, RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, RRuntime.NAMES_ATTR_KEY, newNames.getLength(), xProfiled.getLength());
+                CompilerDirectives.transferToInterpreter();
+                throw error(RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, RRuntime.NAMES_ATTR_KEY, newNames.getLength(), xProfiled.getLength());
             }
 
             int[] dimensions = getDimNode.getDimensions(x);
@@ -466,9 +465,6 @@ public final class SpecialAttributesFunctions {
     public abstract static class SetDimAttributeNode extends SetSpecialAttributeNode {
 
         private final ConditionProfile nullDimProfile = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile naDimProfile = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile negativeDimProfile = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile dimNotMatchLengthProfile = ConditionProfile.createBinaryProfile();
         private final ValueProfile contArgClassProfile = ValueProfile.createClassProfile();
         private final ValueProfile dimArgClassProfile = ValueProfile.createClassProfile();
         private final LoopConditionProfile verifyLoopProfile = LoopConditionProfile.createCountingProfile();
@@ -552,14 +548,13 @@ public final class SpecialAttributesFunctions {
 
         private void verifyOneDimensions(int vectorLength, int dim) {
             int length = dim;
-            if (naDimProfile.profile(RRuntime.isNA(dim))) {
-                throw RError.error(this, RError.Message.DIMS_CONTAIN_NA);
-            } else if (negativeDimProfile.profile(dim < 0)) {
-                throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
+            if (RRuntime.isNA(dim)) {
+                throw error(RError.Message.DIMS_CONTAIN_NA);
+            } else if (dim < 0) {
+                throw error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
             }
-            if (dimNotMatchLengthProfile.profile(length != vectorLength && vectorLength > 0)) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
+            if (length != vectorLength && vectorLength > 0) {
+                throw error(RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
             }
         }
 
@@ -570,18 +565,15 @@ public final class SpecialAttributesFunctions {
             int length = 1;
             for (int i = 0; i < dimLen; i++) {
                 int dim = dimsProfiled.getDataAt(i);
-                if (naDimProfile.profile(RRuntime.isNA(dim))) {
-                    CompilerDirectives.transferToInterpreter();
-                    throw RError.error(this, RError.Message.DIMS_CONTAIN_NA);
-                } else if (negativeDimProfile.profile(dim < 0)) {
-                    CompilerDirectives.transferToInterpreter();
-                    throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
+                if (RRuntime.isNA(dim)) {
+                    throw error(RError.Message.DIMS_CONTAIN_NA);
+                } else if (dim < 0) {
+                    throw error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
                 }
                 length *= dim;
             }
             if (length != vectorLength && vectorLength > 0) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
+                throw error(RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
             }
         }
     }
@@ -610,7 +602,6 @@ public final class SpecialAttributesFunctions {
         private final ConditionProfile nullDimsProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile nonEmptyDimsProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile twoDimsOrMoreProfile = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile isContainerProfile = ConditionProfile.createBinaryProfile();
 
         protected GetDimAttributeNode() {
             super(RRuntime.DIM_ATTR_KEY);
@@ -680,7 +671,7 @@ public final class SpecialAttributesFunctions {
         }
 
         public int nrows(Object x) {
-            if (isContainerProfile.profile(x instanceof RAbstractContainer)) {
+            if (x instanceof RAbstractContainer) {
                 RAbstractContainer xa = (RAbstractContainer) x;
                 int[] dims = getDimensions(xa);
                 if (nonEmptyDimsProfile.profile(dims != null && dims.length > 0)) {
@@ -689,12 +680,12 @@ public final class SpecialAttributesFunctions {
                     return xa.getLength();
                 }
             } else {
-                throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX);
+                throw error(RError.Message.OBJECT_NOT_MATRIX);
             }
         }
 
         public int ncols(Object x) {
-            if (isContainerProfile.profile(x instanceof RAbstractContainer)) {
+            if (x instanceof RAbstractContainer) {
                 RAbstractContainer xa = (RAbstractContainer) x;
                 int[] dims = getDimensions(xa);
                 if (nonEmptyDimsProfile.profile(dims != null && dims.length > 0)) {
@@ -707,7 +698,7 @@ public final class SpecialAttributesFunctions {
                     return 1;
                 }
             } else {
-                throw RError.error(RError.SHOW_CALLER2, RError.Message.OBJECT_NOT_MATRIX);
+                throw error(RError.Message.OBJECT_NOT_MATRIX);
             }
         }
     }
@@ -753,10 +744,7 @@ public final class SpecialAttributesFunctions {
         @Specialization(insertBefore = "setAttrInAttributable")
         protected void setDimNamesInVector(RVector<?> x, RList newDimNames,
                         @Cached("create()") GetDimAttributeNode getDimNode,
-                        @Cached("create()") BranchProfile nullDimsProfile,
-                        @Cached("create()") BranchProfile dimsLengthProfile,
                         @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
-                        @Cached("create()") BranchProfile invalidDimProfile,
                         @Cached("create()") BranchProfile nullDimProfile,
                         @Cached("create()") BranchProfile resizeDimsProfile,
                         @Cached("create()") BranchProfile attrNullProfile,
@@ -765,14 +753,12 @@ public final class SpecialAttributesFunctions {
                         @Cached("create()") ShareObjectNode updateRefCountNode) {
             int[] dimensions = getDimNode.getDimensions(x);
             if (dimensions == null) {
-                nullDimsProfile.enter();
-                throw RError.error(this, RError.Message.DIMNAMES_NONARRAY);
+                throw error(RError.Message.DIMNAMES_NONARRAY);
             }
             int newDimNamesLength = newDimNames.getLength();
             if (newDimNamesLength > dimensions.length) {
-                dimsLengthProfile.enter();
-                throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength,
-                                dimensions.length);
+                CompilerDirectives.transferToInterpreter();
+                throw error(RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, dimensions.length);
             }
 
             loopProfile.profileCounted(newDimNamesLength);
@@ -781,8 +767,8 @@ public final class SpecialAttributesFunctions {
 
                 if ((dimObject instanceof String && dimensions[i] != 1) ||
                                 (dimObject instanceof RStringVector && !isValidDimLength((RStringVector) dimObject, dimensions[i]))) {
-                    invalidDimProfile.enter();
-                    throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
+                    CompilerDirectives.transferToInterpreter();
+                    throw error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
                 }
 
                 if (dimObject == null || (dimObject instanceof RStringVector && ((RStringVector) dimObject).getLength() == 0)) {
@@ -1091,7 +1077,7 @@ public final class SpecialAttributesFunctions {
                             // also
                             // does not update the 'class' attr with other, possibly
                             // valid classes when it reaches this error.
-                            throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor");
+                            throw error(RError.Message.ADDING_INVALID_CLASS, "factor");
                         }
                     }
                 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
index c5e9599bc4..673c3be0be 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
@@ -162,7 +162,7 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo
                 return RDataFactory.createComplexRealOne();
             } else if (this.arithmetic instanceof BinaryArithmetic.Mod) {
                 // CORNER: Must throw error on modulo operation on complex numbers.
-                throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX);
+                throw error(RError.Message.UNIMPLEMENTED_COMPLEX);
             }
             return RRuntime.createComplexNA();
         }
@@ -172,7 +172,7 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo
                 return RDataFactory.createComplex(Double.NaN, Double.NaN);
             } else if (this.arithmetic instanceof BinaryArithmetic.Mod) {
                 // CORNER: Must throw error on modulo operation on complex numbers.
-                throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX);
+                throw error(RError.Message.UNIMPLEMENTED_COMPLEX);
             }
             return RRuntime.createComplexNA();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java
index cc2264b97c..c7491ac86c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java
@@ -50,12 +50,12 @@ public final class RList2EnvNode extends RBaseNode {
         }
         RStringVector names = list.getNames();
         if (names == null) {
-            throw RError.error(this, RError.Message.LIST_NAMES_SAME_LENGTH);
+            throw error(RError.Message.LIST_NAMES_SAME_LENGTH);
         }
         for (int i = list.getLength() - 1; i >= 0; i--) {
             String name = names.getDataAt(i);
             if (!ignoreMissingNames && name.length() == 0) {
-                throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE);
+                throw error(RError.Message.ZERO_LENGTH_VARIABLE);
             }
             // in case of duplicates, last element in list wins
             if (env.get(name) == null) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java
index ae9a2cf35d..d94fd6738d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java
@@ -57,7 +57,7 @@ public final class IfNode extends OperatorNode {
         byte cond = condition.executeByte(frame);
         if (cond == RRuntime.LOGICAL_NA) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.NA_UNEXP);
+            throw error(RError.Message.NA_UNEXP);
         }
         assert cond == RRuntime.LOGICAL_FALSE || cond == RRuntime.LOGICAL_TRUE : "logical value none of TRUE|FALSE|NA";
         return conditionProfile.profile(cond == RRuntime.LOGICAL_TRUE);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java
index 9a85a3d6f4..03698070ae 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.control;
 
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -41,4 +42,9 @@ public abstract class OperatorNode extends RSourceSectionNode implements RSyntax
     public final RSyntaxLookup getSyntaxLHS() {
         return operator;
     }
+
+    @Override
+    protected RBaseNode getErrorContext() {
+        return this;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
index 4be2260ed9..797c096ae9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
@@ -110,8 +110,7 @@ public final class ReplacementDispatchNode extends OperatorNode {
             if (c.getValue() instanceof String) {
                 name = (String) c.getValue();
             } else {
-                // "this" needs to be initialized for error reporting to work
-                throw RError.error(this, RError.Message.INVALID_LHS, "do_set");
+                throw error(RError.Message.INVALID_LHS, "do_set");
             }
         } else {
             throw RInternalError.unimplemented("unexpected lhs type in replacement: " + lhsSyntax.getClass());
@@ -144,9 +143,9 @@ public final class ReplacementDispatchNode extends OperatorNode {
         while (!(current instanceof RSyntaxLookup)) {
             if (!(current instanceof RSyntaxCall)) {
                 if (current instanceof RSyntaxConstant && ((RSyntaxConstant) current).getValue() == RNull.instance) {
-                    throw RError.error(this, RError.Message.INVALID_NULL_LHS);
+                    throw error(RError.Message.INVALID_NULL_LHS);
                 } else {
-                    throw RError.error(this, RError.Message.NON_LANG_ASSIGNMENT_TARGET);
+                    throw error(RError.Message.NON_LANG_ASSIGNMENT_TARGET);
                 }
             }
             RSyntaxCall call = (RSyntaxCall) current;
@@ -154,7 +153,7 @@ public final class ReplacementDispatchNode extends OperatorNode {
 
             RSyntaxElement syntaxLHS = call.getSyntaxLHS();
             if (call.getSyntaxArguments().length == 0 || !(syntaxLHS instanceof RSyntaxLookup || isNamespaceLookupCall(syntaxLHS))) {
-                throw RError.error(this, RError.Message.INVALID_NULL_LHS);
+                throw error(RError.Message.INVALID_NULL_LHS);
             }
             current = call.getSyntaxArguments()[0];
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index 30fc0680a8..1cf534c2eb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -600,7 +600,7 @@ public class ArgumentMatcher {
 
                     // one unused argument
                     CompilerDirectives.transferToInterpreter();
-                    throw RError.error(callingNode, RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex));
+                    throw callingNode.error(RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex));
                 }
 
                 CompilerDirectives.transferToInterpreter();
@@ -615,7 +615,7 @@ public class ArgumentMatcher {
                         str.append(errorString.apply(suppliedIndex));
                     }
                 }
-                throw RError.error(callingNode, RError.Message.UNUSED_ARGUMENTS, str);
+                throw callingNode.error(RError.Message.UNUSED_ARGUMENTS, str);
             }
             return new MatchPermutation(resultPermutation, ArgumentsSignature.get(resultSignature), null, null);
         }
@@ -661,7 +661,7 @@ public class ArgumentMatcher {
                             return MatchPermutation.UNMATCHED;
                         } else {
                             // Has already been matched: Error!
-                            throw RError.error(callingNode, RError.Message.FORMAL_MATCHED_MULTIPLE, formalName);
+                            throw callingNode.error(RError.Message.FORMAL_MATCHED_MULTIPLE, formalName);
                         }
                     }
                     return i;
@@ -692,11 +692,11 @@ public class ArgumentMatcher {
                 if (formalName.startsWith(suppliedName) && ((varArgIndex != ArgumentsSignature.NO_VARARG && i < varArgIndex) || varArgIndex == ArgumentsSignature.NO_VARARG)) {
                     // partial-match only if the formal argument is positioned before ...
                     if (found >= 0) {
-                        throw RError.error(callingNode, RError.Message.ARGUMENT_MATCHES_MULTIPLE, 1 + suppliedIndex);
+                        throw callingNode.error(RError.Message.ARGUMENT_MATCHES_MULTIPLE, 1 + suppliedIndex);
                     }
                     found = i;
                     if (resultPermutation[found] != MatchPermutation.UNMATCHED) {
-                        throw RError.error(callingNode, RError.Message.FORMAL_MATCHED_MULTIPLE, formalName);
+                        throw callingNode.error(RError.Message.FORMAL_MATCHED_MULTIPLE, formalName);
                     }
                 }
             }
@@ -704,6 +704,6 @@ public class ArgumentMatcher {
         if (found >= 0 || hasVarArgs) {
             return found;
         }
-        throw RError.error(callingNode, RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex));
+        throw callingNode.error(RError.Message.UNUSED_ARGUMENT, errorString.apply(suppliedIndex));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 9aaff96744..a3c624bcac 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -127,6 +127,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         return sourceSection;
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return this;
+    }
+
     public abstract RNode getFunction();
 
     private final RSyntaxNode[] arguments;
@@ -280,8 +285,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         Object dispatchObject = dispatchArgument.execute(frame);
         // Cannot dispatch on REmpty
         if (dispatchObject == REmpty.instance) {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.ARGUMENT_EMPTY, 1);
+            throw error(RError.Message.ARGUMENT_EMPTY, 1);
         }
         FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject);
         try {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
index 86b549616a..838dd57a2d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
@@ -43,6 +43,7 @@ import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
@@ -123,6 +124,11 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
         return sourceSection;
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return this;
+    }
+
     @Child private RNode functionNode;
     @Child private RNode special;
     @Child private SetVisibilityNode visibility;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
index 1ac6ee8922..8b67499f95 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
@@ -199,11 +199,11 @@ public final class MissingNode extends OperatorNode {
         if (level == null && readVarArgs == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             if (args.length != 1) {
-                throw RError.error(this, Message.ARGUMENTS_PASSED, args.length, "'missing'", 1);
+                throw error(Message.ARGUMENTS_PASSED, args.length, "'missing'", 1);
             }
             RSyntaxElement arg = args[0];
             if (!(arg instanceof RSyntaxLookup)) {
-                throw RError.error(this, Message.INVALID_USE, "missing");
+                throw error(Message.INVALID_USE, "missing");
             }
             String identifier = ((RSyntaxLookup) arg).getIdentifier();
             if (ArgumentsSignature.VARARG_NAME.equals(identifier)) {
@@ -219,7 +219,7 @@ public final class MissingNode extends OperatorNode {
             RArgsValuesAndNames varArgs = (RArgsValuesAndNames) readVarArgs.execute(frame);
             if (varArgs == null) {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, Message.MISSING_ARGUMENTS);
+                throw error(Message.MISSING_ARGUMENTS);
             }
             return createResult(frame, varArgs.getLength() == 0);
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
index 0290ce2ffd..009a714663 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.primitive;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -234,8 +233,7 @@ public final class BinaryMapNode extends RBaseNode {
     private Object applyVectorized(RAbstractVector left, RAbstractVector leftCast, int leftLength, RAbstractVector right, RAbstractVector rightCast, int rightLength) {
         if (mayContainMetadata && (dimensionsProfile.profile(hasLeftDimNode.execute(left) && hasRightDimNode.execute(right)))) {
             if (differentDimensions(left, right)) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.NON_CONFORMABLE_ARRAYS);
+                throw error(RError.Message.NON_CONFORMABLE_ARRAYS);
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
index 9a4fe5e046..42edcbb3ac 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
@@ -48,7 +48,6 @@ public abstract class ConvertBooleanNode extends RNode {
 
     private final NAProfile naProfile = NAProfile.create();
     private final BranchProfile invalidElementCountBranch = BranchProfile.create();
-    private final BranchProfile errorBranch = BranchProfile.create();
 
     @Override
     public final Object execute(VirtualFrame frame) {
@@ -64,13 +63,13 @@ public abstract class ConvertBooleanNode extends RNode {
 
     @Specialization
     protected byte doNull(@SuppressWarnings("unused") RNull value) {
-        throw RError.error(this, RError.Message.LENGTH_ZERO);
+        throw error(RError.Message.LENGTH_ZERO);
     }
 
     @Specialization
     protected byte doInt(int value) {
         if (naProfile.isNA(value)) {
-            throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+            throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
         }
         return RRuntime.int2logicalNoCheck(value);
     }
@@ -78,7 +77,7 @@ public abstract class ConvertBooleanNode extends RNode {
     @Specialization
     protected byte doDouble(double value) {
         if (naProfile.isNA(value)) {
-            throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+            throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
         }
         return RRuntime.double2logicalNoCheck(value);
     }
@@ -86,7 +85,7 @@ public abstract class ConvertBooleanNode extends RNode {
     @Specialization
     protected byte doLogical(byte value) {
         if (naProfile.isNA(value)) {
-            throw RError.error(this, RError.Message.NA_UNEXP);
+            throw error(RError.Message.NA_UNEXP);
         }
         return value;
     }
@@ -94,7 +93,7 @@ public abstract class ConvertBooleanNode extends RNode {
     @Specialization
     protected byte doComplex(RComplex value) {
         if (naProfile.isNA(value)) {
-            throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+            throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
         }
         return RRuntime.complex2logicalNoCheck(value);
     }
@@ -103,7 +102,7 @@ public abstract class ConvertBooleanNode extends RNode {
     protected byte doString(String value) {
         byte logicalValue = RRuntime.string2logicalNoCheck(value);
         if (naProfile.isNA(logicalValue)) {
-            throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+            throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
         }
         return logicalValue;
     }
@@ -117,10 +116,9 @@ public abstract class ConvertBooleanNode extends RNode {
         if (value.getLength() != 1) {
             invalidElementCountBranch.enter();
             if (value.getLength() == 0) {
-                errorBranch.enter();
-                throw RError.error(this, RError.Message.LENGTH_ZERO);
+                throw error(RError.Message.LENGTH_ZERO);
             } else {
-                RError.warning(this, RError.Message.LENGTH_GT_1);
+                warning(RError.Message.LENGTH_GT_1);
             }
         }
     }
@@ -164,7 +162,7 @@ public abstract class ConvertBooleanNode extends RNode {
     @Specialization
     protected byte doRawVector(RList value) {
         checkLength(value);
-        throw RError.error(this, RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+        throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
     }
 
     public static ConvertBooleanNode create(RSyntaxNode node) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java
index 4a0c825550..ef81593433 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstBooleanNode.java
@@ -58,7 +58,7 @@ public abstract class FirstBooleanNode extends CastNode {
     protected boolean firstScalar(byte argument) {
         if (RRuntime.isNA(argument)) {
             CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, invalidValueName == null ? Message.NA_UNEXP : Message.INVALID_VALUE, invalidValueName);
+            throw error(invalidValueName == null ? Message.NA_UNEXP : Message.INVALID_VALUE, invalidValueName);
         }
         return RRuntime.fromLogical(argument);
     }
@@ -67,7 +67,7 @@ public abstract class FirstBooleanNode extends CastNode {
         if (lengthNotOneProfile.profile(argument.getLength() != 1)) {
             if (argument.getLength() == 0) {
                 CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, invalidValueName == null ? Message.LENGTH_ZERO : Message.INVALID_VALUE, invalidValueName);
+                throw error(invalidValueName == null ? Message.LENGTH_ZERO : Message.INVALID_VALUE, invalidValueName);
             } else {
                 warningProfile.enter();
                 if (invalidValueName == null) {
@@ -104,6 +104,6 @@ public abstract class FirstBooleanNode extends CastNode {
     @Fallback
     protected boolean fallback(@SuppressWarnings("unused") Object argument) {
         CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, invalidValueName == null ? Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL : Message.INVALID_VALUE, invalidValueName);
+        throw error(invalidValueName == null ? Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL : Message.INVALID_VALUE, invalidValueName);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java
index 54d04e8c92..3df79d197d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstIntNode.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -46,7 +45,6 @@ public abstract class FirstIntNode extends CastNode {
     public abstract int executeInt(Object value);
 
     private final ConditionProfile lengthOneProfile = ConditionProfile.createBinaryProfile();
-    private final BranchProfile errorProfile = BranchProfile.create();
 
     @Specialization
     protected int firstScalar(int argument) {
@@ -62,8 +60,7 @@ public abstract class FirstIntNode extends CastNode {
                     return defaultValue;
                 }
             } else if (emptyError != null && argument.getLength() == 0) {
-                errorProfile.enter();
-                throw RError.error(this, emptyError, argumentName);
+                throw error(emptyError, argumentName);
             }
         }
         return argument.getDataAt(0);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
index bd584cf1bd..eb8d1d0725 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
@@ -22,14 +22,15 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.primitive.UnaryMapNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -43,7 +44,7 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
 
     protected final UnaryArithmeticFactory unary;
     private final Message error;
-    private final Object errorArgs;
+    private final Object[] errorArgs;
     protected final RType minPrecedence;
 
     public UnaryArithmeticNode(UnaryArithmeticFactory factory, RType minPrecedence, Message error, Object... errorArgs) {
@@ -105,10 +106,17 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
 
     @Fallback
     protected Object invalidArgType(@SuppressWarnings("unused") Object operand) {
-        if (errorArgs == null) {
-            throw RError.error(this, error);
+        CompilerDirectives.transferToInterpreter();
+        if (errorArgs == null || errorArgs.length == 0) {
+            throw error(error);
+        } else if (errorArgs.length == 1) {
+            throw error(error, errorArgs[0]);
+        } else if (errorArgs.length == 2) {
+            throw error(error, errorArgs[0], errorArgs[1]);
+        } else if (errorArgs.length == 3) {
+            throw error(error, errorArgs[0], errorArgs[1], errorArgs[2]);
         } else {
-            throw RError.error(this, error, (Object[]) errorArgs);
+            throw RInternalError.shouldNotReachHere("too many error arguments in UnaryArithmeticNode");
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
index 2d3092d235..6b79cd9599 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
@@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -61,17 +60,13 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
     public abstract Object executeReduce(Object value, boolean naRm, boolean finite);
 
     @Child private MultiElemStringHandlerNode stringHandler;
-
-    private final BinaryArithmeticFactory factory;
-
     @Child private BinaryArithmetic arithmetic;
 
+    private final BinaryArithmeticFactory factory;
     protected final ReduceSemantics semantics;
 
     private final NACheck na = NACheck.create();
-
     private final ConditionProfile naRmProfile = ConditionProfile.createBinaryProfile();
-    private final BranchProfile warningProfile = BranchProfile.create();
 
     protected UnaryArithmeticReduceNode(ReduceSemantics semantics, BinaryArithmeticFactory factory) {
         this.factory = factory;
@@ -89,15 +84,13 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
     private void emptyWarning() {
         if (semantics.getEmptyWarning() != null) {
-            warningProfile.enter();
-            RError.warning(this, semantics.emptyWarning);
+            warning(semantics.emptyWarning);
         }
     }
 
     private void naResultWarning() {
         if (semantics.getNAResultWarning() != null) {
-            warningProfile.enter();
-            RError.warning(this, semantics.getNAResultWarning());
+            warning(semantics.getNAResultWarning());
         }
     }
 
@@ -180,8 +173,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
                 return na.check(operand) ? RRuntime.createComplexNA() : operand;
             }
         } else {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
         }
     }
 
@@ -202,16 +194,14 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
                 return na.check(operand) ? RRuntime.STRING_NA : operand;
             }
         } else {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
     @SuppressWarnings("unused")
     @Specialization
     protected RRaw doString(RRaw operand, boolean naRm, boolean finite) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "raw");
+        throw error(RError.Message.INVALID_TYPE_ARGUMENT, "raw");
     }
 
     @Specialization
@@ -372,8 +362,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
             }
             return result;
         } else {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
 
         }
     }
@@ -390,8 +379,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
             }
             return semantics.getStringStart();
         } else {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(invokingNode, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw invokingNode.error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -413,8 +401,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
             }
             return result;
         } else {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -423,16 +410,14 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         if (semantics.supportString) {
             return handleString(operand, naRm, finite, 0);
         } else {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
     @SuppressWarnings("unused")
     @Specialization
     protected RRaw doString(RRawVector operand, boolean naRm, boolean finite) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "raw");
+        throw error(RError.Message.INVALID_TYPE_ARGUMENT, "raw");
     }
 
     public static final class ReduceSemantics {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 993c3565a1..e6148d53b9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -43,7 +43,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * might require more information to disambiguate. Rather than create a new class to carry that, we
  * would simply create an instance of a {@link RBaseNode} subclass with the additional state.
  * Currently,there are no such cases.
- *
  */
 @SuppressWarnings("serial")
 public final class RError extends RuntimeException {
@@ -190,12 +189,11 @@ public final class RError extends RuntimeException {
      * Handles an R error with the most general argument signature. All other facade variants
      * delegate to this method.
      *
-     * Note that the method never actually returns a result, but the throws the error directly.
+     * Note that the method never actually returns a result, instead it throws the error directly.
      * However, the signature has a return type of {@link RError} to allow callers to use the idiom
      * {@code throw error(...)} to indicate the control transfer. It is entirely possible that, due
      * to condition handlers, the error will not actually be thrown.
      *
-     *
      * @param node {@code RNode} of the code throwing the error, or {@link #SHOW_CALLER2} if not
      *            available. If {@code NO_NODE} an attempt will be made to identify the call context
      *            from the currently active frame.
@@ -238,6 +236,12 @@ public final class RError extends RuntimeException {
         throw error(node, RError.Message.NYI, msg);
     }
 
+    @TruffleBoundary
+    public static void warning(ErrorContext node, Message msg, Object... args) {
+        assert node != null;
+        RErrorHandling.warningcall(true, node, msg, args);
+    }
+
     @TruffleBoundary
     public static void warning(RBaseNode node, Message msg, Object... args) {
         assert node != null;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index fb962d5327..422a861da9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -672,26 +672,18 @@ public class RErrorHandling {
                 if (warning.call == RNull.instance) {
                     Utils.writeStderr(warning.message, true);
                 } else {
-                    String callSource = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) warning.call);
-                    Utils.writeStderr(String.format("In %s : %s", callSource, warning.message), true);
+                    printWarningMessage("In ", warning, 69);
                 }
             } else if (nWarnings <= 10) {
                 Utils.writeStderr("Warning messages:", true);
                 for (int i = 0; i < nWarnings; i++) {
-                    Object call = warnings.get(i).call;
-                    String message = warnings.get(i).message;
-                    if (call == RNull.instance || ((RLanguage) call).getRep().getSourceSection() == null) {
+                    Warning warning = warnings.get(i);
+                    if (warning.call == RNull.instance) {
                         Utils.writeStderr((i + 1) + ":", true);
-                        Utils.writeStderr("  " + warnings.get(i).message, true);
+                        Utils.writeStderr("  " + warning.message, true);
                     } else {
-                        String callString = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) call);
-                        // this can be enabled when deparsing is completely stable:
-                        // callString = RDeparse.deparse1Line(call, false);
-                        Utils.writeStderr((i + 1) + ": In ", false);
-                        int firstLineLength = message.contains("\n") ? message.indexOf('\n') : message.length();
-                        boolean nl = callString.length() + firstLineLength > 65;
-                        Utils.writeStderr(callString + " :", nl);
-                        Utils.writeStderr((nl ? "  " : " ") + message, true);
+                        Utils.writeStderr(Integer.toString(i + 1), false);
+                        printWarningMessage(": In ", warning, 65);
                     }
                 }
             } else {
@@ -716,6 +708,20 @@ public class RErrorHandling {
         }
     }
 
+    private static void printWarningMessage(String prefix, Warning warning, int maxLen) {
+        String callString = RContext.getRRuntimeASTAccess().getCallerSource((RLanguage) warning.call);
+
+        String message = warning.message;
+        int firstLineLength = message.contains("\n") ? message.indexOf('\n') : message.length();
+        if (callString.length() + firstLineLength > maxLen) {
+            // split long lines
+            Utils.writeStderr(prefix + callString + " :", true);
+            Utils.writeStderr("  " + message, true);
+        } else {
+            Utils.writeStderr(prefix + callString + " : " + message, true);
+        }
+    }
+
     public static void printDeferredWarnings() {
         if (getRErrorHandlingState().warnings.size() > 0) {
             Utils.writeStderr("In addition: ", false);
@@ -735,7 +741,7 @@ public class RErrorHandling {
         // (is 74 a given percentage of console width?)
         if (preamble.length() + 1 + message.length() >= 74) {
             // +1 is for the extra space following the colon
-            return preamble + "\n  " + message;
+            return preamble + " \n  " + message;
         } else {
             return preamble + " " + message;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 4a95c318bd..e0d3de6980 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -367,25 +367,27 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         } else if (newDimNames != null) {
             int[] dimensions = getDimensionsFromAttrs();
             if (dimensions == null) {
-                throw RError.error(invokingNode, RError.Message.DIMNAMES_NONARRAY);
+                throw invokingNode.error(RError.Message.DIMNAMES_NONARRAY);
             }
             int newDimNamesLength = newDimNames.getLength();
             if (newDimNamesLength > dimensions.length) {
-                throw RError.error(invokingNode, RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, dimensions.length);
+                throw invokingNode.error(RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength, dimensions.length);
             }
             for (int i = 0; i < newDimNamesLength; i++) {
                 Object dimObject = newDimNames.getDataAt(i);
                 if (dimObject != RNull.instance) {
                     if (dimObject instanceof String) {
                         if (dimensions[i] != 1) {
-                            throw RError.error(invokingNode, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
+                            CompilerDirectives.transferToInterpreter();
+                            throw invokingNode.error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
                         }
                     } else {
                         RStringVector dimVector = (RStringVector) dimObject;
                         if (dimVector == null) {
                             newDimNames.updateDataAt(i, RNull.instance, null);
                         } else if (dimVector.getLength() != dimensions[i]) {
-                            throw RError.error(invokingNode, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
+                            CompilerDirectives.transferToInterpreter();
+                            throw invokingNode.error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
                         }
                     }
                 }
@@ -783,17 +785,14 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         int length = 1;
         for (int i = 0; i < newDimensions.length; i++) {
             if (RRuntime.isNA(newDimensions[i])) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(invokingNode, RError.Message.DIMS_CONTAIN_NA);
+                throw invokingNode.error(RError.Message.DIMS_CONTAIN_NA);
             } else if (newDimensions[i] < 0) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(invokingNode, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
+                throw invokingNode.error(RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
             }
             length *= newDimensions[i];
         }
         if (length != vectorLength && vectorLength > 0) {
-            CompilerDirectives.transferToInterpreter();
-            throw RError.error(invokingNode, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
+            throw invokingNode.error(RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index d19ba63e09..b369e512dc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -28,10 +28,13 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.LoopNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeVisitor;
+import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RError.RErrorException;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -305,4 +308,143 @@ public abstract class RBaseNode extends Node {
     protected static boolean isRAttributable(Object value) {
         return value instanceof RAttributable;
     }
+
+    /*
+     * Error handling-related functionality.
+     */
+
+    /**
+     * Find the proper context for errors or warnings produced by this node. The default behavior is
+     * to call getErrorContext() of the parent RBaseNode recursively.
+     *
+     * Certain types of nodes, e.g., builtins, will supply the correct context for themselves.
+     */
+    protected RBaseNode getErrorContext() {
+        Node node = getParent();
+        while (node != null) {
+            if (node instanceof RBaseNode) {
+                return ((RBaseNode) node).getErrorContext();
+            }
+            if (node instanceof RootNode) {
+                return RError.NO_CALLER;
+            }
+            node = node.getParent();
+        }
+        throw RInternalError.shouldNotReachHere("trying to get error context of node without parent");
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RErrorException exception) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), exception);
+    }
+
+    /**
+     * Raises the given error with the error context determined by {@link #getErrorContext()}. This
+     * function is always considered to be a slow-path operation and will transferToInterpreter.
+     *
+     * @return an RError so that this function can be called as {@code throw error(...);}.
+     */
+    public final RError error(RError.Message message) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message);
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RError.Message message, Object arg) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg);
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RError.Message message, Object arg1, Object arg2) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2);
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3);
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4);
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5);
+    }
+
+    /**
+     * @see #error(Message)
+     */
+    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
+        CompilerDirectives.transferToInterpreter();
+        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5, arg6);
+    }
+
+    @CompilationFinal boolean hasSeenWarning;
+
+    /**
+     * Raises the given warning with the error context determined by {@link #getErrorContext()}.
+     * This function is profiled so that it will only use a real call if a warning was issued from
+     * this node before.
+     */
+    public final void warning(Message msg) {
+        if (!hasSeenWarning) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            hasSeenWarning = true;
+        }
+        RError.warning(getErrorContext(), msg);
+    }
+
+    /**
+     * @see #warning(Message)
+     */
+    public final void warning(Message msg, Object arg1) {
+        if (!hasSeenWarning) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            hasSeenWarning = true;
+        }
+        RError.warning(getErrorContext(), msg, arg1);
+    }
+
+    /**
+     * @see #warning(Message)
+     */
+    public final void warning(Message msg, Object arg1, Object arg2) {
+        if (!hasSeenWarning) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            hasSeenWarning = true;
+        }
+        RError.warning(getErrorContext(), msg, arg1, arg2);
+    }
+
+    /**
+     * @see #warning(Message)
+     */
+    public final void warning(Message msg, Object arg1, Object arg2, Object arg3) {
+        if (!hasSeenWarning) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            hasSeenWarning = true;
+        }
+        RError.warning(getErrorContext(), msg, arg1, arg2, arg3);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java
index 72082019ba..7317a9e869 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/builtin/RBuiltinBaseNode.java
@@ -22,52 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.nodes.builtin;
 
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.RErrorException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class RBuiltinBaseNode extends RBaseNode {
 
-    protected abstract RBaseNode getErrorContext();
-
-    public final RError error(RErrorException exception) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), exception);
-    }
-
-    public final RError error(RError.Message message) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message);
-    }
-
-    public final RError error(RError.Message message, Object arg) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message, arg);
-    }
-
-    public final RError error(RError.Message message, Object arg1, Object arg2) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message, arg1, arg2);
-    }
-
-    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message, arg1, arg2, arg3);
-    }
-
-    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4);
-    }
-
-    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5);
-    }
-
-    public final RError error(RError.Message message, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) {
-        CompilerDirectives.transferToInterpreter();
-        throw RError.error(getErrorContext(), message, arg1, arg2, arg3, arg4, arg5, arg6);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
index 5f020f50ee..b7b07fc864 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
@@ -156,9 +156,8 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public String op(String left, String right) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -214,9 +213,8 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public String op(String left, String right) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -291,9 +289,8 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public String op(String left, String right) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -386,9 +383,8 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public String op(String left, String right) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -430,15 +426,13 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) {
-            throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX);
+            throw error(RError.Message.UNIMPLEMENTED_COMPLEX);
         }
 
         @Override
-        @TruffleBoundary
         public String op(String left, String right) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -506,15 +500,13 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) {
-            throw RError.error(this, RError.Message.UNIMPLEMENTED_COMPLEX);
+            throw error(RError.Message.UNIMPLEMENTED_COMPLEX);
         }
 
         @Override
-        @TruffleBoundary
         public String op(String left, String right) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
     }
 
@@ -992,9 +984,8 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
         }
 
         @Override
@@ -1039,9 +1030,8 @@ public abstract class BinaryArithmetic extends Operation {
         }
 
         @Override
-        @TruffleBoundary
         public RComplex op(double leftReal, double leftImag, double rightReal, double rightImag) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, "complex");
+            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
index 19a58782aa..a3d342a25f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
@@ -165,7 +165,7 @@ public abstract class BinaryCompare extends BooleanOperation {
 
         @Override
         public boolean op(RComplex left, RComplex right) {
-            throw RError.error(this, RError.Message.COMPARISON_COMPLEX);
+            throw error(RError.Message.COMPARISON_COMPLEX);
         }
     }
 
@@ -197,7 +197,7 @@ public abstract class BinaryCompare extends BooleanOperation {
 
         @Override
         public boolean op(RComplex left, RComplex right) {
-            throw RError.error(this, RError.Message.COMPARISON_COMPLEX);
+            throw error(RError.Message.COMPARISON_COMPLEX);
         }
     }
 
@@ -229,7 +229,7 @@ public abstract class BinaryCompare extends BooleanOperation {
 
         @Override
         public boolean op(RComplex left, RComplex right) {
-            throw RError.error(this, RError.Message.COMPARISON_COMPLEX);
+            throw error(RError.Message.COMPARISON_COMPLEX);
         }
     }
 
@@ -266,7 +266,7 @@ public abstract class BinaryCompare extends BooleanOperation {
 
         @Override
         public boolean op(RComplex left, RComplex right) {
-            throw RError.error(this, RError.Message.COMPARISON_COMPLEX);
+            throw error(RError.Message.COMPARISON_COMPLEX);
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
index 50a2921152..068243c102 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
@@ -129,7 +129,7 @@ public abstract class BinaryLogic extends BooleanOperation {
 
         @Override
         public boolean op(String left, String right) {
-            throw RError.error(this, RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
+            throw error(RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
         }
 
         @Override
@@ -184,7 +184,7 @@ public abstract class BinaryLogic extends BooleanOperation {
 
         @Override
         public boolean op(String left, String right) {
-            throw RError.error(this, RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
+            throw error(RError.Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java
index b656b2072f..805844fbc3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java
@@ -29,7 +29,7 @@ public class TestBuiltin_all extends TestBase {
 
     @Test
     public void testall3() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);");
+        assertEval("argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);");
     }
 
     @Test
@@ -117,10 +117,9 @@ public class TestBuiltin_all extends TestBase {
         assertEval("{ all(TRUE, TRUE, NA,  na.rm=FALSE) }");
 
         assertEval("{ all(TRUE, TRUE, NA,  na.rm=TRUE) }");
-        // FIXME coercion warning missing
         assertEval("{ all(1) }");
         assertEval("{ all(0) }");
-        assertEval(Output.IgnoreWarningContext, "{ all(TRUE,c(TRUE,TRUE),1) }");
+        assertEval("{ all(TRUE,c(TRUE,TRUE),1) }");
         assertEval("{ all(TRUE,c(TRUE,TRUE),1,0) }");
 
         assertEval("{ all(NULL) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
index a0c32a8668..fa9e4a7732 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
@@ -193,7 +193,7 @@ public class TestBuiltin_aperm extends TestBase {
         assertEval("{ aperm(array(c('FASTR', 'IS', 'SO', 'FAST'), c(3,1,2))) }");
 
         // perm specified in complex numbers produces warning
-        assertEval(Output.IgnoreWarningContext, "{ aperm(array(1:27,c(3,3,3)), c(1+1i,3+3i,2+2i))[1,2,3] == array(1:27,c(3,3,3))[1,3,2]; }");
+        assertEval("{ aperm(array(1:27,c(3,3,3)), c(1+1i,3+3i,2+2i))[1,2,3] == array(1:27,c(3,3,3))[1,3,2]; }");
 
         // perm is not a permutation vector
         assertEval("{ aperm(array(1,c( 3,3,3)), c(1,2,1)); }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
index 4d67fec7e1..4a2724063a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
@@ -156,7 +156,7 @@ public class TestBuiltin_array extends TestBase {
     @Test
     public void testArray() {
         assertEval("{ array(1:4, 1:2, 4) }");
-        assertEval(Output.IgnoreWarningContext, "{ array(1:4, c(1+2i, 2+2i)) }");
+        assertEval("{ array(1:4, c(1+2i, 2+2i)) }");
         assertEval("{ array(as.raw(1:4)) }");
         assertEval("{ array(1:4, integer()) }");
         assertEval("{ array(NULL) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
index 480abb2984..b122941859 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
@@ -32,9 +32,7 @@ public class TestBuiltin_bitwiseShiftL extends TestBase {
         assertEval("{ bitwShiftL(TRUE, c(TRUE, FALSE)) }");
 
         assertEval("{ bitwShiftL(c(3+3i), c(3,2,4)) }");
-        // Warning message mismatch
-        assertEval(Output.IgnoreWarningContext, "{ bitwShiftL(c(3,2,4), c(3+3i)) }");
-        // No warning message printed for NAs produced by coercion
+        assertEval("{ bitwShiftL(c(3,2,4), c(3+3i)) }");
         assertEval("{ bitwShiftL(c(1,2,3,4), c(\"a\")) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
index 459a1421dd..1fab7d1275 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
@@ -28,7 +28,7 @@ public class TestBuiltin_bitwiseShiftR extends TestBase {
         assertEval("{ bitwShiftR(c(100,200,300), 1) }");
         assertEval("{ bitwShiftR(c(25,57,66), c(10,20,30,40,50,60)) }");
 
-        assertEval(Output.IgnoreWarningContext, "{ bitwShiftR(c(3,2,4), c(3+3i)) }");
+        assertEval("{ bitwShiftR(c(3,2,4), c(3+3i)) }");
 
         // No warning message printed for NAs produced by coercion
         assertEval(Ignored.Unknown, "{ bitwShiftR(c(1,2,3,4), c(\"Hello\")) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java
index f167e67786..fa5d0bd6d6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_copyDFattr.java
@@ -24,14 +24,12 @@ public class TestBuiltin_copyDFattr extends TestBase {
 
     @Test
     public void testcopyDFattr2() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3)), structure(list(y = NULL, x1 = NULL, x2 = NULL, x3 = NULL), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3)), structure(list(y = NULL, x1 = NULL, x2 = NULL, x3 = NULL), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr3() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(y = c(-0.0561287395290008, -0.155795506705329, -1.47075238389927, -0.47815005510862, 0.417941560199702, 1.35867955152904, -0.102787727342996, 0.387671611559369, -0.0538050405829051, -1.37705955682861), x = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), z = 1:10), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z)), structure(list(y = NULL, x = NULL, z = NULL), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(y = c(-0.0561287395290008, -0.155795506705329, -1.47075238389927, -0.47815005510862, 0.417941560199702, 1.35867955152904, -0.102787727342996, 0.387671611559369, -0.0538050405829051, -1.37705955682861), x = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), z = 1:10), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z)), structure(list(y = NULL, x = NULL, z = NULL), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -41,14 +39,12 @@ public class TestBuiltin_copyDFattr extends TestBase {
 
     @Test
     public void testcopyDFattr5() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(A = 0:10, B = 10:20, `NA` = 20:30), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame'), structure(list(A = NULL, B = NULL, `NA` = NULL), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(A = 0:10, B = 10:20, `NA` = 20:30), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame'), structure(list(A = NULL, B = NULL, `NA` = NULL), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr6() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = structure(c(760, 2160, 5441, 277, 1815, 2587, 547, 1125, 2010, 2422, 6155, 1767, 61, 60, 7807, 7732, 6126, 7921, 3590, 5231, 5384, 5934, 6415, 6789, 6778, 3561, 4505, 3987, 4726, 5550, 5216, 5757, 2345, 6931, 6760, 5796, 4810, 5143, 3091, 3316, 700, 1706, 5088, 944, 2466, 1706, 7364, 1857, 9510, 9603, 31, 7479, 2006, 2588, 2983, 8761, 3932, 4201, 5293, 273, 2223, 4249, 5308, 8327, 499, 5789, 7417, 3242, 3275, 10359, 10852, 362, 9993, 1795, 3562, 4139, 4840, 4959, 547, 4119, 8308, 1674, 2953, 3776, 1369, 7911, 7519, 9318, 4370, 7301, 1642, 4169, 7417, 6117, 4536, 7235, 6723, 7397, 7428, 2084, 4066, 1673, 2860, 0, 3773, 4810, 4206, 2314, 4065, 8961, 6143, 517, 3837, 7498, 2815, 8806, 7668, 12457, 8600, 7003, 2435, 1826, 2403, 3805, 4901, 365, 6642, 3318, 3012, 1431, 2223, 4962, 5982, 638, 3346, 4996, 6800, 7454, 8887, 5024, 2833, 4232, 5238, 3186, 3380, 3382, 8100, 1766, 7184, 8059, 6008, 5047, 2236, 8165, 4224, 2844, 6256, 7370, 3560, 4939, 4941, 2230, 3068, 152, 10122, 3226, 3943, 518, 8569, 845, 2099, 8006, 8052, 9560, 0, 7965, 7470, 8133, 809, 153, 1851, 3010, 2121, 7085, 5068, 7093, 5930, 6878, 8080, 791, 6626, 3962, 1116, 1249, 9257, 1077, 566, 174, 4627, 5022, 2070, 3012, 1625, 6607, 8381, 8389, 1005, 3895, 4236, 6970, 8497, 2861, 8487, 3227, 8030, 8023, 31, 2435, 518, 4758, 7958, 7884, 4453, 6349, 7862, 1392, 3167, 6025, 4656, 1767, 7736, 2678, 2191, 3658, 7758, 8009, 2556, 3511, 7954, 822, 4321, 5151, 7545, 7576, 32, 7875, 5236, 7106, 2802, 7898, 3014, 7867, 5354, 2989, 7555, 6089, 8697, 6479, 1826, 5917, 792, 1431, 1434, 4763, 2910, 6209, 5824, 2400, 1400, 3027, 7198, 7247, 2557, 3855, 61, 7410, 1492, 7160, 7899, 5181, 7280, 3448, 7381, 2434, 6763, 7065, 1218, 1554, 7533, 7288, 2922, 5988, 2495, 5234, 9598, 2953, 2961, 4539, 3775, 6524, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 0, 2, 2, 1, 0, 2, 2, 0, 0, 2, 0, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 0, 2, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 1, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 0, 2, 1, 2, 1, 0, 1, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 1, 2, 0, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 1, 2, 2, 0, 2, 0, 2, 2, 0, 2, 0, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 2, 0, 1, 2, 2, 1, 2), .Dim = c(300L, 2L), .Dimnames = list(NULL, c('time', 'status')), type = 'mright', states = c('1', '2'), class = 'Surv')), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L)), structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = NULL), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = structure(c(760, 2160, 5441, 277, 1815, 2587, 547, 1125, 2010, 2422, 6155, 1767, 61, 60, 7807, 7732, 6126, 7921, 3590, 5231, 5384, 5934, 6415, 6789, 6778, 3561, 4505, 3987, 4726, 5550, 5216, 5757, 2345, 6931, 6760, 5796, 4810, 5143, 3091, 3316, 700, 1706, 5088, 944, 2466, 1706, 7364, 1857, 9510, 9603, 31, 7479, 2006, 2588, 2983, 8761, 3932, 4201, 5293, 273, 2223, 4249, 5308, 8327, 499, 5789, 7417, 3242, 3275, 10359, 10852, 362, 9993, 1795, 3562, 4139, 4840, 4959, 547, 4119, 8308, 1674, 2953, 3776, 1369, 7911, 7519, 9318, 4370, 7301, 1642, 4169, 7417, 6117, 4536, 7235, 6723, 7397, 7428, 2084, 4066, 1673, 2860, 0, 3773, 4810, 4206, 2314, 4065, 8961, 6143, 517, 3837, 7498, 2815, 8806, 7668, 12457, 8600, 7003, 2435, 1826, 2403, 3805, 4901, 365, 6642, 3318, 3012, 1431, 2223, 4962, 5982, 638, 3346, 4996, 6800, 7454, 8887, 5024, 2833, 4232, 5238, 3186, 3380, 3382, 8100, 1766, 7184, 8059, 6008, 5047, 2236, 8165, 4224, 2844, 6256, 7370, 3560, 4939, 4941, 2230, 3068, 152, 10122, 3226, 3943, 518, 8569, 845, 2099, 8006, 8052, 9560, 0, 7965, 7470, 8133, 809, 153, 1851, 3010, 2121, 7085, 5068, 7093, 5930, 6878, 8080, 791, 6626, 3962, 1116, 1249, 9257, 1077, 566, 174, 4627, 5022, 2070, 3012, 1625, 6607, 8381, 8389, 1005, 3895, 4236, 6970, 8497, 2861, 8487, 3227, 8030, 8023, 31, 2435, 518, 4758, 7958, 7884, 4453, 6349, 7862, 1392, 3167, 6025, 4656, 1767, 7736, 2678, 2191, 3658, 7758, 8009, 2556, 3511, 7954, 822, 4321, 5151, 7545, 7576, 32, 7875, 5236, 7106, 2802, 7898, 3014, 7867, 5354, 2989, 7555, 6089, 8697, 6479, 1826, 5917, 792, 1431, 1434, 4763, 2910, 6209, 5824, 2400, 1400, 3027, 7198, 7247, 2557, 3855, 61, 7410, 1492, 7160, 7899, 5181, 7280, 3448, 7381, 2434, 6763, 7065, 1218, 1554, 7533, 7288, 2922, 5988, 2495, 5234, 9598, 2953, 2961, 4539, 3775, 6524, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 0, 2, 2, 1, 0, 2, 2, 0, 0, 2, 0, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 0, 2, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 1, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 0, 2, 1, 2, 1, 0, 1, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 1, 2, 0, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 1, 2, 2, 0, 2, 0, 2, 2, 0, 2, 0, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 2, 0, 1, 2, 2, 1, 2), .Dim = c(300L, 2L), .Dimnames = list(NULL, c('time', 'status')), type = 'mright', states = c('1', '2'), class = 'Surv')), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L)), structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = NULL), .Names = 'Surv(stop, status * as.numeric(event), type = \\\'mstate\\\')', class = 'data.frame', row.names = c(NA, 300L))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -75,14 +71,12 @@ public class TestBuiltin_copyDFattr extends TestBase {
 
     @Test
     public void testcopyDFattr11() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(srcfile = c(NA, '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats'), frow = c(NA, 2228L, 2369L, 2379L), lrow = c(NA, 2228L, 2369L, 2380L)), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame'), structure(list(srcfile = NULL, frow = NULL, lrow = NULL), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(srcfile = c(NA, '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats'), frow = c(NA, 2228L, 2369L, 2379L), lrow = c(NA, 2228L, 2369L, 2380L)), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame'), structure(list(srcfile = NULL, frow = NULL, lrow = NULL), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr12() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(y = c(73, 73, 70, 74, 75, 115, 105, 107, 124, 107, 116, 125, 102, 144, 178, 149, 177, 124, 157, 128, 169, 165, 186, 152, 181, 139, 173, 151, 138, 181, 152, 188, 173, 196, 180, 171, 188, 174, 198, 172, 176, 162, 188, 182, 182, 141, 191, 190, 159, 170, 163, 197), x = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 11, 12)), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x)), structure(list(y = NULL, x = NULL), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(y = c(73, 73, 70, 74, 75, 115, 105, 107, 124, 107, 116, 125, 102, 144, 178, 149, 177, 124, 157, 128, 169, 165, 186, 152, 181, 139, 173, 151, 138, 181, 152, 188, 173, 196, 180, 171, 188, 174, 198, 172, 176, 162, 188, 182, 182, 141, 191, 190, 159, 170, 163, 197), x = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 11, 12)), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x)), structure(list(y = NULL, x = NULL), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -93,32 +87,27 @@ public class TestBuiltin_copyDFattr extends TestBase {
 
     @Test
     public void testcopyDFattr14() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(y = c(-0.667819876370237, 0.170711734013213, 0.552921941721332, -0.253162069270378, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, -1.36919169254062, 0.0881443844426084, -0.0834190388782434)), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0)), structure(list(y = NULL), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(y = c(-0.667819876370237, 0.170711734013213, 0.552921941721332, -0.253162069270378, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, -1.36919169254062, 0.0881443844426084, -0.0834190388782434)), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0)), structure(list(y = NULL), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr15() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(`cbind(w = weight, w2 = weight^2)` = structure(c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14, 4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69, 17.3889, 31.1364, 26.8324, 37.3321, 20.25, 21.2521, 26.7289, 20.5209, 28.4089, 26.4196, 23.1361, 17.3889, 19.4481, 12.8881, 34.4569, 14.6689, 36.3609, 23.9121, 18.6624, 21.9961), .Dim = c(20L, 2L), .Dimnames = list(NULL, c('w', 'w2'))), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Ctl', 'Trt'), class = 'factor')), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group)), structure(list(`cbind(w = weight, w2 = weight^2)` = NULL, group = NULL), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(`cbind(w = weight, w2 = weight^2)` = structure(c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14, 4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69, 17.3889, 31.1364, 26.8324, 37.3321, 20.25, 21.2521, 26.7289, 20.5209, 28.4089, 26.4196, 23.1361, 17.3889, 19.4481, 12.8881, 34.4569, 14.6689, 36.3609, 23.9121, 18.6624, 21.9961), .Dim = c(20L, 2L), .Dimnames = list(NULL, c('w', 'w2'))), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Ctl', 'Trt'), class = 'factor')), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group)), structure(list(`cbind(w = weight, w2 = weight^2)` = NULL, group = NULL), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr16() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(Y = c(130L, 157L, 174L, 117L, 114L, 161L, 141L, 105L, 140L, 118L, 156L, 61L, 91L, 97L, 100L, 70L, 108L, 126L, 149L, 96L, 124L, 121L, 144L, 68L, 64L, 112L, 86L, 60L, 102L, 89L, 96L, 89L, 129L, 132L, 124L, 74L, 89L, 81L, 122L, 64L, 103L, 132L, 133L, 70L, 89L, 104L, 117L, 62L, 90L, 100L, 116L, 80L, 82L, 94L, 126L, 63L, 70L, 109L, 99L, 53L, 74L, 118L, 113L, 89L, 82L, 86L, 104L, 97L, 99L, 119L, 121L), B = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c('I', 'II', 'III', 'IV', 'V', 'VI'), class = 'factor'), V = structure(c(3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c('Golden.rain', 'Marvellous', 'Victory'), class = 'factor'), N = structure(c(2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt'), class = 'factor')), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame'), structure(list(Y = NULL, B = NULL, V = NULL, N = NULL), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(Y = c(130L, 157L, 174L, 117L, 114L, 161L, 141L, 105L, 140L, 118L, 156L, 61L, 91L, 97L, 100L, 70L, 108L, 126L, 149L, 96L, 124L, 121L, 144L, 68L, 64L, 112L, 86L, 60L, 102L, 89L, 96L, 89L, 129L, 132L, 124L, 74L, 89L, 81L, 122L, 64L, 103L, 132L, 133L, 70L, 89L, 104L, 117L, 62L, 90L, 100L, 116L, 80L, 82L, 94L, 126L, 63L, 70L, 109L, 99L, 53L, 74L, 118L, 113L, 89L, 82L, 86L, 104L, 97L, 99L, 119L, 121L), B = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c('I', 'II', 'III', 'IV', 'V', 'VI'), class = 'factor'), V = structure(c(3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c('Golden.rain', 'Marvellous', 'Victory'), class = 'factor'), N = structure(c(2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt'), class = 'factor')), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame'), structure(list(Y = NULL, B = NULL, V = NULL, N = NULL), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr17() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2)), structure(list(Fr = NULL, Hair = NULL, Eye = NULL, Sex = NULL), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2)), structure(list(Fr = NULL, Hair = NULL, Eye = NULL, Sex = NULL), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcopyDFattr18() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(Employed = c(60.323, 61.122, 60.171, 61.187, 63.221, 63.639, 64.989, 63.761, 66.019, 67.857, 68.169, 66.513, 68.655, 69.564, 69.331, 70.551), GNP.deflator = c(83, 88.5, 88.2, 89.5, 96.2, 98.1, 99, 100, 101.2, 104.6, 108.4, 110.8, 112.6, 114.2, 115.7, 116.9), GNP = c(234.289, 259.426, 258.054, 284.599, 328.975, 346.999, 365.385, 363.112, 397.469, 419.18, 442.769, 444.546, 482.704, 502.601, 518.173, 554.894), Unemployed = c(235.6, 232.5, 368.2, 335.1, 209.9, 193.2, 187, 357.8, 290.4, 282.2, 293.6, 468.1, 381.3, 393.1, 480.6, 400.7), Armed.Forces = c(159, 145.6, 161.6, 165, 309.9, 359.4, 354.7, 335, 304.8, 285.7, 279.8, 263.7, 255.2, 251.4, 257.2, 282.7), Population = c(107.608, 108.632, 109.773, 110.929, 112.075, 113.27, 115.094, 116.219, 117.388, 118.734, 120.445, 121.95, 123.366, 125.368, 127.852, 130.081), Year = 1947:1962), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~     GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year)), structure(list(Employed = NULL, GNP.deflator = NULL, GNP = NULL, Unemployed = NULL, Armed.Forces = NULL, Population = NULL, Year = NULL), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(Employed = c(60.323, 61.122, 60.171, 61.187, 63.221, 63.639, 64.989, 63.761, 66.019, 67.857, 68.169, 66.513, 68.655, 69.564, 69.331, 70.551), GNP.deflator = c(83, 88.5, 88.2, 89.5, 96.2, 98.1, 99, 100, 101.2, 104.6, 108.4, 110.8, 112.6, 114.2, 115.7, 116.9), GNP = c(234.289, 259.426, 258.054, 284.599, 328.975, 346.999, 365.385, 363.112, 397.469, 419.18, 442.769, 444.546, 482.704, 502.601, 518.173, 554.894), Unemployed = c(235.6, 232.5, 368.2, 335.1, 209.9, 193.2, 187, 357.8, 290.4, 282.2, 293.6, 468.1, 381.3, 393.1, 480.6, 400.7), Armed.Forces = c(159, 145.6, 161.6, 165, 309.9, 359.4, 354.7, 335, 304.8, 285.7, 279.8, 263.7, 255.2, 251.4, 257.2, 282.7), Population = c(107.608, 108.632, 109.773, 110.929, 112.075, 113.27, 115.094, 116.219, 117.388, 118.734, 120.445, 121.95, 123.366, 125.368, 127.852, 130.081), Year = 1947:1962), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~     GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year)), structure(list(Employed = NULL, GNP.deflator = NULL, GNP = NULL, Unemployed = NULL, Armed.Forces = NULL, Population = NULL, Year = NULL), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -129,8 +118,7 @@ public class TestBuiltin_copyDFattr extends TestBase {
 
     @Test
     public void testcopyDFattr20() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(structure(list(`cbind(X, M)` = structure(c(68, 42, 37, 24, 66, 33, 47, 23, 63, 29, 57, 19, 42, 30, 52, 43, 50, 23, 55, 47, 53, 27, 49, 29), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('X', 'M'))), M.user = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c('N', 'Y'), class = 'factor'), Temp = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c('High', 'Low'), class = 'factor'), Soft = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c('Hard', 'Medium', 'Soft'), class = 'factor')), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft)), structure(list(`cbind(X, M)` = NULL, M.user = NULL, Temp = NULL, Soft = NULL), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X,     M) ~ M.user + Temp + Soft))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(list(`cbind(X, M)` = structure(c(68, 42, 37, 24, 66, 33, 47, 23, 63, 29, 57, 19, 42, 30, 52, 43, 50, 23, 55, 47, 53, 27, 49, 29), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('X', 'M'))), M.user = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c('N', 'Y'), class = 'factor'), Temp = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c('High', 'Low'), class = 'factor'), Soft = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c('Hard', 'Medium', 'Soft'), class = 'factor')), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft)), structure(list(`cbind(X, M)` = NULL, M.user = NULL, Temp = NULL, Soft = NULL), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X,     M) ~ M.user + Temp + Soft))); .Internal(copyDFattr(argv[[1]], argv[[2]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
index 5c62b28cce..da7f2560bc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
@@ -225,7 +225,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse40() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        assertEval("argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java
index 1b21fd0bc0..5741c165e1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java
@@ -24,8 +24,7 @@ public class TestBuiltin_dfltWarn extends TestBase {
 
     @Test
     public void testdfltWarn2() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list('bessel_y(2,nu=288.12): precision lost in result', quote(besselY(2, nu = nu <- seq(3, 300, len = 51)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list('bessel_y(2,nu=288.12): precision lost in result', quote(besselY(2, nu = nu <- seq(3, 300, len = 51)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -35,8 +34,7 @@ public class TestBuiltin_dfltWarn extends TestBase {
 
     @Test
     public void testdfltWarn4() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list('header and col.names are of different lengths', quote(read.table('foo3', header = TRUE, col.names = letters[1:4]))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list('header and col.names are of different lengths', quote(read.table('foo3', header = TRUE, col.names = letters[1:4]))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -51,7 +49,7 @@ public class TestBuiltin_dfltWarn extends TestBase {
 
     @Test
     public void testdfltWarn7() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list(\'drop argument will be ignored', quote(`[.data.frame`(women, 'height', drop = FALSE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(\'drop argument will be ignored', quote(`[.data.frame`(women, 'height', drop = FALSE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -62,13 +60,12 @@ public class TestBuiltin_dfltWarn extends TestBase {
 
     @Test
     public void testdfltWarn9() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list('1 y value <= 0 omitted from logarithmic plot', quote(xy.coords(x, NULL, log = log))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list('1 y value <= 0 omitted from logarithmic plot', quote(xy.coords(x, NULL, log = log))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testdfltWarn10() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list(\'x is neither a vector nor a matrix: using as.numeric(x)', quote(dotchart(table(infert$education)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(\'x is neither a vector nor a matrix: using as.numeric(x)', quote(dotchart(table(infert$education)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -79,7 +76,6 @@ public class TestBuiltin_dfltWarn extends TestBase {
 
     @Test
     public void testdfltWarn12() {
-        assertEval(Output.IgnoreWarningContext,
-                        "argv <- list('incomplete final line found by readTableHeader on foo4', quote(read.table('foo4', header = TRUE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list('incomplete final line found by readTableHeader on foo4', quote(read.table('foo4', header = TRUE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java
index 306597da00..c50fd3e298 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java
@@ -58,8 +58,6 @@ public class TestBuiltin_extract_dataframe extends TestBase {
     @Test
     public void extractDataFrameWithNULLNames() {
         assertEval("{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr[1,2] }");
-        // N.B.: this warning is surprisingly formatted with extra new line before the contents of
-        // warning(...) invoked from R code
-        assertEval(Output.IgnoreWarningContext, "{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr['col'] }");
+        assertEval("{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr['col'] }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java
index d6b89595d8..afeeea62aa 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java
@@ -38,8 +38,8 @@ public class TestBuiltin_factor extends TestBase {
 
         assertEval(Output.IgnoreErrorContext, "{ x<-factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-NULL; as.character(x) }");
         assertEval(Output.IgnoreErrorContext, "{ x<-factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-character(); as.character(x) }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-c(1,2,3); class(x)<-\"factor\"; x }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-c(\"1\",\"2\",\"3\"); class(x)<-\"factor\"; x }");
+        assertEval("{ x<-c(1,2,3); class(x)<-\"factor\"; x }");
+        assertEval("{ x<-c(\"1\",\"2\",\"3\"); class(x)<-\"factor\"; x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-c(1L,2L,3L); class(x)<-\"factor\"; x }");
 
         assertEval(Output.IgnoreErrorContext, "{ x<-factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-c(7L, 42L); x  }");
@@ -62,8 +62,8 @@ public class TestBuiltin_factor extends TestBase {
 
         assertEval("{ x<-c(1L, 2L, 1L); class(x)<-c(\"ordered\", \"factor\"); levels(x)<-c(\"a\", \"b\"); x > \"a\" }");
 
-        assertEval(Output.IgnoreWarningContext, "{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[1]<-x; y }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[1]<-x; y }");
+        assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[1]<-x; y }");
+        assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[1]<-x; y }");
         assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-list(1); y[[1]]<-x; y }");
         assertEval("{ x<-factor(c(\"c\", \"b\", \"a\", \"c\")); y<-c(1); y[[1]]<-x; y }");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
index 5c9ab0bd62..6c0ecb1d2d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
@@ -174,7 +174,7 @@ public class TestBuiltin_gsub extends TestBase {
         assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\") }");
         assertEval("{ gsub(\"a\",\"aa\", \"prague alley\", fixed=TRUE) }");
         assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\", fixed=TRUE) }");
-        assertEval(Output.IgnoreWarningContext, "{ gsub(\"a\",\"aa\", \"prAgue alley\", fixed=TRUE, ignore.case=TRUE) }");
+        assertEval("{ gsub(\"a\",\"aa\", \"prAgue alley\", fixed=TRUE, ignore.case=TRUE) }");
         assertEval("{ gsub(\"([a-e])\",\"\\\\1\\\\1\", \"prague alley\") }");
         assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\")) }");
         assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\"), fixed=TRUE) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java
index d4579d558c..d0ca51b6e3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java
@@ -30,6 +30,6 @@ public class TestBuiltin_isfactor extends TestBase {
         assertEval("{is.factor(1)}");
         assertEval("{is.factor(c)}");
 
-        assertEval(Output.IgnoreErrorContext, "{x<-1;class(x)<-\"factor\";is.factor(x)}");
+        assertEval("{x<-1;class(x)<-\"factor\";is.factor(x)}");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
index 62ede3d12e..59cd8da598 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
@@ -149,7 +149,7 @@ public class TestBuiltin_isna extends TestBase {
 
     @Test
     public void testisna29() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list(NULL);is.na(argv[[1]]);");
+        assertEval("argv <- list(NULL);is.na(argv[[1]]);");
     }
 
     @Test
@@ -247,7 +247,7 @@ public class TestBuiltin_isna extends TestBase {
         assertEval("{ is.na(1[10]) }");
         assertEval("{ is.na(c(1[10],2[10],3)) }");
         assertEval("{ is.na(list(1[10],1L[10],list(),integer())) }");
-        assertEval(Output.IgnoreWarningContext, "is.na(quote(x()))");
+        assertEval("is.na(quote(x()))");
         assertEval("is.na(is.na)");
 
         assertEval("is.na(data.frame(col1=1:5, col2=c(NA, 1, NA, 2, NA)))");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
index a4bf2ecafe..e2e5405b40 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
@@ -36,7 +36,7 @@ public class TestBuiltin_levels extends TestBase {
         assertEval("{ x <- 1 ; levels(x)<-c(\"cat\", \"dog\"); levels(x)}");
         assertEval("{ x <- 1 ; levels(x)<-c(3, \"cat\"); levels(x);}");
         assertEval("{ x <- 1 ; levels(x)<-c(1, \"cat\", 4.5, \"3\"); levels(x);}");
-        assertEval("{ x <- 1 ; levels(x)<-NULL; levels(notx)}");
+        assertEval(Output.MayIgnoreErrorContext, "{ x <- 1 ; levels(x)<-NULL; levels(notx)}");
         assertEval("{ x <- NULL; levels(x)<-\"dog\"; levels(x)}");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
index 9988eac042..1ac1ef7f5b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
@@ -184,13 +184,13 @@ public class TestBuiltin_max extends TestBase {
         assertEval("{ max(\"42\", \"7\") }");
 
         assertEval("{ max(as.double(NA), na.rm=FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ max(as.double(NA), as.double(NA), na.rm=TRUE) }");
+        assertEval("{ max(as.double(NA), as.double(NA), na.rm=TRUE) }");
         assertEval("{ max(as.double(NA), as.double(NA), na.rm=FALSE) }");
         assertEval("{ max(as.integer(NA), na.rm=FALSE) }");
         assertEval("{ max(as.integer(NA), as.integer(NA), na.rm=FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ max(as.character(NA), na.rm=TRUE) }");
+        assertEval("{ max(as.character(NA), na.rm=TRUE) }");
         assertEval("{ max(as.character(NA), na.rm=FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ max(as.character(NA), as.character(NA), na.rm=TRUE) }");
+        assertEval("{ max(as.character(NA), as.character(NA), na.rm=TRUE) }");
         assertEval("{ max(as.character(NA), as.character(NA), na.rm=FALSE) }");
         assertEval("{ max(42L, as.integer(NA), na.rm=TRUE) }");
         assertEval("{ max(42L, as.integer(NA), na.rm=FALSE) }");
@@ -216,7 +216,7 @@ public class TestBuiltin_max extends TestBase {
 
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer(0)) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer()) }");
-        assertEval(Output.IgnoreWarningContext, "{ max(as.double(NA), na.rm=TRUE) }");
+        assertEval("{ max(as.double(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
index a083740070..cd6cea5290 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
@@ -119,7 +119,7 @@ public class TestBuiltin_mean extends TestBase {
 
     @Test
     public void testmean22() {
-        assertEval(Output.IgnoreWarningContext, "argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE',     'TRUE'), class = 'factor')), .Names = 'x');do.call('mean', argv)");
+        assertEval("argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE',     'TRUE'), class = 'factor')), .Names = 'x');do.call('mean', argv)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
index 8cf0b4359d..685a13c6d2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
@@ -152,13 +152,13 @@ public class TestBuiltin_min extends TestBase {
         assertEval("{ min(\"42\", \"7\") }");
 
         assertEval("{ min(as.double(NA), na.rm=FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ min(as.double(NA), as.double(NA), na.rm=TRUE) }");
+        assertEval("{ min(as.double(NA), as.double(NA), na.rm=TRUE) }");
         assertEval("{ min(as.double(NA), as.double(NA), na.rm=FALSE) }");
         assertEval("{ min(as.integer(NA), na.rm=FALSE) }");
         assertEval("{ min(as.integer(NA), as.integer(NA), na.rm=FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ min(as.character(NA), na.rm=TRUE) }");
+        assertEval("{ min(as.character(NA), na.rm=TRUE) }");
         assertEval("{ min(as.character(NA), na.rm=FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ min(as.character(NA), as.character(NA), na.rm=TRUE) }");
+        assertEval("{ min(as.character(NA), as.character(NA), na.rm=TRUE) }");
         assertEval("{ min(as.character(NA), as.character(NA), na.rm=FALSE) }");
         assertEval("{ min(42L, as.integer(NA), na.rm=TRUE) }");
         assertEval("{ min(42L, as.integer(NA), na.rm=FALSE) }");
@@ -175,7 +175,7 @@ public class TestBuiltin_min extends TestBase {
 
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(integer(0)) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(integer()) }");
-        assertEval(Output.IgnoreWarningContext, "{ min(as.double(NA), na.rm=TRUE) }");
+        assertEval("{ min(as.double(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.integer(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
index 1d26cefe10..b2dd1d1206 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
@@ -181,7 +181,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators33() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list(c(20.8, 11.2, 6.2, 12.8, 43.4), c(10.4, 5.6, 3.1, 6.4, 21.7, 0, 10.4, 5.6, 3.1, 6.4, 21.7));`+`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(c(20.8, 11.2, 6.2, 12.8, 43.4), c(10.4, 5.6, 3.1, 6.4, 21.7, 0, 10.4, 5.6, 3.1, 6.4, 21.7));`+`(argv[[1]],argv[[2]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
index 5298a7200a..5ccb8c0e1e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
@@ -97,7 +97,7 @@ public class TestBuiltin_pmax extends TestBase {
 
         assertEval("{ pmax(c(1, 7), c(42, 1)) }");
         assertEval("{ pmax(c(1, 7), double()) }");
-        assertEval(Output.IgnoreWarningContext, "{ pmax(c(1, 7, 8), c(1), c(42, 1)) }");
+        assertEval("{ pmax(c(1, 7, 8), c(1), c(42, 1)) }");
         assertEval("{ pmax(c(1, 7), c(42, as.double(NA))) }");
         assertEval("{ pmax(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
index 6ea406f009..29710a9eae 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
@@ -76,13 +76,13 @@ public class TestBuiltin_pmin extends TestBase {
     public void testPMin() {
         assertEval("{ pmin(c(1L, 7L), c(42L, 1L)) }");
         assertEval("{ pmin(c(1L, 7L), integer()) }");
-        assertEval(Output.IgnoreWarningContext, "{ pmin(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }");
+        assertEval("{ pmin(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }");
         assertEval("{ pmin(c(1L, 7L), c(42L, as.integer(NA))) }");
         assertEval("{ pmin(c(1L, 7L), c(42L, as.integer(NA)), na.rm=TRUE) }");
 
         assertEval("{ pmin(c(1, 7), c(42, 1)) }");
         assertEval("{ pmin(c(1, 7), double()) }");
-        assertEval(Output.IgnoreWarningContext, "{ pmin(c(1, 7, 8), c(1), c(42, 1)) }");
+        assertEval("{ pmin(c(1, 7, 8), c(1), c(42, 1)) }");
         assertEval("{ pmin(c(1, 7), c(42, as.double(NA))) }");
         assertEval("{ pmin(c(1, 7), c(42, as.double(NA)), na.rm=TRUE) }");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
index e4de9fa076..33ae519955 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
@@ -63,11 +63,9 @@ public class TestBuiltin_rawConnection extends TestRBase {
 
     @Test
     public void testWriteBinary() {
-
         // this test is currently ignored, since 'charToRaw' is not compliant
         assertEval(Ignored.Unknown, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval(Output.IgnoreWarningContext,
-                        "{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
+        assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
     }
 
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
index e15b21ddd4..5591689a05 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
@@ -205,10 +205,10 @@ public class TestBuiltin_rep extends TestBase {
         assertEval("{ rep(7, times=NULL) }");
         assertEval("{ rep(7, times=\"7\") }");
         assertEval("{ rep(7, length.out=\"7\") }");
-        assertEval(Output.IgnoreWarningContext, "{ rep(7, length.out=integer()) }");
+        assertEval("{ rep(7, length.out=integer()) }");
         assertEval("{ rep(7, length.out=NA) }");
         assertEval("{ rep(7, length.out=NULL) }");
-        assertEval(Output.IgnoreWarningContext, "{ rep(7, length.out=c(7, 42)) }");
+        assertEval("{ rep(7, length.out=c(7, 42)) }");
         assertEval("{ rep(7, each=\"7\") }");
         assertEval("{ rep(7, each=integer()) }");
         assertEval("{ rep(7, each=NA) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
index d317ae23a5..2f2074ef28 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
@@ -24,13 +24,13 @@ public class TestBuiltin_scan extends TestBase {
         assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, skip = 1, quiet = TRUE) }");
         assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, skip = 1) }");
         assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, skip = 1, nlines = 1) }");
-        assertEval(Output.IgnoreWarningContext, "{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, what = list(\"\",\"\",\"\")) }");
+        assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, what = list(\"\",\"\",\"\")) }");
         assertEval("{ con<-textConnection(c(\"TITLE extra line\", \"2 3 5 7\", \"11 13 17\")); scan(con, what = list(\"\",\"\",\"\"), flush=TRUE) }");
 
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, skip = 1) }");
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, skip = 1, quiet=TRUE) }");
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, skip = 1, nlines = 1) }");
-        assertEval(Output.IgnoreWarningContext, "{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\")) }");
+        assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\")) }");
 
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), fill=TRUE) }");
         assertEval("{ con<-textConnection(c(\"HEADER\", \"7 2 3\", \"4 5 42\")); scan(con, what = list(\"\",\"\",\"\"), multi.line=FALSE) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java
index 2799e9a5ec..f06f1669ca 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java
@@ -107,8 +107,7 @@ public class TestBuiltin_strsplit extends TestBase {
         assertEval("{ strsplit(\"ahoj\", split=\"\") [[c(1,2)]] }");
         assertEval("{ strsplit(\"a,h,o,j\", split=\",\") }");
         assertEval("{ strsplit(\"abc\", \".\", fixed = TRUE, perl=FALSE) }");
-        // Warning text formats differently
-        assertEval(Output.IgnoreWarningContext, "{ strsplit(\"abc\", \".\", fixed = TRUE, perl=TRUE) }");
+        assertEval("{ strsplit(\"abc\", \".\", fixed = TRUE, perl=TRUE) }");
         assertEval("{ strsplit(\"abc\", \".\", fixed = FALSE, perl=FALSE) }");
         assertEval("{ strsplit(\"abc\", \".\", fixed = FALSE, perl=TRUE) }");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java
index 811272afd4..af45e08505 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java
@@ -184,10 +184,10 @@ public class TestBuiltin_sum extends TestBase {
     public void testOveflow() {
         assertEval("sum(1:100000)");
         assertEval("sum(seq.int(1, 100000))");
-        assertEval(Output.IgnoreWarningContext, "sum(seq.int(from=1, by=1, length.out=100000))");
+        assertEval("sum(seq.int(from=1, by=1, length.out=100000))");
         assertEval("sum(-1:-100000)");
         assertEval("sum(seq.int(-1, -100000))");
-        assertEval(Output.IgnoreWarningContext, "sum(seq.int(from=-1, by=-1, length.out=100000))");
+        assertEval("sum(seq.int(from=-1, by=-1, length.out=100000))");
 
         assertEval("sum(c(2147483647L, 1L))");
         assertEval("sum(c(-2147483647L, -1L))");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java
index acef8ebf71..ec16560044 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java
@@ -320,10 +320,10 @@ public class TestSimpleArithmetic extends TestBase {
 
     @Test
     public void testVectorsLengthWarning() {
-        assertEval(Output.IgnoreWarningContext, "{ 1:2+1:3 }");
-        assertEval(Output.IgnoreWarningContext, "{ 1:3*1:2 }");
-        assertEval(Output.IgnoreWarningContext, "{ 1:3+c(1,2+2i) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(1,2+2i)+1:3 }");
+        assertEval("{ 1:2+1:3 }");
+        assertEval("{ 1:3*1:2 }");
+        assertEval("{ 1:3+c(1,2+2i) }");
+        assertEval("{ c(1,2+2i)+1:3 }");
     }
 
     @Test
@@ -612,11 +612,11 @@ public class TestSimpleArithmetic extends TestBase {
 
     @Test
     public void testNonvectorizedLogicalLengthChecks() {
-        assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,4)) | as.raw(c(1,5,4)) }");
-        assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,5,4)) | as.raw(c(1,4)) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(TRUE, FALSE, FALSE) & c(TRUE,TRUE) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(a=TRUE, TRUE) | c(TRUE, b=FALSE, FALSE) }");
+        assertEval("{ as.raw(c(1,4)) | as.raw(c(1,5,4)) }");
+        assertEval("{ as.raw(c(1,5,4)) | as.raw(c(1,4)) }");
+        assertEval("{ c(TRUE, FALSE, FALSE) & c(TRUE,TRUE) }");
+        assertEval("{ c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) }");
+        assertEval("{ c(a=TRUE, TRUE) | c(TRUE, b=FALSE, FALSE) }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java
index 5ba65d7130..557546aaeb 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java
@@ -209,18 +209,18 @@ public class TestSimpleComparison extends TestBase {
         assertEval("{ 1:3 == TRUE }");
         assertEval("{ TRUE == 1:3 }");
 
-        assertEval(Output.IgnoreWarningContext, "{ c(1,2) < c(2,1,4) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(2,1,4) < c(1,2) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(1L,2L) < c(2L,1L,4L) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(2L,1L,4L) < c(1L,2L) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(TRUE,FALSE,FALSE) < c(TRUE,TRUE) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(TRUE,TRUE) == c(TRUE,FALSE,FALSE) }");
-        assertEval(Output.IgnoreWarningContext, "{ as.raw(c(1,2)) < as.raw(c(2,1,4)) }");
-        assertEval(Output.IgnoreWarningContext, "{ as.raw(c(2,1,4)) < as.raw(c(1,2)) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(\"hi\",\"hello\",\"bye\") > c(\"cau\", \"ahoj\") }");
-        assertEval(Output.IgnoreWarningContext, "{ c(\"cau\", \"ahoj\") != c(\"hi\",\"hello\",\"bye\") }");
-        assertEval(Output.IgnoreWarningContext, "{ c(1+1i,2+2i) == c(2+1i,1+2i,1+1i) }");
-        assertEval(Output.IgnoreWarningContext, "{ c(2+1i,1+2i,1+1i) == c(1+1i, 2+2i) }");
+        assertEval("{ c(1,2) < c(2,1,4) }");
+        assertEval("{ c(2,1,4) < c(1,2) }");
+        assertEval("{ c(1L,2L) < c(2L,1L,4L) }");
+        assertEval("{ c(2L,1L,4L) < c(1L,2L) }");
+        assertEval("{ c(TRUE,FALSE,FALSE) < c(TRUE,TRUE) }");
+        assertEval("{ c(TRUE,TRUE) == c(TRUE,FALSE,FALSE) }");
+        assertEval("{ as.raw(c(1,2)) < as.raw(c(2,1,4)) }");
+        assertEval("{ as.raw(c(2,1,4)) < as.raw(c(1,2)) }");
+        assertEval("{ c(\"hi\",\"hello\",\"bye\") > c(\"cau\", \"ahoj\") }");
+        assertEval("{ c(\"cau\", \"ahoj\") != c(\"hi\",\"hello\",\"bye\") }");
+        assertEval("{ c(1+1i,2+2i) == c(2+1i,1+2i,1+1i) }");
+        assertEval("{ c(2+1i,1+2i,1+1i) == c(1+1i, 2+2i) }");
 
         assertEval("{ as.raw(c(2,1,4)) < raw() }");
         assertEval("{ raw() < as.raw(c(2,1,4)) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
index c6c1b883c1..38e697cebf 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
@@ -100,9 +100,9 @@ public class TestSimpleDataFrames extends TestBase {
         assertEval("{ x<-as.character(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }");
         assertEval("{ x<-as.complex(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }");
         assertEval("{ x<-as.raw(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=\"r1\", nm=\"x\"); attributes(y); }");
-        assertEval("{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\"), nm=\"x\"); attributes(y); }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\", \"r3\"), nm=\"x\"); attributes(y); }");
+        assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=\"r1\", nm=\"x\"); attributes(y); }");
+        assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\"), nm=\"x\"); attributes(y); }");
+        assertEval("{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\", \"r3\"), nm=\"x\"); attributes(y); }");
         assertEval("{ x<-matrix(c(1,2,3,4), nrow=2); y<-as.data.frame(x, row.names=NULL, optional=FALSE); attributes(y); }");
         assertEval("{ x<-matrix(c(1,2,3,4), nrow=2); y<-as.data.frame(x, row.names=\"r1\", optional=FALSE); attributes(y); }");
         assertEval("{ x<-1; class(x)<-\"foo\"; y<-as.data.frame(x) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
index 9ed8cb3b99..d7063ba2a9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
@@ -51,45 +51,45 @@ public class TestSimpleIfEvaluator extends TestBase {
     @Test
     public void testIf() {
         assertEval("{ x <- 2 ; if (1==x) TRUE else 2 }");
-        assertEval(Output.IgnoreErrorContext, "{ x <- 2 ; if (NA) x <- 3 ; x }");
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(NA)  }");
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(NA) }");
+        assertEval("{ x <- 2 ; if (NA) x <- 3 ; x }");
+        assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(NA)  }");
+        assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(NA) }");
         assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(TRUE) }");
         assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(FALSE) }");
 
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(\"hello\") }");
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(logical()) }");
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(x) { if (x == 2) 1 else 2 } ; f(1) ; f(NA) }");
+        assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(\"hello\") }");
+        assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(logical()) }");
+        assertEval("{ f <- function(x) { if (x == 2) 1 else 2 } ; f(1) ; f(NA) }");
 
         assertEval("{ if (TRUE==FALSE) TRUE else FALSE }");
-        assertEval(Output.IgnoreErrorContext, "{ if (NA == TRUE) TRUE else FALSE }");
-        assertEval(Output.IgnoreErrorContext, "{ if (TRUE == NA) TRUE else FALSE }");
+        assertEval("{ if (NA == TRUE) TRUE else FALSE }");
+        assertEval("{ if (TRUE == NA) TRUE else FALSE }");
         assertEval("{ if (FALSE==TRUE) TRUE else FALSE }");
         assertEval("{ if (FALSE==1) TRUE else FALSE }");
         assertEval("{ f <- function(v) { if (FALSE==v) TRUE else FALSE } ; f(TRUE) ; f(1) }");
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ x<-list(1,2); if (x) 7 else 42 }");
+        assertEval("{ x<-list(1,2); if (x) 7 else 42 }");
         assertEval("{ if (!(7+42i)) TRUE else FALSE }");
     }
 
     @Test
     public void testIfIgnore() {
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(1:3) }");
+        assertEval("{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(1:3) }");
     }
 
     @Test
     public void testCast() {
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(a) { if (is.na(a)) { 1 } else { 2 } } ; f(5) ; f(1:3)}");
-        assertEval(Output.IgnoreWarningContext, "{ if (1:3) { TRUE } }");
-        assertEval(Output.IgnoreErrorContext, "{ if (integer()) { TRUE } }");
-        assertEval(Output.IgnoreErrorContext, "{ if (1[2:1]) { TRUE } }");
-        assertEval(Output.IgnoreWarningContext, "{ if (c(0,0,0)) { TRUE } else { 2 } }");
-        assertEval(Output.IgnoreWarningContext, "{ if (c(1L,0L,0L)) { TRUE } else { 2 } }");
-        assertEval(Output.IgnoreWarningContext, "{ if (c(0L,0L,0L)) { TRUE } else { 2 } }");
-        assertEval(Output.IgnoreErrorContext, "{ if (c(1L[2],0L,0L)) { TRUE } else { 2 } }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(1:3) ; f(2) }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(c(TRUE,FALSE)) ; f(FALSE) }");
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(logical()) }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(c(TRUE,FALSE)) ; f(1) }");
+        assertEval("{ f <- function(a) { if (is.na(a)) { 1 } else { 2 } } ; f(5) ; f(1:3)}");
+        assertEval("{ if (1:3) { TRUE } }");
+        assertEval("{ if (integer()) { TRUE } }");
+        assertEval("{ if (1[2:1]) { TRUE } }");
+        assertEval("{ if (c(0,0,0)) { TRUE } else { 2 } }");
+        assertEval("{ if (c(1L,0L,0L)) { TRUE } else { 2 } }");
+        assertEval("{ if (c(0L,0L,0L)) { TRUE } else { 2 } }");
+        assertEval("{ if (c(1L[2],0L,0L)) { TRUE } else { 2 } }");
+        assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(1:3) ; f(2) }");
+        assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(c(TRUE,FALSE)) ; f(FALSE) }");
+        assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(logical()) }");
+        assertEval("{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(c(TRUE,FALSE)) ; f(1) }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
index 15e11180f0..ce3819fa70 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
@@ -49,7 +49,7 @@ public class TestSimpleLoop extends TestBase {
 
     @Test
     public void testLoopsErrors() {
-        assertEval(Output.IgnoreErrorContext, "{ while (1 < NA) { 1 } }");
+        assertEval("{ while (1 < NA) { 1 } }");
 
         assertEval("{ break; }");
         assertEval("{ next; }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java
index 75b2a0d373..e347c051f5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java
@@ -53,7 +53,7 @@ public class TestSimpleTruffle extends TestBase {
     @Test
     public void testWarningsAndErrors() {
         assertEval("{ (c(1, 2) < c(1, 2, 3)) ==  (c(1, 2) < c(1, 3, 4)) }");
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ 1i > (c(1, 2) < c(1, 2, 3)) }");
+        assertEval("{ 1i > (c(1, 2) < c(1, 2, 3)) }");
         assertEval("{ 1i > ((c(1, 2) < c(1, 2, 3)) ==  (c(1, 2) < c(1, 3, 4))) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
index c5ab5f2053..21158c964e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
@@ -382,7 +382,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ l<-list(1,2,3,4); l[[c(2,1)]]<-7; l }");
         assertEval("{ l<-list(1,2,3,4); l[c(2,1)]<-7; l }");
 
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4; x[1]<-c(1,1); x }");
+        assertEval("{ x<-1:4; x[1]<-c(1,1); x }");
         assertEval("{ x<-1:4; x[[1]]<-c(1,1); x }");
         assertEval("{ x<-1; x[0]<-integer(); x }");
         assertEval(Output.IgnoreErrorMessage, "{ x<-1; x[[0]]<-integer(); x }");
@@ -399,8 +399,8 @@ public class TestSimpleVectors extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ x<-7; x[[0]]<-42; x }");
         assertEval("{ x<-1:4;  x[c(1, 0)]<-42; x }");
         assertEval("{ x<-1:4;  x[c(0, 1)]<-42; x }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4;  x[c(1, 0)]<-c(7, 42); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4;  x[c(0, 1)]<-c(7, 42); x }");
+        assertEval("{ x<-1:4;  x[c(1, 0)]<-c(7, 42); x }");
+        assertEval("{ x<-1:4;  x[c(0, 1)]<-c(7, 42); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[NULL]<-42; x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[NA]<-42; x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[0]<-42; x }");
@@ -409,15 +409,15 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,NA)]<-c(42, 43); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(NA,1)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,0)]]<-c(42, 43); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x }");
+        assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,0,0)]]<-c(42, 43); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(1,0,0)]<-c(42, 43); x }");
+        assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,0,0)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,1,0)]]<-c(42, 43); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,1,0)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,1)]]<-c(42, 43); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(0,1)]<-c(42, 43); x }");
+        assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,1)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,0,1)]]<-c(42, 43); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x<-1:4; dim(x)<-c(2,2); x[c(0,0,1)]<-c(42, 43); x }");
+        assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,0,1)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,1,1)]]<-c(42, 43); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(0,1,1)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorMessage, "{ x<-1:4; dim(x)<-c(2,2); x[[c(0,0)]]<-c(42, 43); x }");
@@ -1432,7 +1432,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-1:2; x[[0-2]]<-100; x }");
 
         assertEval(Output.IgnoreErrorContext, "{ f <- function() { a[3] <- 4 } ; f() }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- c(1,2) ; z <- c(10,11) ; attr(z,\"my\") <- 4 ; b[2] <- z ; b }");
+        assertEval("{ b <- c(1,2) ; z <- c(10,11) ; attr(z,\"my\") <- 4 ; b[2] <- z ; b }");
         assertEval("{ b <- c(1,2) ; z <- b ; b[-2] <- 3L ; b }");
         assertEval("{ b <- c(1,2) ; z <- b ; b[-10L] <- FALSE ; b }");
         assertEval("{ b <- c(TRUE,NA) ; z <- b ; b[-10L] <- FALSE ; b }");
@@ -1723,17 +1723,17 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ b <- 3:4 ; b[c(NA)] <- c(2,7) ; b }");
         assertEval("{ b <- 3:4 ; b[c(NA,1)] <- c(2,10) ; b }");
         assertEval(Output.IgnoreErrorContext, "{ b <- 3:4 ; b[[c(NA,1)]] <- c(2,10) ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- 3:4 ; b[c(0,1)] <- c(2,10,11) ; b }");
+        assertEval("{ b <- 3:4 ; b[c(0,1)] <- c(2,10,11) ; b }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(3:4, c(1,2), c(10,11)) ; f(4:5, as.integer(NA), 2) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(3:4, c(1,2), c(10,11)) ; f(4:5, c(1,-1), 2) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(3:4, c(1,2), c(10,11)) ; f(4:5, c(NA,-1), 2) }");
 
         assertEval("{ b <- c(1,4,5) ; x <- c(2,8,2) ; b[x==2] <- c(10,11) ; b }");
         assertEval("{ b <- c(1,4,5) ; z <- b ; x <- c(2,8,2) ; b[x==2] <- c(10,11) ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- c(1,4,5) ;  x <- c(2,2) ; b[x==2] <- c(10,11) ; b }");
+        assertEval("{ b <- c(1,4,5) ;  x <- c(2,2) ; b[x==2] <- c(10,11) ; b }");
         assertEval("{ b <- c(1,2,5) ;  x <- c(2,2,NA) ; b[x==2] <- c(10,11,3) ; b }");
         assertEval("{ b <- c(1,2,5) ;  x <- as.double(NA) ; attr(x,\"my\") <- 2 ; b[c(1,NA,2)==2] <- x ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- c(1,2,5) ;  x <- c(2,2,-1) ; b[x==2] <- c(10,11,5) ; b }");
+        assertEval("{ b <- c(1,2,5) ;  x <- c(2,2,-1) ; b[x==2] <- c(10,11,5) ; b }");
 
         assertEval("{ b <- c(1,2,5) ; b[integer()] <- NULL ; b }");
         assertEval("{ b <- c(1,2,5) ; b[c(1)] <- NULL ; b }");
@@ -1769,13 +1769,13 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(c(3+4i,5+6i), c(FALSE,TRUE,TRUE), c(NA,1+10i)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(c(TRUE,FALSE), c(FALSE,TRUE,TRUE), c(NA,2L)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), c(NA,FALSE)) }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }");
+        assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(c(TRUE,TRUE,FALSE), c(FALSE,TRUE,TRUE), c(TRUE,NA)) }");
         assertEval(" { f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), c(NA,FALSE)) }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }");
+        assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }");
-        assertEval(Output.IgnoreErrorContext, "{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }");
+        assertEval(Output.ImprovedErrorContext, "{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }");
 
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,FALSE), list(1+2i)) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,FALSE), list(1+2i)) ; f(1:2, c(TRUE,FALSE), list(TRUE)) }");
@@ -1787,11 +1787,11 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,NA), 10) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(list(1,2), c(TRUE,NA), c(10,11)) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; x <- list(1,2) ; z <- x ; f(x, c(TRUE,NA), c(10,11)) }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- list(1,2) ; attr(x,\"my\") <- 10; x[c(TRUE,TRUE)] <- c(10,11,12); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- list(1,0) ; x[as.logical(x)] <- c(10,11); x }");
+        assertEval("{ x <- list(1,2) ; attr(x,\"my\") <- 10; x[c(TRUE,TRUE)] <- c(10,11,12); x }");
+        assertEval("{ x <- list(1,0) ; x[as.logical(x)] <- c(10,11); x }");
         assertEval("{ x <- list(1,0) ; x[is.na(x)] <- c(10,11); x }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- list(1,0) ; x[c(TRUE,FALSE)] <- x[2:1] ; x }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- list(1,0) ; attr(x,\"my\") <- 20 ; x[c(TRUE,FALSE)] <- c(11,12) ; x }");
+        assertEval("{ x <- list(1,0) ; x[c(TRUE,FALSE)] <- x[2:1] ; x }");
+        assertEval("{ x <- list(1,0) ; attr(x,\"my\") <- 20 ; x[c(TRUE,FALSE)] <- c(11,12) ; x }");
         assertEval("{ x <- list(1,0) ; x[is.na(x)] <- c(10L,11L); x }");
         assertEval("{ x <- list(1,0) ; x[c(TRUE,TRUE)] <- c(TRUE,NA); x }");
         assertEval("{ x <- list(1,0) ; x[logical()] <- c(TRUE,NA); x }");
@@ -1822,20 +1822,20 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- 5:6 ; x }");
         assertEval("{ x <- c(1L,2L,3L,4L) ; attr(x,\"my\") <- 0 ;  x[c(TRUE,FALSE)] <- 5:6 ; x }");
         assertEval("{ x <- c(1L,2L,3L,4L) ;  x[is.na(x)] <- 5:6 ; x }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- rev(x) ; x }");
+        assertEval("{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- rev(x) ; x }");
         assertEval("{ x <- c(1L,2L) ; x[logical()] <- 3L ; x }");
 
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE)] <- c(FALSE,NA) ; b }");
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,FALSE)] <- c(FALSE,NA) ; b }");
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,NA)] <- c(FALSE,NA) ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,TRUE)] <- c(FALSE,NA) ; b }");
+        assertEval("{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,TRUE)] <- c(FALSE,NA) ; b }");
         assertEval("{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,FALSE,TRUE,TRUE)] <- c(FALSE,NA,NA) ; b }");
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,NA)] <- FALSE ; b }");
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; z <- b ; b[c(TRUE,FALSE,TRUE,NA)] <- FALSE ; b }");
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; attr(b,\"my\") <- 10 ; b[c(TRUE,FALSE,TRUE,NA)] <- FALSE ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,FALSE)] <- b ; b }");
+        assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,FALSE)] <- b ; b }");
         assertEval("{ b <- c(TRUE,FALSE,FALSE,TRUE) ; b[b] <- c(TRUE,FALSE) ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(b,i,v) { b[b] <- b ; b } ; f(c(TRUE,FALSE,FALSE,TRUE)) ; f(1:3) }");
+        assertEval("{ f <- function(b,i,v) { b[b] <- b ; b } ; f(c(TRUE,FALSE,FALSE,TRUE)) ; f(1:3) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(TRUE,FALSE,FALSE,TRUE),c(TRUE,FALSE), NA) ; f(1:4, c(TRUE,TRUE), NA) }");
         assertEval("{ f <- function(b,i,v) { b[i] <- v ; b } ; f(c(TRUE,FALSE,FALSE,TRUE),c(TRUE,FALSE), NA) ; f(c(FALSE,FALSE,TRUE), c(TRUE,TRUE), c(1,2,3)) }");
         assertEval("{ b <- c(TRUE,NA,FALSE,TRUE) ; b[logical()] <- c(FALSE,NA) ; b }");
@@ -1846,7 +1846,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(TRUE,FALSE,NA)] <- \"X\" ; b }");
         assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[logical()] <- \"X\" ; b }");
         assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(FALSE,NA,NA)] <- c(\"X\",\"y\") ; b }");
-        assertEval(Output.IgnoreWarningContext, "{ b <- c(\"a\",\"b\",\"c\") ; b[c(FALSE,TRUE,TRUE)] <- c(\"X\",\"y\",\"z\") ; b }");
+        assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[c(FALSE,TRUE,TRUE)] <- c(\"X\",\"y\",\"z\") ; b }");
         assertEval("{ b <- c(\"a\",\"b\",\"c\") ; x <- b ; b[c(FALSE,TRUE,TRUE)] <- c(\"X\",\"z\") ; b } ");
         assertEval("{ b <- c(\"a\",\"b\",\"c\") ; x <- b ; b[c(FALSE,TRUE,NA)] <- c(\"X\",\"z\") ; b }");
         assertEval("{ b <- c(\"a\",\"b\",\"c\") ; b[is.na(b)] <- c(\"X\",\"z\") ; b }");
@@ -2103,12 +2103,12 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(as.complex(c(13,14)),c(\"\",\"\",\"\"),as.complex(23)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(as.complex(c(13,14)),c(\"\",\"\",NA),as.complex(23)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(as.raw(c(13,14)),c(\"a\",\"X\",\"a\"),as.raw(23)) }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"a\",\"X\",\"a\",\"b\"),list(3,TRUE,FALSE)) }");
+        assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"a\",\"X\",\"a\",\"b\"),list(3,TRUE,FALSE)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),list(3,TRUE,FALSE)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),as.raw(10)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),as.complex(10)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),1:3) }");
-        assertEval(Output.IgnoreWarningContext, "{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),c(TRUE,NA)) }");
+        assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1,a=2),c(\"X\",\"b\",NA),c(TRUE,NA)) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1L,a=2L),c(\"X\",\"b\",NA),c(TRUE,NA,FALSE)) }");
         assertEval(Output.IgnoreErrorContext, "{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1L,a=2L),c(\"X\",\"b\",NA),NULL) }");
         assertEval("{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(list(X=1L,a=2L),c(\"X\",\"b\",NA),NULL) }");
@@ -2162,10 +2162,10 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x <- NULL; x[c(0,1)] <- c(5); x; }");
         assertEval("{ x <- NULL; x[c(0,2)] <- c(5); x; }");
         assertEval("{ x <- NULL; x[0] <- c(1,5); x; }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[1] <- c(1,5); x; }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[c(1,0)] <- c(1,5); x; }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[c(0,1)] <- c(1,5); x; }");
-        assertEval(Output.IgnoreWarningContext, "{ x <- NULL; x[c(0,2)] <- c(1,5); x; }");
+        assertEval("{ x <- NULL; x[1] <- c(1,5); x; }");
+        assertEval("{ x <- NULL; x[c(1,0)] <- c(1,5); x; }");
+        assertEval("{ x <- NULL; x[c(0,1)] <- c(1,5); x; }");
+        assertEval("{ x <- NULL; x[c(0,2)] <- c(1,5); x; }");
         assertEval(Output.IgnoreErrorMessage, "{ x <- NULL; x[[c(1,0)]] <- c(1,5); x; }");
         assertEval(Output.IgnoreErrorMessage, "{ x <- NULL; x[[c(1,2)]] <- c(1,5); x; }");
 
-- 
GitLab


From 08bbd6aa794fb5dda5afb5e9168f56964c1a7571 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 24 Feb 2017 18:41:53 +0100
Subject: [PATCH 058/402] further simplifications around errors and warnings

---
 .../r/library/grDevices/DevicesCCalls.java    |  12 +-
 .../r/library/graphics/GraphicsCCalls.java    |   6 +-
 .../r/library/methods/SubstituteDirect.java   |   8 +-
 .../r/library/stats/RMultinomNode.java        |   2 +-
 .../r/library/stats/RandFunctionsNodes.java   |  11 +-
 .../truffle/r/library/utils/TypeConvert.java  |   8 +-
 .../truffle/r/nodes/builtin/base/Assign.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Attr.java    |   3 -
 .../r/nodes/builtin/base/EnvFunctions.java    |   3 -
 .../r/nodes/builtin/base/LaFunctions.java     |   3 -
 .../r/nodes/builtin/base/MatchArg.java        |   7 +-
 .../truffle/r/nodes/builtin/base/PMinMax.java |   6 +-
 .../truffle/r/nodes/builtin/base/Paste.java   |   5 +-
 .../r/nodes/builtin/base/Quantifier.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Repeat.java  |  24 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |   2 +-
 .../r/nodes/builtin/base/StandardGeneric.java |   4 +-
 .../r/nodes/builtin/base/UpdateAttr.java      |   2 +-
 .../foreign/CallAndExternalFunctions.java     |  16 -
 .../base/foreign/FortranAndCFunctions.java    |  18 +-
 .../builtin/base/foreign/LookupAdapter.java   |   4 +-
 .../r/nodes/builtin/CastBuilderTest.java      |   5 +-
 .../builtin/ResultTypesAnalyserTest.java      |   2 +-
 .../r/nodes/builtin/SampleCollectorTest.java  |   2 +-
 .../truffle/r/nodes/casts/TestCasts.java      |   3 +-
 .../r/nodes/test/PipelineToCastNodeTests.java |   2 +-
 .../r/nodes/access/RemoveAndAnswerNode.java   |   2 +-
 .../access/vector/PositionsCheckNode.java     |   2 +
 .../r/nodes/binary/BinaryArithmeticNode.java  |   2 +-
 .../r/nodes/binary/BinaryBooleanNode.java     |   2 +-
 .../truffle/r/nodes/builtin/CastBuilder.java  |  13 +-
 .../truffle/r/nodes/builtin/InternalNode.java |   6 +
 .../nodes/builtin/NodeWithArgumentCasts.java  |  18 +-
 .../truffle/r/nodes/builtin/RBuiltinNode.java |   2 +-
 .../r/nodes/builtin/casts/MessageData.java    |  14 -
 .../r/nodes/builtin/casts/PipelineConfig.java |   9 +-
 .../builtin/casts/PipelineToCastNode.java     |  40 +-
 .../builtin/casts/fluent/CastNodeBuilder.java |   6 +-
 .../builtin/casts/fluent/PipelineBuilder.java |   5 +-
 .../casts/fluent/PipelineConfigBuilder.java   |   7 +-
 .../r/nodes/function/CallMatcherNode.java     |   5 +
 .../truffle/r/nodes/function/RCallNode.java   |   5 +
 .../nodes/function/signature/MissingNode.java |   1 -
 .../truffle/r/nodes/objects/NewObject.java    |   6 +-
 .../truffle/r/nodes/unary/CastBaseNode.java   |  26 +-
 .../r/nodes/unary/CastComplexNode.java        |  12 +-
 .../r/nodes/unary/CastDoubleBaseNode.java     |  15 +-
 .../truffle/r/nodes/unary/CastDoubleNode.java |  18 +-
 .../r/nodes/unary/CastExpressionNode.java     |   2 +-
 .../r/nodes/unary/CastIntegerBaseNode.java    |  19 +-
 .../r/nodes/unary/CastIntegerNode.java        |  23 +-
 .../r/nodes/unary/CastLogicalBaseNode.java    |   9 +-
 .../r/nodes/unary/CastLogicalNode.java        |   7 +-
 .../truffle/r/nodes/unary/CastNode.java       |  21 +-
 .../truffle/r/nodes/unary/CastRawNode.java    |  26 +-
 .../truffle/r/nodes/unary/CastSymbolNode.java |   6 +-
 .../r/nodes/unary/FirstStringNode.java        |  12 +-
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../r/runtime/nmath/RandomFunctions.java      |   4 +-
 .../truffle/r/runtime/nmath/distr/RHyper.java |   2 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 435 +++++++++---------
 .../builtins/TestBuiltin_anyDuplicated.java   |   4 +-
 .../r/test/builtins/TestBuiltin_asvector.java |  10 +-
 .../test/builtins/TestBuiltin_duplicated.java |   4 +-
 .../r/test/builtins/TestBuiltin_pmax.java     |   4 +-
 .../r/test/builtins/TestBuiltin_pmin.java     |   2 +-
 .../library/stats/TestExternal_rbinom.java    |   2 +-
 .../stats/TestRandGenerationFunctions.java    |   2 +-
 68 files changed, 417 insertions(+), 558 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
index 1b6c1f9833..d7ba80d07c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
@@ -17,8 +17,6 @@ package com.oracle.truffle.r.library.grDevices;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
-
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen;
@@ -59,11 +57,11 @@ public class DevicesCCalls {
 
     public static final class C_PDF extends RExternalBuiltinNode {
 
-        @Child private CastNode extractFontsNode = newCastBuilder(NO_CALLER).mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode();
-        @Child private CastNode asStringNode = newCastBuilder(NO_CALLER).asStringVector().findFirst().buildCastNode();
-        @Child private CastNode asDoubleNode = newCastBuilder(NO_CALLER).asDoubleVector().findFirst().buildCastNode();
-        @Child private CastNode asLogicalNode = newCastBuilder(NO_CALLER).asLogicalVector().findFirst().buildCastNode();
-        @Child private CastNode asIntNode = newCastBuilder(NO_CALLER).asIntegerVector().findFirst().buildCastNode();
+        @Child private CastNode extractFontsNode = newCastBuilder().mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode();
+        @Child private CastNode asStringNode = newCastBuilder().asStringVector().findFirst().buildCastNode();
+        @Child private CastNode asDoubleNode = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
+        @Child private CastNode asLogicalNode = newCastBuilder().asLogicalVector().findFirst().buildCastNode();
+        @Child private CastNode asIntNode = newCastBuilder().asIntegerVector().findFirst().buildCastNode();
 
         static {
             Casts.noCasts(C_PDF.class);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
index 2f04283ba5..adee6f49ea 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
@@ -17,8 +17,6 @@ package com.oracle.truffle.r.library.graphics;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
-
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
 import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
@@ -37,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 public class GraphicsCCalls {
     public static final class C_PlotXY extends RExternalBuiltinNode {
 
-        @Child private CastNode castXYNode = newCastBuilder(NO_CALLER).mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
+        @Child private CastNode castXYNode = newCastBuilder().mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
 
         static {
             Casts.noCasts(C_PlotXY.class);
@@ -106,7 +104,7 @@ public class GraphicsCCalls {
         private double col = RRuntime.DOUBLE_NA;
         private double font = RRuntime.DOUBLE_NA;
 
-        @Child private CastNode firstDoubleCast = newCastBuilder(NO_CALLER).asDoubleVector().findFirst().buildCastNode();
+        @Child private CastNode firstDoubleCast = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
 
         static {
             Casts.noCasts(C_mtext.class);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
index d450b30ac4..0bd6d97f09 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
@@ -38,14 +38,20 @@ import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
     static {
-        Casts casts = new Casts(SubstituteDirect.class, RError.SHOW_CALLER);
+        Casts casts = new Casts(SubstituteDirect.class);
         casts.arg(1).defaultError(INVALID_LIST_FOR_SUBSTITUTION).mustBe(instanceOf(RAbstractListVector.class).or(instanceOf(REnvironment.class)));
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return RError.SHOW_CALLER;
+    }
+
     @Specialization
     @TruffleBoundary
     protected static Object substituteDirect(Object object, REnvironment env) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
index f2644dfb67..0379b9d46d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java
@@ -52,7 +52,7 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 {
     }
 
     static {
-        Casts casts = new Casts(RMultinomNode.class, RError.SHOW_CALLER);
+        Casts casts = new Casts(RMultinomNode.class);
         casts.arg(0).asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_FIRST_ARGUMENT_NAME, "n");
         casts.arg(1).asIntegerVector().findFirst().mustBe(notIntNA(), Message.INVALID_SECOND_ARGUMENT_NAME, "size");
         casts.arg(2).mustBe(missingValue().not(), Message.ARGUMENT_MISSING, "prob").mapIf(nullValue(), emptyDoubleVector()).asDoubleVector();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index c5a88e9279..2dbf940c2f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -99,7 +99,7 @@ public final class RandFunctionsNodes {
      * result vector, and similar. The random function is provided as implementation of
      * {@link RandFunction3_Double}.
      */
-    protected abstract static class RandFunctionExecutorBase extends Node {
+    protected abstract static class RandFunctionExecutorBase extends RBaseNode {
         static final class RandGenerationNodeData {
             final BranchProfile nanResult = BranchProfile.create();
             final BranchProfile nan = BranchProfile.create();
@@ -111,6 +111,11 @@ public final class RandFunctionsNodes {
             }
         }
 
+        @Override
+        protected RBaseNode getErrorContext() {
+            return RError.SHOW_CALLER;
+        }
+
         public abstract Object execute(RAbstractVector length, RAbstractDoubleVector a, RAbstractDoubleVector b, RAbstractDoubleVector c, RandomNumberProvider rand);
 
         @Child private ConvertToLength convertToLength = ConvertToLengthNodeGen.create();
@@ -149,8 +154,8 @@ public final class RandFunctionsNodes {
             RRNG.putRNGState();
         }
 
-        static void showNAWarning() {
-            RError.warning(SHOW_CALLER, RError.Message.NA_PRODUCED);
+        void showNAWarning() {
+            warning(RError.Message.NA_PRODUCED);
         }
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
index 34a46b38cc..00ef74c006 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/TypeConvert.java
@@ -48,13 +48,14 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 {
 
     @Child private SetFixedAttributeNode setLevelsAttrNode = SetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY);
 
     static {
-        Casts casts = new Casts(TypeConvert.class, RError.SHOW_CALLER);
+        Casts casts = new Casts(TypeConvert.class);
         casts.arg(0).mustBe(stringValue(), FIRST_ARGUMENT_MUST_BE_CHARACTER).asStringVector();
         casts.arg(1).mustBe(stringValue(), INVALID_ARG, "'na.strings'").asStringVector();
         casts.arg(2).mapIf(logicalValue(),
@@ -62,6 +63,11 @@ public abstract class TypeConvert extends RExternalBuiltinNode.Arg5 {
                         chain(map(constant(LOGICAL_FALSE))).with(toBoolean()).end());
     }
 
+    @Override
+    protected RBaseNode getErrorContext() {
+        return RError.SHOW_CALLER;
+    }
+
     private static boolean isNA(String s, RAbstractStringVector naStrings) {
         // naStrings are in addition to NA_character_
         if (RRuntime.isNA(s)) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
index 42833c94fe..7daef2edc8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
@@ -66,7 +66,7 @@ public abstract class Assign extends RBuiltinNode {
     }
 
     @Override
-    protected RBaseNode getErrorContext() {
+    public RBaseNode getErrorContext() {
         return direct ? this : super.getErrorContext();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
index 530f77eb8e..e566319c45 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode;
@@ -60,7 +59,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 public abstract class Attr extends RBuiltinNode {
 
     private final ConditionProfile searchPartialProfile = ConditionProfile.createBinaryProfile();
-    private final BranchProfile errorProfile = BranchProfile.create();
 
     @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create();
     @Child private InternStringNode intern = InternStringNodeGen.create();
@@ -141,7 +139,6 @@ public abstract class Attr extends RBuiltinNode {
         if (object instanceof RAttributable) {
             return attrRA((RAttributable) object, intern.execute((String) name), (boolean) exact);
         } else {
-            errorProfile.enter();
             throw RError.nyi(this, "object cannot be attributed");
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 390b88decb..17f87b4f05 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -45,7 +45,6 @@ import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
@@ -88,7 +87,6 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 public class EnvFunctions {
 
     protected abstract static class Adapter extends RBuiltinNode {
-        protected final BranchProfile errorProfile = BranchProfile.create();
     }
 
     @RBuiltin(name = "as.environment", kind = PRIMITIVE, parameterNames = {"fun"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
@@ -289,7 +287,6 @@ public class EnvFunctions {
         @Specialization
         protected REnvironment parentenv(REnvironment env) {
             if (env == REnvironment.emptyEnv()) {
-                errorProfile.enter();
                 throw error(RError.Message.EMPTY_NO_PARENT);
             }
             return env.getParent();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 27d3bd635c..fec8c896f3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -444,7 +444,6 @@ public class LaFunctions {
     @RBuiltin(name = "La_chol", kind = INTERNAL, parameterNames = {"a", "pivot", "tol"}, behavior = PURE)
     public abstract static class LaChol extends RBuiltinNode {
 
-        private final BranchProfile errorProfile = BranchProfile.create();
         private final ConditionProfile noPivot = ConditionProfile.createBinaryProfile();
 
         @Child private SetFixedAttributeNode setPivotAttrNode = SetFixedAttributeNode.create("pivot");
@@ -482,7 +481,6 @@ public class LaFunctions {
             if (noPivot.profile(!piv)) {
                 info = dpotrfNode.execute('U', m, aData, m);
                 if (info != 0) {
-                    errorProfile.enter();
                     // TODO informative error message (aka GnuR)
                     throw error(RError.Message.LAPACK_ERROR, info, "dpotrf");
                 }
@@ -492,7 +490,6 @@ public class LaFunctions {
                 int[] rank = new int[1];
                 info = dpstrfNode.execute('U', n, aData, n, ipiv, rank, tol, work);
                 if (info != 0) {
-                    errorProfile.enter();
                     // TODO informative error message (aka GnuR)
                     throw error(RError.Message.LAPACK_ERROR, info, "dpotrf");
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
index dd8a4b0e48..b9d9c1f7c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.SUBSTITUTE;
 
@@ -81,9 +80,9 @@ public abstract class MatchArg extends RBuiltinNode {
         @Child private PMatch pmatch = PMatchNodeGen.create();
         @Child private Identical identical = IdenticalNodeGen.create();
 
-        @Child private CastNode argCast = newCastBuilder(NO_CALLER).asStringVector().buildCastNode();
-        @Child private CastNode choicesCast = newCastBuilder(NO_CALLER).allowMissing().mustBe(stringValue()).asStringVector().buildCastNode();
-        @Child private CastNode severalOKCast = newCastBuilder(NO_CALLER).mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()).buildCastNode();
+        @Child private CastNode argCast = newCastBuilder().asStringVector().buildCastNode();
+        @Child private CastNode choicesCast = newCastBuilder().allowMissing().mustBe(stringValue()).asStringVector().buildCastNode();
+        @Child private CastNode severalOKCast = newCastBuilder().mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean()).buildCastNode();
 
         public abstract Object execute(Object arg, Object choices, Object severalOK);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index 8986a6ec19..28fec92997 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -239,7 +239,7 @@ public abstract class PMinMax extends RBuiltinNode {
             naCheckX.enable(x);
             naCheckY.enable(y);
             if ((xLength > 1 && xLength < maxLength) || (yLength > 1 && yLength < maxLength)) {
-                RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED);
+                warning(RError.Message.ARG_RECYCYLED);
             }
             boolean profiledNaRm = naRmProfile.profile(naRm);
             double[] data = new double[maxLength];
@@ -422,7 +422,7 @@ public abstract class PMinMax extends RBuiltinNode {
             byte warningAdded = warning;
             RAbstractStringVector vec = (RAbstractStringVector) argValues[offset];
             if (vec.getLength() > 1 && vec.getLength() < maxLength && warningAdded == RRuntime.LOGICAL_FALSE) {
-                RError.warning(RError.SHOW_CALLER2, RError.Message.ARG_RECYCYLED);
+                warning(RError.Message.ARG_RECYCYLED);
                 warningAdded = RRuntime.LOGICAL_TRUE;
             }
             String result = vec.getDataAt(ind % vec.getLength());
@@ -449,7 +449,7 @@ public abstract class PMinMax extends RBuiltinNode {
             for (int i = offset + 1; i < argValues.length; i++) {
                 vec = (RAbstractStringVector) argValues[i];
                 if (vec.getLength() > 1 && vec.getLength() < maxLength && warningAdded == RRuntime.LOGICAL_FALSE) {
-                    RError.warning(this, RError.Message.ARG_RECYCYLED);
+                    warning(RError.Message.ARG_RECYCYLED);
                     warningAdded = RRuntime.LOGICAL_TRUE;
                 }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index 208ca6d69b..36bbd68139 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -26,7 +26,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringV
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import static com.oracle.truffle.r.runtime.RError.SHOW_CALLER;
 import static com.oracle.truffle.r.runtime.RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -223,7 +222,7 @@ public abstract class Paste extends RBuiltinNode {
         }
         if (castAsCharacterResultNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castAsCharacterResultNode = insert(newCastBuilder(SHOW_CALLER).mustBe(stringValue(), NON_STRING_ARG_TO_INTERNAL_PASTE).buildCastNode());
+            castAsCharacterResultNode = insert(newCastBuilder().mustBe(stringValue(), NON_STRING_ARG_TO_INTERNAL_PASTE).buildCastNode());
         }
     }
 
@@ -238,7 +237,7 @@ public abstract class Paste extends RBuiltinNode {
     private CastNode getAsCharacterNode() {
         if (asCharacterNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            asCharacterNode = insert(newCastBuilder(SHOW_CALLER).returnIf(nullValue(), emptyStringVector()).asStringVector().buildCastNode());
+            asCharacterNode = insert(newCastBuilder().returnIf(nullValue(), emptyStringVector()).asStringVector().buildCastNode());
         }
         return asCharacterNode;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index c9af0b9004..40d444302f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -63,7 +63,7 @@ public abstract class Quantifier extends RBuiltinNode {
         @Child private CastNode next;
 
         ProfileCastNode() {
-            this.next = newCastBuilder(null).allowNull().shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))),
+            this.next = newCastBuilder().allowNull().shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))),
                             RError.Message.COERCING_ARGUMENT, typeName(), "logical").asLogicalVector().buildCastNode();
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index db5dbce76a..8b92d9861f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -35,7 +35,6 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
@@ -76,7 +75,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 public abstract class Repeat extends RBuiltinNode {
 
     private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
-    private final BranchProfile errorBranch = BranchProfile.create();
     private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
     private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile();
     @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
@@ -100,16 +98,11 @@ public abstract class Repeat extends RBuiltinNode {
         return getNames.getNames(x) != null;
     }
 
-    private RError invalidTimes() {
-        throw error(RError.Message.INVALID_ARGUMENT, "times");
-    }
-
     @Specialization(guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
     protected RAbstractVector repNoEachNoNamesSimple(RAbstractDoubleVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
         int t = times.getDataAt(0);
         if (t < 0) {
-            errorBranch.enter();
-            throw invalidTimes();
+            throw error(RError.Message.INVALID_ARGUMENT, "times");
         }
         int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
         double[] data = new double[length];
@@ -120,8 +113,7 @@ public abstract class Repeat extends RBuiltinNode {
     @Specialization(guards = {"each > 1", "!hasNames(x)"})
     protected RAbstractVector repEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
         if (times.getLength() > 1) {
-            errorBranch.enter();
-            throw invalidTimes();
+            throw error(RError.Message.INVALID_ARGUMENT, "times");
         }
         RAbstractVector input = handleEach(x, each);
         if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
@@ -145,8 +137,7 @@ public abstract class Repeat extends RBuiltinNode {
                     @Cached("create()") InitAttributesNode initAttributes,
                     @Cached("createNames()") SetFixedAttributeNode putNames) {
         if (times.getLength() > 1) {
-            errorBranch.enter();
-            throw invalidTimes();
+            throw error(RError.Message.INVALID_ARGUMENT, "times");
         }
         RAbstractVector input = handleEach(x, each);
         RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
@@ -210,8 +201,7 @@ public abstract class Repeat extends RBuiltinNode {
             // only one times value is given
             final int howManyTimes = times.getDataAt(0);
             if (howManyTimes < 0) {
-                errorBranch.enter();
-                throw invalidTimes();
+                throw error(RError.Message.INVALID_ARGUMENT, "times");
             }
             if (replicateOnce.profile(howManyTimes == 1)) {
                 return (RVector<?>) (copyIfSameSize ? x.copy() : x);
@@ -221,16 +211,14 @@ public abstract class Repeat extends RBuiltinNode {
         } else {
             // times is a vector with several elements
             if (x.getLength() != times.getLength()) {
-                errorBranch.enter();
-                throw invalidTimes();
+                throw error(RError.Message.INVALID_ARGUMENT, "times");
             }
             // iterate once over the times vector to determine result vector size
             int resultLength = 0;
             for (int i = 0; i < times.getLength(); i++) {
                 int t = times.getDataAt(i);
                 if (t < 0) {
-                    errorBranch.enter();
-                    throw invalidTimes();
+                    throw error(RError.Message.INVALID_ARGUMENT, "times");
                 }
                 resultLength += t;
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 3fad457309..1bb90b5933 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -357,7 +357,7 @@ public final class SeqFunctions {
         }
 
         CastNode createLengthResultCast() {
-            return newCastBuilder(null).defaultError(Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).asIntegerVector(false, false, false).findFirst().mustBe(
+            return newCastBuilder().defaultError(Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED).asIntegerVector(false, false, false).findFirst().mustBe(
                             gte(0).and(notIntNA())).buildCastNode();
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
index ab924501ec..c6e061a795 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
@@ -67,8 +67,8 @@ public abstract class StandardGeneric extends RBuiltinNode {
     @Child private CollectGenericArgumentsNode collectArgumentsNode;
     @Child private DispatchGeneric dispatchGeneric = DispatchGenericNodeGen.create();
 
-    @Child private CastNode castIntScalar = newCastBuilder(null).asIntegerVector().findFirst(RRuntime.INT_NA).buildCastNode();
-    @Child private CastNode castStringScalar = newCastBuilder(null).asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
+    @Child private CastNode castIntScalar = newCastBuilder().asIntegerVector().findFirst(RRuntime.INT_NA).buildCastNode();
+    @Child private CastNode castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
 
     private final BranchProfile noGenFunFound = BranchProfile.create();
     private final ConditionProfile sameNamesProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index 24ed77fce4..9cbeac74df 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -174,7 +174,7 @@ public abstract class UpdateAttr extends RBuiltinNode {
         } else if (value instanceof String) {
             return RDataFactory.createStringVector((String) value);
         } else {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.SET_INVALID_CLASS_ATTR);
+            throw RError.error(RError.SHOW_CALLER, RError.Message.SET_INVALID_CLASS_ATTR);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 396a987bbe..2a9fe3ee00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -20,7 +20,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.library.grDevices.DevicesCCalls;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_Par;
@@ -224,8 +223,6 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".Call", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotCall extends CallRFFIAdapter {
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         static {
             Casts.noCasts(DotCall.class);
         }
@@ -705,7 +702,6 @@ public class CallAndExternalFunctions {
                         @Cached("create()") DLL.RFindSymbolNode findSymbolNode) {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName);
             }
             return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), args.getArguments());
@@ -725,8 +721,6 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".External", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotExternal extends CallRFFIAdapter {
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         static {
             Casts.noCasts(DotExternal.class);
         }
@@ -810,7 +804,6 @@ public class CallAndExternalFunctions {
                         @Cached("create()") DLL.RFindSymbolNode findSymbolNode) {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External", packageName);
             }
             Object list = encodeArgumentPairList(args, symbol);
@@ -833,8 +826,6 @@ public class CallAndExternalFunctions {
             Casts.noCasts(DotExternal2.class);
         }
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
@@ -892,7 +883,6 @@ public class CallAndExternalFunctions {
                         @Cached("create()") DLL.RFindSymbolNode findSymbolNode) {
             DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External2", packageName);
             }
             Object list = encodeArgumentPairList(args, symbol);
@@ -909,8 +899,6 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".External.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotExternalGraphics extends CallRFFIAdapter {
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         static {
             Casts.noCasts(DotExternalGraphics.class);
         }
@@ -956,7 +944,6 @@ public class CallAndExternalFunctions {
             DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.External, null, null);
             DLL.SymbolHandle func = findSymbolNode.execute(name, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, name);
             }
             Object list = encodeArgumentPairList(args, name);
@@ -972,8 +959,6 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".Call.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotCallGraphics extends CallRFFIAdapter {
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         static {
             Casts.noCasts(DotCallGraphics.class);
         }
@@ -1019,7 +1004,6 @@ public class CallAndExternalFunctions {
             DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Call, null, null);
             DLL.SymbolHandle func = findSymbolNode.execute(name, packageName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, name);
             }
             return callRFFINode.execute(new NativeCallInfo(name, func, rns.getDllInfo()), args.getArguments());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
index e0f6af2d15..1bdbad5326 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
@@ -20,7 +20,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -226,13 +225,11 @@ public class FortranAndCFunctions {
 
         @Specialization
         protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding,
-                        @Cached("create()") DLL.RFindSymbolNode findSymbolNode,
-                        @Cached("create()") BranchProfile errorProfile) {
-            String libName = checkPackageArg(rPackage, errorProfile);
+                        @Cached("create()") DLL.RFindSymbolNode findSymbolNode) {
+            String libName = checkPackageArg(rPackage);
             DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Fortran, null, null);
             DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol);
             }
             return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args);
@@ -258,30 +255,25 @@ public class FortranAndCFunctions {
             throw RInternalError.shouldNotReachHere();
         }
 
-        @SuppressWarnings("unused")
         @Specialization
-        protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding) {
+        protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding) {
             NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
             return dispatch(this, nativeCallInfo, naok, dup, args);
         }
 
-        @SuppressWarnings("unused")
         @Specialization
-        protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding,
-                        @Cached("create()") DLL.RFindSymbolNode findSymbolNode,
-                        @Cached("create()") BranchProfile errorProfile) {
+        protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding,
+                        @Cached("create()") DLL.RFindSymbolNode findSymbolNode) {
             String libName = null;
             if (!(rPackage instanceof RMissing)) {
                 libName = RRuntime.asString(rPackage);
                 if (libName == null) {
-                    errorProfile.enter();
                     throw error(RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
                 }
             }
             DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.C, null, null);
             DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
-                errorProfile.enter();
                 throw error(RError.Message.C_SYMBOL_NOT_IN_TABLE, symbol);
             }
             return dispatch(this, new NativeCallInfo(symbol.getDataAt(0), func, rns.getDllInfo()), naok, dup, args);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index 8eb161fc90..31f230f522 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodes;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -127,12 +126,11 @@ abstract class LookupAdapter extends RBuiltinNode {
         return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol);
     }
 
-    protected String checkPackageArg(Object rPackage, BranchProfile errorProfile) {
+    protected String checkPackageArg(Object rPackage) {
         String libName = null;
         if (!(rPackage instanceof RMissing)) {
             libName = RRuntime.asString(rPackage);
             if (libName == null) {
-                errorProfile.enter();
                 throw error(RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
             }
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
index 6863e8959d..0e432013b9 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
@@ -129,7 +129,7 @@ public class CastBuilderTest {
 
     @Before
     public void setUp() {
-        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class), RError.NO_CALLER);
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
         arg = cb.arg("x");
         castNode = null;
     }
@@ -931,7 +931,7 @@ public class CastBuilderTest {
         testPipeline(false);
     }
 
-    private static void testPipeline(boolean emptyPositiveSamplesAllowed) {
+    private static void testPipeline(@SuppressWarnings("unused") boolean emptyPositiveSamplesAllowed) {
         if (!TEST_SAMPLING) {
             return;
         }
@@ -946,6 +946,7 @@ public class CastBuilderTest {
         return castNode;
     }
 
+    @SuppressWarnings("unused")
     private void testPipeline(Samples<?> samples) {
         if (!TEST_SAMPLING) {
             return;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
index b3bb49ecc4..d45c80d6e1 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
@@ -103,7 +103,7 @@ public class ResultTypesAnalyserTest {
     @Before
     public void setUp() {
         MarkLookup.clear();
-        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class), RError.NO_CALLER);
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
         arg = cb.arg("x");
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
index 094fd88648..52e252a035 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
@@ -83,7 +83,7 @@ public class SampleCollectorTest {
 
     @Before
     public void setUp() {
-        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class), RError.NO_CALLER);
+        cb = new CastBuilder(DummyBuiltin.class.getAnnotation(RBuiltin.class));
         arg = cb.arg("x");
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index dd12608d0b..f5fbaed21e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -56,7 +56,6 @@ import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.test.TestBase;
 import com.oracle.truffle.r.nodes.unary.CastNode;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -135,7 +134,7 @@ public class TestCasts extends TestBase {
     }
 
     private static CastNode setupAndGetCast(Consumer<CastBuilder> setup) {
-        CastBuilder builder = new CastBuilder(1, RError.NO_CALLER);
+        CastBuilder builder = new CastBuilder(1);
         setup.accept(builder);
         return builder.getCasts()[0];
     }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
index 7c3135d422..a719c9d363 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
@@ -83,7 +83,7 @@ public class PipelineToCastNodeTests {
     }
 
     private static CastNode createPipeline(PipelineStep<?, ?> lastStep) {
-        PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x", null);
+        PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x");
         configBuilder.setValueForwarding(false);
         return PipelineToCastNode.convert(configBuilder.build(), lastStep, Optional.empty());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
index 3a66dc1427..62d420220e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
@@ -65,7 +65,7 @@ public abstract class RemoveAndAnswerNode extends RNode {
 
         private RemoveAndAnswerNode specialize(FrameSlot fs) {
             if (fs == null) {
-                RError.warning(RError.SHOW_CALLER, RError.Message.UNKNOWN_OBJECT, name);
+                warning(RError.Message.UNKNOWN_OBJECT, name);
             }
             return replace(RemoveAndAnswerResolvedNodeGen.create(fs));
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
index 0584507735..34d28947e3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.access.vector;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
@@ -124,6 +125,7 @@ final class PositionsCheckNode extends Node {
     }
 
     private RError dimensionsError() {
+        CompilerDirectives.transferToInterpreter();
         if (replace) {
             if (mode.isSubset()) {
                 if (getDimensions() == 2) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index 443c3db50c..96aa278a5a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -74,7 +74,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
     }
 
     @Override
-    protected RBaseNode getErrorContext() {
+    public RBaseNode getErrorContext() {
         return this;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index ef597fbc7c..21088940da 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -74,7 +74,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
     }
 
     @Override
-    protected RBaseNode getErrorContext() {
+    public RBaseNode getErrorContext() {
         return this;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index cfd2bdd2cc..9fc4ac7073 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -61,7 +61,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -89,12 +88,10 @@ public final class CastBuilder {
     private static final PipelineBuilder[] EMPTY_BUILDERS = new PipelineBuilder[0];
 
     private final RBuiltin builtin;
-    private final ErrorContext callObj;
     private final String[] argumentNames;
     private PipelineBuilder[] argumentBuilders;
 
-    public CastBuilder(RBuiltin builtin, ErrorContext callObj) {
-        this.callObj = callObj;
+    public CastBuilder(RBuiltin builtin) {
         // Note: if we have the builtin metadata, we pre-allocate the arrays, builtinNode != null is
         // used to determine, if the arrays are pre-allocated or if they can grow
         if (builtin == null) {
@@ -108,16 +105,14 @@ public final class CastBuilder {
         }
     }
 
-    public CastBuilder(int argumentsCount, ErrorContext callObj) {
-        this.callObj = callObj;
+    public CastBuilder(int argumentsCount) {
         assert argumentsCount >= 0 : "argumentsCount must be non-negative";
         builtin = null;
         argumentNames = null;
         argumentBuilders = new PipelineBuilder[argumentsCount];
     }
 
-    public CastBuilder(ErrorContext callObj) {
-        this.callObj = callObj;
+    public CastBuilder() {
         builtin = null;
         argumentNames = null;
         argumentBuilders = EMPTY_BUILDERS;
@@ -257,7 +252,7 @@ public final class CastBuilder {
             argumentBuilders = Arrays.copyOf(argumentBuilders, argumentIndex + 1);
         }
         if (argumentBuilders[argumentIndex] == null) {
-            argumentBuilders[argumentIndex] = new PipelineBuilder(argumentName, callObj);
+            argumentBuilders[argumentIndex] = new PipelineBuilder(argumentName);
         }
         return argumentBuilders[argumentIndex];
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
index 16694345d4..8d1683a4c1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
@@ -211,6 +212,11 @@ public abstract class InternalNode extends OperatorNode {
             }
         }
 
+        @Override
+        protected RBaseNode getErrorContext() {
+            return builtin.getErrorContext();
+        }
+
         protected abstract Object[] prepareArgs(VirtualFrame frame);
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
index 16fcfdc90b..f133a299b7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
@@ -29,8 +29,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
@@ -58,28 +56,18 @@ public interface NodeWithArgumentCasts {
         private final boolean declaresNoCasts;
 
         private Casts() {
-            casts = new CastBuilder(RError.NO_CALLER);
+            casts = new CastBuilder();
             this.declaresNoCasts = false;
         }
 
         public Casts(Class<? extends NodeWithArgumentCasts> cls) {
             castsMap.put(cls, this);
-            RBuiltin builtin = cls.getAnnotation(RBuiltin.class);
-            ErrorContext callObj = RError.contextForBuiltin(builtin);
-            casts = new CastBuilder(builtin, callObj);
-            this.declaresNoCasts = false;
-        }
-
-        public Casts(Class<? extends NodeWithArgumentCasts> cls, ErrorContext callObj) {
-            castsMap.put(cls, this);
-            RBuiltin annotation = cls.getAnnotation(RBuiltin.class);
-            casts = new CastBuilder(annotation, callObj);
+            casts = new CastBuilder(cls.getAnnotation(RBuiltin.class));
             this.declaresNoCasts = false;
         }
 
         private Casts(Class<? extends NodeWithArgumentCasts> cls, boolean declaresNoCasts) {
-            RBuiltin annotation = cls.getAnnotation(RBuiltin.class);
-            casts = new CastBuilder(annotation, null);
+            casts = new CastBuilder(cls.getAnnotation(RBuiltin.class));
             this.declaresNoCasts = declaresNoCasts;
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index bba7cfda29..f3c4cc292e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -104,7 +104,7 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
     }
 
     @Override
-    protected RBaseNode getErrorContext() {
+    public RBaseNode getErrorContext() {
         ErrorContext context = RError.contextForBuiltin(getRBuiltin());
         return context == null ? this : context;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
index a2d9d2158f..714387dcc5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
@@ -25,34 +25,20 @@ package com.oracle.truffle.r.nodes.builtin.casts;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Value type that holds data necessary for error/warning message from a cast pipeline.
  */
 public final class MessageData {
-    private final RBaseNode callObj;
     private final RError.Message message;
     private final Object[] messageArgs;
 
     public MessageData(Message message, Object... messageArgs) {
-        this.callObj = null;
         this.message = message;
         this.messageArgs = messageArgs;
         assert message != null;
     }
 
-    public MessageData(RBaseNode callObj, Message message, Object... messageArgs) {
-        this.callObj = callObj;
-        this.message = message;
-        this.messageArgs = messageArgs;
-        assert message != null;
-    }
-
-    public RBaseNode getCallObj() {
-        return callObj;
-    }
-
     public Message getMessage() {
         return message;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
index 39e2f8a790..607f55a258 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.builtin.casts;
 
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
 
 /**
  * Immutable class with configuration of the pipeline. Create using {@link PipelineConfigBuilder}.
@@ -34,17 +33,15 @@ import com.oracle.truffle.r.runtime.RError.ErrorContext;
  */
 public class PipelineConfig {
     private final String argumentName;
-    private final ErrorContext callObj;
     private final MessageData defaultError;
     private final MessageData defaultWarning;
     private boolean valueForwarding;
 
-    public PipelineConfig(String argumentName, ErrorContext callObj, MessageData defaultError, MessageData defaultWarning, boolean valueForwarding) {
+    public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, boolean valueForwarding) {
         this.defaultError = defaultError;
         this.defaultWarning = defaultWarning;
         this.valueForwarding = valueForwarding;
         this.argumentName = argumentName;
-        this.callObj = callObj;
     }
 
     /**
@@ -55,10 +52,6 @@ public class PipelineConfig {
         return new MessageData(RError.Message.INVALID_ARGUMENT, argumentName);
     }
 
-    public ErrorContext getCallObj() {
-        return callObj;
-    }
-
     public MessageData getDefaultError() {
         return defaultError;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 84f6a59c7a..5a8ee47be9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -87,7 +87,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -96,7 +95,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 /**
@@ -118,7 +116,7 @@ public final class PipelineToCastNode {
         boolean singleMapStep = firstStepIn.getNext() == null && firstStepIn instanceof MapIfStep;
         PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep<?, ?>) firstStepIn).withoutReturns() : firstStepIn;
 
-        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage(), config.getCallObj()));
+        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage()));
 
         if (!config.getValueForwarding()) {
             return originalPipelineFactory.get();
@@ -163,21 +161,11 @@ public final class PipelineToCastNode {
 
         private final MessageData defaultError;
         private final MessageData defaultWarning;
-        private final RBaseNode callObj;
 
-        CastNodeFactory(MessageData defaultError, MessageData defaultWarning, MessageData defaultMessage, ErrorContext callObj) {
+        CastNodeFactory(MessageData defaultError, MessageData defaultWarning, MessageData defaultMessage) {
             assert defaultMessage != null : "defaultMessage is null";
             this.defaultError = MessageData.getFirstNonNull(defaultError, defaultMessage);
             this.defaultWarning = MessageData.getFirstNonNull(defaultWarning, defaultMessage);
-            this.callObj = callObj;
-        }
-
-        private MessageData process(MessageData data) {
-            if (data == null || callObj == null) {
-                return data;
-            } else {
-                return new MessageData(callObj, data.getMessage(), data.getMessageArgs());
-            }
         }
 
         @Override
@@ -196,13 +184,13 @@ public final class PipelineToCastNode {
                     // Note: intentional direct use of defaultError
                     msg = defaultError != null ? defaultError : new MessageData(RError.Message.LENGTH_ZERO);
                 }
-                return FindFirstNodeGen.create(step.getElementClass(), process(msg), step.getDefaultValue());
+                return FindFirstNodeGen.create(step.getElementClass(), msg, step.getDefaultValue());
             } else {
                 MessageData warning = step.getError();
                 if (warning == null) {
                     return FindFirstNodeGen.create(step.getElementClass(), step.getDefaultValue());
                 } else {
-                    return FindFirstNodeGen.create(step.getElementClass(), process(warning), step.getDefaultValue());
+                    return FindFirstNodeGen.create(step.getElementClass(), warning, step.getDefaultValue());
                 }
             }
         }
@@ -212,7 +200,7 @@ public final class PipelineToCastNode {
             @SuppressWarnings("unchecked")
             ArgumentFilter<Object, Object> filter = (ArgumentFilter<Object, Object>) ArgumentFilterFactoryImpl.INSTANCE.createFilter(step.getFilter());
             MessageData msg = getDefaultIfNull(step.getMessage(), step.isWarning());
-            return FilterNode.create(filter, step.isWarning(), process(msg), boxPrimitives, step.getFilter().resultForNull() == ResultForArg.TRUE,
+            return FilterNode.create(filter, step.isWarning(), msg, boxPrimitives, step.getFilter().resultForNull() == ResultForArg.TRUE,
                             step.getFilter().resultForMissing() == ResultForArg.TRUE);
         }
 
@@ -220,13 +208,13 @@ public final class PipelineToCastNode {
         public CastNode visit(NotNAStep<?> step, CastNode previous) {
             if (step.getReplacement() == null) {
                 MessageData msg = getDefaultIfNull(step.getMessage(), false);
-                return NonNANodeGen.create(process(msg), step.getReplacement());
+                return NonNANodeGen.create(msg, step.getReplacement());
             } else {
                 MessageData msg = step.getMessage();
                 if (msg == null) {
                     return NonNANodeGen.create(null, step.getReplacement());
                 } else {
-                    return NonNANodeGen.create(process(msg), step.getReplacement());
+                    return NonNANodeGen.create(msg, step.getReplacement());
                 }
             }
         }
@@ -238,19 +226,19 @@ public final class PipelineToCastNode {
             RType type = step.getType();
             switch (type) {
                 case Integer:
-                    return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj)
-                                    : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
+                    return step.vectorCoercion ? CastIntegerNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
+                                    : CastIntegerBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Double:
-                    return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj)
-                                    : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
+                    return step.vectorCoercion ? CastDoubleNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
+                                    : CastDoubleBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Character:
                     return step.vectorCoercion ? CastStringNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
                                     : CastStringBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Logical:
-                    return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj)
-                                    : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
+                    return step.vectorCoercion ? CastLogicalNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes)
+                                    : CastLogicalBaseNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Complex:
-                    return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes, callObj);
+                    return CastComplexNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Raw:
                     return CastRawNodeGen.create(step.preserveNames, step.preserveDimensions, step.preserveAttributes);
                 case Any:
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java
index 24f7569eed..a6930c3a41 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CastNodeBuilder.java
@@ -22,14 +22,12 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
-
 /**
  * Can be used to construct a cast node outside of the FastR builtins framework. The cast node can
  * be then used to cast anything, not only arguments.
  */
 public final class CastNodeBuilder {
-    public static PreinitialPhaseBuilder newCastBuilder(ErrorContext callObj) {
-        return new PipelineBuilder("", callObj).fluent();
+    public static PreinitialPhaseBuilder newCastBuilder() {
+        return new PipelineBuilder("").fluent();
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index 19d2e3b397..ee2ffc3328 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -40,7 +40,6 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.nodes.unary.CastNode;
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RType;
 
@@ -55,8 +54,8 @@ public final class PipelineBuilder {
     private ChainBuilder<?> chainBuilder;
     private final AtomicReference<Optional<ForwardingAnalysisResult>> fwdAnalysisResult = new AtomicReference<>();
 
-    public PipelineBuilder(String argumentName, ErrorContext callObj) {
-        this.pcb = new PipelineConfigBuilder(argumentName, callObj);
+    public PipelineBuilder(String argumentName) {
+        this.pcb = new PipelineConfigBuilder(argumentName);
     }
 
     public CastNode buildNode() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
index b6efd44e4e..9fa3ffa310 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -40,17 +39,15 @@ public final class PipelineConfigBuilder {
     private MessageData defaultWarning;
 
     private boolean valueForwarding = true;
-    private final ErrorContext callObj;
 
-    public PipelineConfigBuilder(String argumentName, ErrorContext callObj) {
+    public PipelineConfigBuilder(String argumentName) {
         this.argumentName = argumentName;
-        this.callObj = callObj;
         defaultError = new MessageData(RError.Message.INVALID_ARGUMENT, argumentName);
         defaultWarning = defaultError;
     }
 
     public PipelineConfig build() {
-        return new PipelineConfig(argumentName, callObj, defaultError, defaultWarning, valueForwarding);
+        return new PipelineConfig(argumentName, defaultError, defaultWarning, valueForwarding);
     }
 
     void setDefaultError(MessageData defaultError) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
index ae7d5fc902..d735d29331 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
@@ -231,6 +231,11 @@ public abstract class CallMatcherNode extends RBaseNode {
             }
         }
 
+        @Override
+        protected RBaseNode getErrorContext() {
+            return builtin == null ? super.getErrorContext() : builtin.getErrorContext();
+        }
+
         @Override
         public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, String functionName, DispatchArgs dispatchArgs) {
             if (suppliedSignature == cachedSuppliedSignature && function == cachedFunction && checkLastArgSignature(cachedSuppliedSignature, suppliedArguments)) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index a3c624bcac..00da0b6a7e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -762,6 +762,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
             wrapSeen = new boolean[formals.getLength()];
         }
 
+        @Override
+        protected RBaseNode getErrorContext() {
+            return builtin.getErrorContext();
+        }
+
         @ExplodeLoop
         public Object[] castArguments(VirtualFrame frame, Object[] args) {
             int argCount = formals.getLength();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
index 8b67499f95..abc8291e09 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
@@ -40,7 +40,6 @@ import com.oracle.truffle.r.nodes.function.RMissingHelper;
 import com.oracle.truffle.r.nodes.function.signature.MissingNodeFactory.MissingCheckCacheNodeGen;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
index f32c80724f..b4bb62f49e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
@@ -13,8 +13,6 @@
 package com.oracle.truffle.r.nodes.objects;
 
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import static com.oracle.truffle.r.runtime.RError.NO_CALLER;
-
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.access.AccessSlotNode;
@@ -40,8 +38,8 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 {
     @Child private GetFixedAttributeNode pckgAttrAccess = GetFixedAttributeNode.create(RRuntime.PCKG_ATTR_KEY);
     @Child private SetClassAttributeNode setClassAttrNode;
 
-    @Child private CastNode castStringScalar = newCastBuilder(NO_CALLER).asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
-    @Child private CastNode castLogicalScalar = newCastBuilder(NO_CALLER).asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode();
+    @Child private CastNode castStringScalar = newCastBuilder().asStringVector().findFirst(RRuntime.STRING_NA).buildCastNode();
+    @Child private CastNode castLogicalScalar = newCastBuilder().asLogicalVector().findFirst(RRuntime.LOGICAL_NA).buildCastNode();
 
     static {
         Casts casts = new Casts(NewObject.class);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
index f136727e66..d94c36c1dc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastBaseNode.java
@@ -45,7 +45,6 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class CastBaseNode extends CastNode {
 
@@ -62,8 +61,6 @@ public abstract class CastBaseNode extends CastNode {
     private final boolean preserveDimensions;
     private final boolean preserveAttributes;
 
-    protected final RBaseNode messageCallObj;
-
     /**
      * GnuR provides several, sometimes incompatible, ways to coerce given value to given type. This
      * flag tells the cast node that it should behave in a way compatible with functions exposed by
@@ -71,19 +68,11 @@ public abstract class CastBaseNode extends CastNode {
      */
     private final boolean forRFFI;
 
-    protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false, messageCallObj);
-    }
-
     protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false, null);
+        this(preserveNames, preserveDimensions, preserveAttributes, false);
     }
 
     protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
-        this(preserveNames, preserveDimensions, preserveAttributes, forRFFI, null);
-    }
-
-    protected CastBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI, RBaseNode messageCallObj) {
         this.preserveNames = preserveNames;
         this.preserveDimensions = preserveDimensions;
         this.preserveAttributes = preserveAttributes;
@@ -91,7 +80,6 @@ public abstract class CastBaseNode extends CastNode {
         if (preserveDimensions) {
             getDimNamesNode = GetDimNamesAttributeNode.create();
         }
-        this.messageCallObj = messageCallObj == null ? this : messageCallObj;
     }
 
     public final boolean preserveNames() {
@@ -110,7 +98,7 @@ public abstract class CastBaseNode extends CastNode {
 
     protected RError throwCannotCoerceListError(String type) {
         listCoercionErrorBranch.enter();
-        throw RError.error(messageCallObj, RError.Message.LIST_COERCION, type);
+        throw error(RError.Message.LIST_COERCION, type);
     }
 
     protected int[] getPreservedDimensions(RAbstractContainer operand) {
@@ -155,11 +143,11 @@ public abstract class CastBaseNode extends CastNode {
 
     protected Object doOtherDefault(Object mappedValue) {
         if (mappedValue instanceof REnvironment) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.ENVIRONMENTS_COERCE);
+            throw error(RError.Message.ENVIRONMENTS_COERCE);
         } else if (mappedValue instanceof RTypedValue) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName());
+            throw error(RError.Message.CANNOT_COERCE, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName());
         } else if (mappedValue instanceof TruffleObject) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName());
+            throw error(RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName());
         } else {
             throw RInternalError.shouldNotReachHere("unexpected value of type " + (mappedValue == null ? "null" : mappedValue.getClass()));
         }
@@ -167,9 +155,9 @@ public abstract class CastBaseNode extends CastNode {
 
     protected Object doOtherRFFI(Object mappedValue) {
         if (mappedValue instanceof RTypedValue) {
-            RError.warning(RError.SHOW_CALLER2, Message.CANNOT_COERCE_RFFI, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName());
+            warning(Message.CANNOT_COERCE_RFFI, ((RTypedValue) mappedValue).getRType().getName(), getTargetType().getName());
         } else if (mappedValue instanceof TruffleObject) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName());
+            throw error(RError.Message.CANNOT_COERCE, "truffleobject", getTargetType().getName());
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
index fcd810bb29..8815142190 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastComplexNode.java
@@ -46,7 +46,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
@@ -64,12 +63,8 @@ public abstract class CastComplexNode extends CastBaseNode {
 
     public abstract Object executeComplex(Object o);
 
-    protected CastComplexNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallerObj);
-    }
-
     protected CastComplexNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     protected CastComplexNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
@@ -138,8 +133,7 @@ public abstract class CastComplexNode extends CastBaseNode {
         }
         RComplex result = RRuntime.string2complexNoCheck(operand);
         if (RRuntime.isNA(result) && !operand.equals(RRuntime.STRING_NaN)) {
-            warningBranch.enter();
-            RError.warning(this, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         return result;
     }
@@ -206,7 +200,7 @@ public abstract class CastComplexNode extends CastBaseNode {
             ddata[index + 1] = complexValue.getImaginaryPart();
         }
         if (warning) {
-            RError.warning(this, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         RComplexVector ret = RDataFactory.createComplexVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
index 6e1b66b740..9abeb67a8d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleBaseNode.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -33,7 +32,6 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
@@ -41,14 +39,9 @@ public abstract class CastDoubleBaseNode extends CastBaseNode {
 
     protected final NACheck naCheck = NACheck.create();
     protected final NAProfile naProfile = NAProfile.create();
-    protected final BranchProfile warningBranch = BranchProfile.create();
-
-    protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj);
-    }
 
     protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     protected CastDoubleBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
@@ -94,8 +87,7 @@ public abstract class CastDoubleBaseNode extends CastBaseNode {
         naCheck.enable(operand);
         double result = naCheck.convertComplexToDouble(operand, false);
         if (operand.getImaginaryPart() != 0.0) {
-            warningBranch.enter();
-            RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+            warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
         }
         return result;
     }
@@ -114,8 +106,7 @@ public abstract class CastDoubleBaseNode extends CastBaseNode {
         }
         double result = RRuntime.string2doubleNoCheck(operand);
         if (RRuntime.isNA(result)) {
-            warningBranch.enter();
-            RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
index d937c07eef..381bd14e90 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
@@ -27,6 +27,7 @@ import java.util.function.IntToDoubleFunction;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -43,20 +44,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class CastDoubleNode extends CastDoubleBaseNode {
 
-    protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
-    }
-
     protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
         super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
     }
 
-    protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallerObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallerObj);
+    protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     @Child private CastDoubleNode recursiveCastDouble;
@@ -102,7 +98,8 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
 
     @Specialization
     protected RDoubleVector doStringVector(RStringVector operand,
-                    @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile) {
+                    @Cached("createBinaryProfile()") ConditionProfile emptyStringProfile,
+                    @Cached("create()") BranchProfile warningBranch) {
         naCheck.enable(operand);
         double[] ddata = new double[operand.getLength()];
         boolean seenNA = false;
@@ -126,7 +123,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
             ddata[i] = doubleValue;
         }
         if (warning) {
-            RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         RDoubleVector ret = RDataFactory.createDoubleVector(ddata, !seenNA, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
@@ -149,8 +146,7 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
             }
         }
         if (warning) {
-            warningBranch.enter();
-            RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+            warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
         }
         return vectorCopy(operand, ddata, naCheck.neverSeenNA());
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java
index 3c48230dc7..c426860c0f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastExpressionNode.java
@@ -79,7 +79,7 @@ public abstract class CastExpressionNode extends CastBaseNode {
 
     @Specialization
     protected RExpression doFunction(RFunction value) {
-        throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE, value.isBuiltin() ? "builtin" : "closure", "expression");
+        throw error(RError.Message.CANNOT_COERCE, value.isBuiltin() ? "builtin" : "closure", "expression");
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
index 5a26f6d198..dc79c02b5f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerBaseNode.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -34,26 +33,20 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public abstract class CastIntegerBaseNode extends CastBaseNode {
 
     protected final NACheck naCheck = NACheck.create();
-    protected final BranchProfile warningBranch = BranchProfile.create();
 
     @Child private CastIntegerNode recursiveCastInteger;
 
-    protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
-    }
-
     protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
         super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
     }
 
-    protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj);
+    protected CastIntegerBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     @Override
@@ -64,7 +57,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode {
     protected Object castIntegerRecursive(Object o) {
         if (recursiveCastInteger == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes(), messageCallObj));
+            recursiveCastInteger = insert(CastIntegerNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
         }
         return recursiveCastInteger.executeInt(o);
     }
@@ -95,8 +88,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode {
         naCheck.enable(operand);
         int result = naCheck.convertComplexToInt(operand, false);
         if (operand.getImaginaryPart() != 0.0) {
-            warningBranch.enter();
-            RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+            warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
         }
         return result;
     }
@@ -110,8 +102,7 @@ public abstract class CastIntegerBaseNode extends CastBaseNode {
         }
         int result = RRuntime.string2intNoCheck(operand);
         if (RRuntime.isNA(result)) {
-            warningBranch.enter();
-            RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
index b0310c602b..7d46d80f99 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -42,23 +43,20 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
 public abstract class CastIntegerNode extends CastIntegerBaseNode {
 
     private final NAProfile naProfile = NAProfile.create();
 
-    protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
-    }
+    private final BranchProfile warningBranch = BranchProfile.create();
 
     protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
         super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
     }
 
-    protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj);
+    protected CastIntegerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     public abstract Object executeInt(int o);
@@ -126,8 +124,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
             }
         }
         if (warning) {
-            warningBranch.enter();
-            RError.warning(messageCallObj, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+            warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
         }
         return vectorCopy(operand, idata, naCheck.neverSeenNA());
     }
@@ -158,7 +155,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
             idata[i] = intValue;
         }
         if (warning) {
-            RError.warning(messageCallObj, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         return vectorCopy(operand, idata, !seenNA);
     }
@@ -230,7 +227,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     }
 
     public static CastIntegerNode create() {
-        return CastIntegerNodeGen.create(true, true, true, null);
+        return CastIntegerNodeGen.create(true, true, true);
     }
 
     public static CastIntegerNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
@@ -238,10 +235,6 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     }
 
     public static CastIntegerNode createNonPreserving() {
-        return CastIntegerNodeGen.create(false, false, false, null);
-    }
-
-    public static CastIntegerNode createPreserveNames() {
-        return CastIntegerNodeGen.create(false, false, false, null);
+        return CastIntegerNodeGen.create(false, false, false);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java
index 94f484b2fc..a01f4bdf4d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalBaseNode.java
@@ -27,23 +27,18 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public abstract class CastLogicalBaseNode extends CastBaseNode {
 
     protected final NACheck naCheck = NACheck.create();
 
-    protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
-    }
-
     protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
         super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
     }
 
-    protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj);
+    protected CastLogicalBaseNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
index 6f15ddd3fc..745cb3980a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
 public abstract class CastLogicalNode extends CastLogicalBaseNode {
@@ -51,12 +50,8 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
     @Child private CastLogicalNode recursiveCastLogical;
     @Child private InheritsCheckNode inheritsFactorCheck;
 
-    protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, RBaseNode messageCallObj) {
-        super(preserveNames, preserveDimensions, preserveAttributes, messageCallObj);
-    }
-
     protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
+        super(preserveNames, preserveDimensions, preserveAttributes);
     }
 
     protected CastLogicalNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
index 3bcca2434f..c252dcce4c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
@@ -25,10 +25,9 @@ package com.oracle.truffle.r.nodes.unary;
 import java.util.Arrays;
 import java.util.function.Function;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Cast nodes behave like unary nodes, but in many cases it is useful to have a specific type for
@@ -69,28 +68,26 @@ public abstract class CastNode extends UnaryNode {
         return newMsgArgs;
     }
 
-    private RBaseNode getCallObj(MessageData message) {
-        return message.getCallObj() == null ? this : message.getCallObj();
-    }
-
-    @TruffleBoundary
     protected RuntimeException handleArgumentError(Object arg, MessageData message) {
+        CompilerDirectives.transferToInterpreter();
+        Object[] args = substituteArgs(arg, message);
         if (isTesting) {
-            throw new IllegalArgumentException(String.format(message.getMessage().message, substituteArgs(arg, message)));
+            throw new IllegalArgumentException(String.format(message.getMessage().message, args));
         } else {
-            throw RError.error(getCallObj(message), message.getMessage(), substituteArgs(arg, message));
+            throw RError.error(getErrorContext(), message.getMessage(), args);
         }
     }
 
-    @TruffleBoundary
     protected void handleArgumentWarning(Object arg, MessageData message) {
+        CompilerDirectives.transferToInterpreter();
         if (message == null) {
             return;
         }
+        Object[] args = substituteArgs(arg, message);
         if (isTesting) {
-            lastWarning = String.format(message.getMessage().message, substituteArgs(arg, message));
+            lastWarning = String.format(message.getMessage().message, args);
         } else {
-            RError.warning(getCallObj(message), message.getMessage(), substituteArgs(arg, message));
+            RError.warning(getErrorContext(), message.getMessage(), args);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
index a9d7b0ad36..c66438279a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
@@ -94,8 +94,7 @@ public abstract class CastRawNode extends CastBaseNode {
 
     private RRaw checkOutOfRange(int operand, int intResult) {
         if (intResult != operand) {
-            warningBranch.enter();
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
             return RDataFactory.createRaw((byte) 0);
         }
         return RDataFactory.createRaw((byte) intResult);
@@ -117,8 +116,7 @@ public abstract class CastRawNode extends CastBaseNode {
     protected RRaw doComplex(RComplex operand) {
         int intResult = RRuntime.complex2rawIntValue(operand);
         if (operand.getImaginaryPart() != 0) {
-            warningBranch.enter();
-            RError.warning(this, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+            warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
         }
         return checkOutOfRange((int) operand.getRealPart(), intResult);
     }
@@ -145,14 +143,12 @@ public abstract class CastRawNode extends CastBaseNode {
         } else {
             intValue = RRuntime.string2intNoCheck(operand);
             if (RRuntime.isNA(intValue)) {
-                warningBranch.enter();
-                RError.warning(this, RError.Message.NA_INTRODUCED_COERCION);
+                warning(RError.Message.NA_INTRODUCED_COERCION);
             }
         }
         int intRawValue = RRuntime.int2rawIntValue(intValue);
         if (intRawValue != intValue) {
-            warningBranch.enter();
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
             return RRaw.valueOf((byte) 0);
         }
         return RRaw.valueOf((byte) intRawValue);
@@ -183,7 +179,7 @@ public abstract class CastRawNode extends CastBaseNode {
             bdata[i] = (byte) intRawValue;
         }
         if (warning) {
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
         }
         return vectorCopy(operand, bdata);
     }
@@ -203,7 +199,7 @@ public abstract class CastRawNode extends CastBaseNode {
             bdata[i] = (byte) intRawValue;
         }
         if (warning) {
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
         }
         return vectorCopy(operand, bdata);
     }
@@ -240,10 +236,10 @@ public abstract class CastRawNode extends CastBaseNode {
             bdata[i] = (byte) intValue;
         }
         if (naCoercionWarning) {
-            RError.warning(this, RError.Message.NA_INTRODUCED_COERCION);
+            warning(RError.Message.NA_INTRODUCED_COERCION);
         }
         if (outOfRangeWarning) {
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
         }
         return vectorCopy(operand, bdata);
     }
@@ -268,10 +264,10 @@ public abstract class CastRawNode extends CastBaseNode {
             bdata[i] = (byte) intRawValue;
         }
         if (imaginaryDiscardedWarning) {
-            RError.warning(this, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+            warning(RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
         }
         if (outOfRangeWarning) {
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
         }
         return vectorCopy(operand, bdata);
     }
@@ -292,7 +288,7 @@ public abstract class CastRawNode extends CastBaseNode {
             bdata[i] = (byte) intRawValue;
         }
         if (warning) {
-            RError.warning(this, RError.Message.OUT_OF_RANGE);
+            warning(RError.Message.OUT_OF_RANGE);
         }
         return vectorCopy(operand, bdata);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java
index 31b0fea74e..4aac866720 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java
@@ -62,7 +62,7 @@ public abstract class CastSymbolNode extends CastBaseNode {
 
     @Specialization
     protected RSymbol doNull(@SuppressWarnings("unused") RNull value) {
-        throw RError.error(this, RError.Message.INVALID_TYPE_LENGTH, "symbol", 0);
+        throw error(RError.Message.INVALID_TYPE_LENGTH, "symbol", 0);
     }
 
     @Specialization
@@ -117,9 +117,9 @@ public abstract class CastSymbolNode extends CastBaseNode {
     @TruffleBoundary
     protected RSymbol doEmptyVector(RAbstractVector vector) {
         if (vector instanceof RList) {
-            throw RError.error(this, RError.Message.INVALID_TYPE_LENGTH, "symbol", 0);
+            throw error(RError.Message.INVALID_TYPE_LENGTH, "symbol", 0);
         } else {
-            throw RError.error(this, Message.INVALID_DATA_OF_TYPE_TOO_SHORT, vector.getRType().getName(), 0);
+            throw error(Message.INVALID_DATA_OF_TYPE_TOO_SHORT, vector.getRType().getName(), 0);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java
index a1672bbea1..e0bde5a104 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/FirstStringNode.java
@@ -24,8 +24,6 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -40,9 +38,6 @@ public abstract class FirstStringNode extends CastNode {
         this.argumentName = argumentName;
     }
 
-    private final ConditionProfile lengthOneProfile = ConditionProfile.createBinaryProfile();
-    private final BranchProfile errorProfile = BranchProfile.create();
-
     public final String executeString(Object argument) {
         return (String) execute(argument);
     }
@@ -54,16 +49,15 @@ public abstract class FirstStringNode extends CastNode {
 
     @Specialization(replaces = "firstScalar")
     protected String firstVector(RAbstractStringVector argument) {
-        if (!lengthOneProfile.profile(argument.getLength() == 1)) {
-            errorProfile.enter();
-            throw RError.error(RError.SHOW_CALLER, emptyError, argumentName);
+        if (argument.getLength() != 1) {
+            throw error(emptyError, argumentName);
         }
         return argument.getDataAt(0);
     }
 
     @Fallback
     protected String firstVectorFallback(@SuppressWarnings("unused") Object argument) {
-        throw RError.error(RError.SHOW_CALLER, emptyError, argumentName);
+        throw error(emptyError, argumentName);
     }
 
     public static FirstStringNode createWithError(RError.Message emptyError, String argumentName) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index e6148d53b9..ad5120700f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.runtime;
 
 import java.io.IOException;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
@@ -231,8 +232,8 @@ public final class RError extends RuntimeException {
      * A temporary error that indicates an unimplemented feature where terminating the VM using
      * {@link Utils#rSuicide(String)} would be inappropriate.
      */
-    @TruffleBoundary
     public static RError nyi(RBaseNode node, String msg) {
+        CompilerDirectives.transferToInterpreter();
         throw error(node, RError.Message.NYI, msg);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java
index 815481e6f4..736cf4b3bd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RandomFunctions.java
@@ -22,9 +22,9 @@
  */
 package com.oracle.truffle.r.runtime.nmath;
 
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.nmath.distr.SExp;
 import com.oracle.truffle.r.runtime.nmath.distr.SNorm;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.rng.RRNG;
 import com.oracle.truffle.r.runtime.rng.RRNG.NormKind;
 import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator;
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator;
  * implement common code for the vectorized versions.
  */
 public class RandomFunctions {
-    public abstract static class RandFunction3_Double extends Node {
+    public abstract static class RandFunction3_Double extends RBaseNode {
         public abstract double execute(double a, double b, double c, RandomNumberProvider rand);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java
index 2b501eb81d..3521424f93 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java
@@ -235,7 +235,7 @@ public final class RHyper extends RandFunction3_Double {
                 v = rand.unifRand();
                 nUv++;
                 if (nUv >= 10000) {
-                    RError.warning(RError.SHOW_CALLER, Message.GENERIC, String.format("rhyper() branch III: giving up after %d rejections", nUv));
+                    warning(Message.GENERIC, String.format("rhyper() branch III: giving up after %d rejections", nUv));
                     return RMathError.defaultError();
                 }
 
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 735f194785..40d49f6331 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
@@ -383,7 +383,7 @@ Error in y@foo <- 42 : object 'y' not found
 Error in standardGeneric("") :
   argument to 'standardGeneric' must be a non-empty character string
 
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext#
 #{ standardGeneric("foo", 42) }
 Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
 
@@ -397,7 +397,7 @@ Error in standardGeneric(42) :
 Error in standardGeneric(character()) :
   argument to 'standardGeneric' must be a non-empty character string
 
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext#
 #{ x<-42; class(x)<-character(); standardGeneric("foo", x) }
 Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
 
@@ -1460,11 +1460,11 @@ Error: invalid 'category' argument
 In addition: Warning message:
 NAs introduced by coercion
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
 #.Internal(Sys.setlocale(4, 42))
 Error: invalid 'locale' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
 #.Internal(Sys.setlocale(4, c('more', 'elements')))
 Error: invalid 'locale' argument
 
@@ -2146,7 +2146,7 @@ In all(1) : coercing argument of type 'double' to logical
 #{ all(TRUE, TRUE, TRUE) }
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testAll#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testAll#
 #{ all(TRUE,c(TRUE,TRUE),1) }
 [1] TRUE
 Warning message:
@@ -2206,7 +2206,7 @@ Warning messages:
 #argv <- list(structure(c(FALSE, FALSE), .Names = c('x', 'value')));all(argv[[1]]);
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testall3#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_all.testall3#
 #argv <- list(c(1, 1, 3, 1, 1, 3, 3, 3, 3), FALSE, NULL);all(argv[[1]],argv[[2]],argv[[3]]);
 [1] FALSE
 Warning message:
@@ -2567,7 +2567,7 @@ In any(argv[[1]]) : coercing argument of type 'double' to logical
 #{ anyDuplicated(c(1,2,1)) }
 [1] 3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated#
 #{ anyDuplicated(c(1,2,3,2), incomparables = c(2+6i)) }
 [1] 0
 Warning message:
@@ -2578,7 +2578,7 @@ In anyDuplicated.default(c(1, 2, 3, 2), incomparables = c(2 + (0+6i))) :
 #{ anyDuplicated(c(1,2,3,4)) }
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testAnyDuplicated#
 #{ anyDuplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") }
 [1] 3
 Warning message:
@@ -2824,7 +2824,7 @@ Error in aperm.default(array(1, c(3, 3, 3)), c(1, 2)) :
 Error in aperm.default(array(1, c(3, 3, 3)), c(1, 2, 0)) :
   value out of range in 'perm'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testAperm#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testAperm#
 #{ aperm(array(1:27,c(3,3,3)), c(1+1i,3+3i,2+2i))[1,2,3] == array(1:27,c(3,3,3))[1,3,2]; }
 [1] TRUE
 Warning message:
@@ -4153,7 +4153,7 @@ Error in array(1:4, 1:2, 4) : 'dimnames' must be a list
 #{ array(1:4, NULL) }
 Error in array(1:4, NULL) : 'dims' cannot be of length 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testArray#
 #{ array(1:4, c(1+2i, 2+2i)) }
      [,1] [,2]
 [1,]    1    2
@@ -6259,7 +6259,7 @@ a + foo(c) * b
 #foo <- function(x) x*2; f <- function() a+foo(c)*b; as.function(c(alist(a=1+14, b=foo(x),c=), body(f)))(c=3,b=1)
 [1] 21
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asfunction.testasfunction#Output.IgnoreErrorContext#
 #{ .Internal(as.function.default(alist(a+b), "foo")) }
 Error in as.function.default(alist(a + b), "foo") : invalid environment
 
@@ -7176,7 +7176,7 @@ x ~ z
 #{ as.vector("foo") }
 [1] "foo"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext#
 #{ as.vector("foo", "bar") }
 Error in as.vector(x, mode) : invalid 'mode' argument
 
@@ -7184,13 +7184,13 @@ Error in as.vector(x, mode) : invalid 'mode' argument
 #{ as.vector("foo", "character") }
 [1] "foo"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #{ as.vector("foo", "double") }
 [1] NA
 Warning message:
 In as.vector("foo", "double") : NAs introduced by coercion
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #{ as.vector("foo", "integer") }
 [1] NA
 Warning message:
@@ -7206,13 +7206,13 @@ In as.vector("foo", "integer") : NAs introduced by coercion
 #{ as.vector("foo", "logical") }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #{ as.vector("foo", "numeric") }
 [1] NA
 Warning message:
 In as.vector("foo", "numeric") : NAs introduced by coercion
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #{ as.vector("foo", "raw") }
 [1] 00
 Warning messages:
@@ -7220,15 +7220,15 @@ Warning messages:
 2: In as.vector("foo", "raw") :
   out-of-range values treated as 0 in coercion to raw
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext#
 #{ as.vector(42, NULL) }
 Error in as.vector(x, mode) : invalid 'mode' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext#
 #{ as.vector(42, c("character", "character")) }
 Error in as.vector(x, mode) : invalid 'mode' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.ImprovedErrorContext#
 #{ as.vector(42, character())  }
 Error in as.vector(x, mode) : invalid 'mode' argument
 
@@ -7240,7 +7240,7 @@ NULL
 #{ as.vector(NULL, "list") }
 list()
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #{ as.vector(c("foo", "bar"), "raw") }
 [1] 00 00
 Warning messages:
@@ -7987,15 +7987,15 @@ Error in atan2() : argument "y" is missing, with no default
 #{ atan2(0.7) }
 Error in atan2(0.7) : argument "x" is missing, with no default
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#Output.ImprovedErrorContext#
 #{ atan2(2, as.symbol('45')) }
 Error in atan2(y, x) : non-numeric argument to mathematical function
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#Output.ImprovedErrorContext#
 #{ atan2(2, new.env()) }
 Error in atan2(y, x) : non-numeric argument to mathematical function
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testTrigExp#Output.ImprovedErrorContext#
 #{ atan2(NULL, 1) }
 Error in atan2(y, x) : non-numeric argument to mathematical function
 
@@ -8085,7 +8085,7 @@ Error: object 'colNameX' not found
 #attach('string')
 Error in attach("string") : file 'string' not found
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_attach.testArguments#
 #attach(list(), name=42)
 Error in attach(list(), name = 42) : invalid 'name' argument
 
@@ -8411,11 +8411,11 @@ NULL
 #argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), terms = quote(Fr ~ (Hair + Eye + Sex)^2), row.names = c(NA, 32L), class = 'data.frame'), 'terms');attr(argv[[1]],argv[[2]]);
 Fr ~ (Hair + Eye + Sex)^2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts#
 #x<-42; attr(x, 42) <- NULL
 Error in attr(x, 42) <- NULL : 'name' must be non-null character string
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testArgsCasts#
 #x<-42; attr(x, NULL) <- NULL
 Error in attr(x, NULL) <- NULL : 'name' must be non-null character string
 
@@ -9627,7 +9627,7 @@ Error in bitwAnd(c(1, 2, 3, 4), c(TRUE)) :
 #argv <- list(structure(integer(0), class = 'hexmode'), structure(integer(0), class = 'hexmode')); .Internal(bitwiseAnd(argv[[1]], argv[[2]]))
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseNot.testBitwiseFunctions#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseNot.testBitwiseFunctions#
 #{ bitwNot(TRUE) }
 Error in bitwNot(TRUE) : unimplemented type 'logical' in 'bitNot'
 
@@ -9697,7 +9697,7 @@ In bitwShiftL(c(1, 2, 3, 4), c("a")) : NAs introduced by coercion
 Error in bitwShiftL(c(3 + (0+3i)), c(3, 2, 4)) :
   unimplemented type 'complex' in 'bitShiftL'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
 #{ bitwShiftL(c(3,2,4), c(3+3i)) }
 [1] 24 16 32
 Warning message:
@@ -9726,7 +9726,7 @@ In bitwShiftR(c(1, 2, 3, 4), c("Hello")) : NAs introduced by coercion
 #{ bitwShiftR(c(25,57,66), c(10,20,30,40,50,60)) }
 [1]  0  0  0 NA NA NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
 #{ bitwShiftR(c(3,2,4), c(3+3i)) }
 [1] 0 0 0
 Warning message:
@@ -11664,17 +11664,17 @@ hello
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#
 #cat(list(), expression(), sep='this-should-be-ok')
 this-should-be-ok
-##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#Output.ImprovedErrorContext#
 #cat(list(1,2,3))
 Error in cat(list(...), file, sep, fill, labels, append) :
   argument 1 (type 'list') cannot be handled by 'cat'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#Output.ImprovedErrorContext#
 #cat(parse(text='42'))
 Error in cat(list(...), file, sep, fill, labels, append) :
   argument 1 (type 'expression') cannot be handled by 'cat'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cat.testCatUnsupportedArgs#Output.ImprovedErrorContext#
 #cat(quote(3+3))
 Error in cat(list(...), file, sep, fill, labels, append) :
   argument 1 (type 'language') cannot be handled by 'cat'
@@ -14390,7 +14390,7 @@ attr(,"foo")
 Error in `[[<-.data.frame`(`*tmp*`, i, value = numeric(0)) :
   replacement has 0 rows, data has 5
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr11#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr11#
 #argv <- list(structure(list(srcfile = c(NA, '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats', '/home/lzhao/hg/r-instrumented/library/stats/R/stats'), frow = c(NA, 2228L, 2369L, 2379L), lrow = c(NA, 2228L, 2369L, 2380L)), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame'), structure(list(srcfile = NULL, frow = NULL, lrow = NULL), .Names = c('srcfile', 'frow', 'lrow'), row.names = c(NA, 4L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))
   srcfile frow lrow
 1    NULL NULL NULL
@@ -14401,7 +14401,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr12#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr12#
 #argv <- list(structure(list(y = c(73, 73, 70, 74, 75, 115, 105, 107, 124, 107, 116, 125, 102, 144, 178, 149, 177, 124, 157, 128, 169, 165, 186, 152, 181, 139, 173, 151, 138, 181, 152, 188, 173, 196, 180, 171, 188, 174, 198, 172, 176, 162, 188, 182, 182, 141, 191, 190, 159, 170, 163, 197), x = c(1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 11, 12)), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x)), structure(list(y = NULL, x = NULL), .Names = c('y', 'x'), class = 'data.frame', row.names = c(NA, 52L), terms = quote(~y + x))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
       y    x
 1  NULL NULL
@@ -14482,7 +14482,7 @@ attr(,"class")
 attr(,"class")attr(,"package")
 [1] ".GlobalEnv"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr14#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr14#
 #argv <- list(structure(list(y = c(-0.667819876370237, 0.170711734013213, 0.552921941721332, -0.253162069270378, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, -1.36919169254062, 0.0881443844426084, -0.0834190388782434)), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0)), structure(list(y = NULL), .Names = 'y', class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ 0))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
       y
 1  NULL
@@ -14499,7 +14499,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr15#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr15#
 #argv <- list(structure(list(`cbind(w = weight, w2 = weight^2)` = structure(c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14, 4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69, 17.3889, 31.1364, 26.8324, 37.3321, 20.25, 21.2521, 26.7289, 20.5209, 28.4089, 26.4196, 23.1361, 17.3889, 19.4481, 12.8881, 34.4569, 14.6689, 36.3609, 23.9121, 18.6624, 21.9961), .Dim = c(20L, 2L), .Dimnames = list(NULL, c('w', 'w2'))), group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Ctl', 'Trt'), class = 'factor')), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group)), structure(list(`cbind(w = weight, w2 = weight^2)` = NULL, group = NULL), .Names = c('cbind(w = weight, w2 = weight^2)', 'group'), class = 'data.frame', row.names = c(NA, 20L), terms = quote(cbind(w = weight, w2 = weight^2) ~ group))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
    cbind(w = weight, w2 = weight^2) group
 1                              NULL  NULL
@@ -14526,7 +14526,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr16#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr16#
 #argv <- list(structure(list(Y = c(130L, 157L, 174L, 117L, 114L, 161L, 141L, 105L, 140L, 118L, 156L, 61L, 91L, 97L, 100L, 70L, 108L, 126L, 149L, 96L, 124L, 121L, 144L, 68L, 64L, 112L, 86L, 60L, 102L, 89L, 96L, 89L, 129L, 132L, 124L, 74L, 89L, 81L, 122L, 64L, 103L, 132L, 133L, 70L, 89L, 104L, 117L, 62L, 90L, 100L, 116L, 80L, 82L, 94L, 126L, 63L, 70L, 109L, 99L, 53L, 74L, 118L, 113L, 89L, 82L, 86L, 104L, 97L, 99L, 119L, 121L), B = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L), .Label = c('I', 'II', 'III', 'IV', 'V', 'VI'), class = 'factor'), V = structure(c(3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c('Golden.rain', 'Marvellous', 'Victory'), class = 'factor'), N = structure(c(2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt'), class = 'factor')), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame'), structure(list(Y = NULL, B = NULL, V = NULL, N = NULL), .Names = c('Y', 'B', 'V', 'N'), terms = quote(Y ~ B + V + N + V:N), row.names = 2:72, class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))
       Y    B    V    N
 2  NULL NULL NULL NULL
@@ -14604,7 +14604,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr17#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr17#
 #argv <- list(structure(list(Fr = c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), Hair = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), .Label = c('Black', 'Brown', 'Red', 'Blond'), class = 'factor'), Eye = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c('Brown', 'Blue', 'Hazel', 'Green'), class = 'factor'), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2)), structure(list(Fr = NULL, Hair = NULL, Eye = NULL, Sex = NULL), .Names = c('Fr', 'Hair', 'Eye', 'Sex'), class = 'data.frame', row.names = c(NA, 32L), terms = quote(Fr ~ (Hair + Eye + Sex)^2))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
      Fr Hair  Eye  Sex
 1  NULL NULL NULL NULL
@@ -14643,7 +14643,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr18#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr18#
 #argv <- list(structure(list(Employed = c(60.323, 61.122, 60.171, 61.187, 63.221, 63.639, 64.989, 63.761, 66.019, 67.857, 68.169, 66.513, 68.655, 69.564, 69.331, 70.551), GNP.deflator = c(83, 88.5, 88.2, 89.5, 96.2, 98.1, 99, 100, 101.2, 104.6, 108.4, 110.8, 112.6, 114.2, 115.7, 116.9), GNP = c(234.289, 259.426, 258.054, 284.599, 328.975, 346.999, 365.385, 363.112, 397.469, 419.18, 442.769, 444.546, 482.704, 502.601, 518.173, 554.894), Unemployed = c(235.6, 232.5, 368.2, 335.1, 209.9, 193.2, 187, 357.8, 290.4, 282.2, 293.6, 468.1, 381.3, 393.1, 480.6, 400.7), Armed.Forces = c(159, 145.6, 161.6, 165, 309.9, 359.4, 354.7, 335, 304.8, 285.7, 279.8, 263.7, 255.2, 251.4, 257.2, 282.7), Population = c(107.608, 108.632, 109.773, 110.929, 112.075, 113.27, 115.094, 116.219, 117.388, 118.734, 120.445, 121.95, 123.366, 125.368, 127.852, 130.081), Year = 1947:1962), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~     GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year)), structure(list(Employed = NULL, GNP.deflator = NULL, GNP = NULL, Unemployed = NULL, Armed.Forces = NULL, Population = NULL, Year = NULL), .Names = c('Employed', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'), class = 'data.frame', row.names = 1947:1962, terms = quote(Employed ~ GNP.deflator + GNP + Unemployed + Armed.Forces + Population + Year))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
      Employed GNP.deflator  GNP Unemployed Armed.Forces Population Year
 1947     NULL         NULL NULL       NULL         NULL       NULL NULL
@@ -14671,7 +14671,7 @@ In format.data.frame(x, digits = digits, na.encode = FALSE) :
 Error in `[[<-.data.frame`(`*tmp*`, i, value = numeric(0)) :
   replacement has 0 rows, data has 4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr2#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr2#
 #argv <- list(structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10, x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3)), structure(list(y = NULL, x1 = NULL, x2 = NULL, x3 = NULL), .Names = c('y', 'x1', 'x2', 'x3'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x1 + x2 + x3))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
       y   x1   x2   x3
 1  NULL NULL NULL NULL
@@ -14688,7 +14688,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr20#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr20#
 #argv <- list(structure(list(`cbind(X, M)` = structure(c(68, 42, 37, 24, 66, 33, 47, 23, 63, 29, 57, 19, 42, 30, 52, 43, 50, 23, 55, 47, 53, 27, 49, 29), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('X', 'M'))), M.user = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), .Label = c('N', 'Y'), class = 'factor'), Temp = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c('High', 'Low'), class = 'factor'), Soft = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c('Hard', 'Medium', 'Soft'), class = 'factor')), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X, M) ~ M.user + Temp + Soft)), structure(list(`cbind(X, M)` = NULL, M.user = NULL, Temp = NULL, Soft = NULL), .Names = c('cbind(X, M)', 'M.user', 'Temp', 'Soft'), class = 'data.frame', row.names = c('1', '3', '5', '7', '9', '11', '13', '15', '17', '19', '21', '23'), terms = quote(cbind(X,     M) ~ M.user + Temp + Soft))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
    cbind(X, M) M.user Temp Soft
 1         NULL   NULL NULL NULL
@@ -14707,7 +14707,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr3#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr3#
 #argv <- list(structure(list(y = c(-0.0561287395290008, -0.155795506705329, -1.47075238389927, -0.47815005510862, 0.417941560199702, 1.35867955152904, -0.102787727342996, 0.387671611559369, -0.0538050405829051, -1.37705955682861), x = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE), z = 1:10), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z)), structure(list(y = NULL, x = NULL, z = NULL), .Names = c('y', 'x', 'z'), class = 'data.frame', row.names = c(NA, 10L), terms = quote(y ~ x * z))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
       y    x    z
 1  NULL NULL NULL
@@ -14729,7 +14729,7 @@ In format.data.frame(x, digits = digits, na.encode = FALSE) :
 [1] surname     nationality deceased
 <0 rows> (or 0-length row.names)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr5#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr5#
 #argv <- list(structure(list(A = 0:10, B = 10:20, `NA` = 20:30), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame'), structure(list(A = NULL, B = NULL, `NA` = NULL), .Names = c('A', 'B', NA), row.names = c(NA, -11L), class = 'data.frame')); .Internal(copyDFattr(argv[[1]], argv[[2]]))
       A    B   NA
 1  NULL NULL NULL
@@ -14747,7 +14747,7 @@ Warning message:
 In format.data.frame(x, digits = digits, na.encode = FALSE) :
   corrupt data frame: columns will be truncated or padded with NAs
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr6#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_copyDFattr.testcopyDFattr6#
 #argv <- list(structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = structure(c(760, 2160, 5441, 277, 1815, 2587, 547, 1125, 2010, 2422, 6155, 1767, 61, 60, 7807, 7732, 6126, 7921, 3590, 5231, 5384, 5934, 6415, 6789, 6778, 3561, 4505, 3987, 4726, 5550, 5216, 5757, 2345, 6931, 6760, 5796, 4810, 5143, 3091, 3316, 700, 1706, 5088, 944, 2466, 1706, 7364, 1857, 9510, 9603, 31, 7479, 2006, 2588, 2983, 8761, 3932, 4201, 5293, 273, 2223, 4249, 5308, 8327, 499, 5789, 7417, 3242, 3275, 10359, 10852, 362, 9993, 1795, 3562, 4139, 4840, 4959, 547, 4119, 8308, 1674, 2953, 3776, 1369, 7911, 7519, 9318, 4370, 7301, 1642, 4169, 7417, 6117, 4536, 7235, 6723, 7397, 7428, 2084, 4066, 1673, 2860, 0, 3773, 4810, 4206, 2314, 4065, 8961, 6143, 517, 3837, 7498, 2815, 8806, 7668, 12457, 8600, 7003, 2435, 1826, 2403, 3805, 4901, 365, 6642, 3318, 3012, 1431, 2223, 4962, 5982, 638, 3346, 4996, 6800, 7454, 8887, 5024, 2833, 4232, 5238, 3186, 3380, 3382, 8100, 1766, 7184, 8059, 6008, 5047, 2236, 8165, 4224, 2844, 6256, 7370, 3560, 4939, 4941, 2230, 3068, 152, 10122, 3226, 3943, 518, 8569, 845, 2099, 8006, 8052, 9560, 0, 7965, 7470, 8133, 809, 153, 1851, 3010, 2121, 7085, 5068, 7093, 5930, 6878, 8080, 791, 6626, 3962, 1116, 1249, 9257, 1077, 566, 174, 4627, 5022, 2070, 3012, 1625, 6607, 8381, 8389, 1005, 3895, 4236, 6970, 8497, 2861, 8487, 3227, 8030, 8023, 31, 2435, 518, 4758, 7958, 7884, 4453, 6349, 7862, 1392, 3167, 6025, 4656, 1767, 7736, 2678, 2191, 3658, 7758, 8009, 2556, 3511, 7954, 822, 4321, 5151, 7545, 7576, 32, 7875, 5236, 7106, 2802, 7898, 3014, 7867, 5354, 2989, 7555, 6089, 8697, 6479, 1826, 5917, 792, 1431, 1434, 4763, 2910, 6209, 5824, 2400, 1400, 3027, 7198, 7247, 2557, 3855, 61, 7410, 1492, 7160, 7899, 5181, 7280, 3448, 7381, 2434, 6763, 7065, 1218, 1554, 7533, 7288, 2922, 5988, 2495, 5234, 9598, 2953, 2961, 4539, 3775, 6524, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 1, 2, 1, 2, 2, 0, 1, 2, 1, 2, 2, 2, 2, 0, 2, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 2, 0, 2, 2, 1, 0, 2, 2, 0, 0, 2, 0, 2, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 0, 0, 2, 2, 1, 2, 2, 1, 2, 0, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 1, 2, 1, 2, 2, 0, 2, 2, 2, 0, 2, 2, 1, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 1, 2, 0, 2, 2, 2, 1, 2, 1, 2, 2, 2, 0, 0, 2, 1, 2, 1, 0, 1, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 1, 2, 0, 2, 1, 2, 1, 2, 2, 0, 1, 2, 1, 0, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 1, 2, 2, 0, 2, 0, 2, 2, 0, 2, 0, 2, 2, 0, 1, 2, 0, 0, 1, 2, 1, 2, 0, 1, 2, 2, 1, 2), .Dim = c(300L, 2L), .Dimnames = list(NULL, c('time', 'status')), type = 'mright', states = c('1', '2'), class = 'Surv')), .Names = 'Surv(stop, status * as.numeric(event), type = \'mstate\')', class = 'data.frame', row.names = c(NA, 300L)), structure(list(`Surv(stop, status * as.numeric(event), type = 'mstate')` = NULL), .Names = 'Surv(stop, status * as.numeric(event), type = \'mstate\')', class = 'data.frame', row.names = c(NA, 300L))); .Internal(copyDFattr(argv[[1]], argv[[2]]))
     Surv(stop, status * as.numeric(event), type = 'mstate')
 1                                                      NULL
@@ -15541,6 +15541,11 @@ Error: could not find function "crc64"
 #crc64()
 Error: could not find function "crc64"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testCrossprod#Output.ImprovedErrorContext#
+#{ crossprod('asdf', matrix(1:6, ncol=2)) }
+Error in crossprod(x, y) :
+  requires numeric/complex matrix/vector arguments
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testCrossprod#
 #{ crossprod(1:3, matrix(1:6, ncol=2)) }
      [,1] [,2]
@@ -17036,7 +17041,7 @@ a[a <- TRUE]
 #argv <- list(quote(unclass(x)), 500, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "unclass(x)"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse40#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse40#
 #argv <- list(logical(0), logical(0), FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "logical(0)"
 Warning message:
@@ -17161,7 +17166,7 @@ f is deprecated.
 Use convertY instead.
 See help(Deprecated)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn10#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn10#
 #argv <- list('x is neither a vector nor a matrix: using as.numeric(x)', quote(dotchart(table(infert$education)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))
 NULL
 Warning message:
@@ -17177,14 +17182,14 @@ In package.skeleton("myTst", code_files = tmp) :
   file55711ba85492
  are now renamed to z<name>.R
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn12#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn12#
 #argv <- list('incomplete final line found by readTableHeader on foo4', quote(read.table('foo4', header = TRUE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))
 NULL
 Warning message:
 In read.table("foo4", header = TRUE) :
   incomplete final line found by readTableHeader on foo4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn2#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn2#
 #argv <- list('bessel_y(2,nu=288.12): precision lost in result', quote(besselY(2, nu = nu <- seq(3, 300, len = 51)))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))
 NULL
 Warning message:
@@ -17197,7 +17202,7 @@ NULL
 Warning message:
 glm.fit: algorithm stopped at boundary value
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn4#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn4#
 #argv <- list('header and col.names are of different lengths', quote(read.table('foo3', header = TRUE, col.names = letters[1:4]))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))
 NULL
 Warning message:
@@ -17217,7 +17222,7 @@ NULL
 Warning message:
 In log(ifelse(y == 0, 1, y/mu)) : NaNs produced
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn7#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn7#
 #argv <- list('drop argument will be ignored', quote(`[.data.frame`(women, 'height', drop = FALSE))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))
 NULL
 Warning message:
@@ -17231,7 +17236,7 @@ Warning message:
 In predict.lm(object, newdata, se.fit, scale = residual.scale, type = ifelse(type ==  :
   prediction from a rank-deficient fit may be misleading
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn9#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dfltWarn.testdfltWarn9#
 #argv <- list('1 y value <= 0 omitted from logarithmic plot', quote(xy.coords(x, NULL, log = log))); .Internal(.dfltWarn(argv[[1]], argv[[2]]))
 NULL
 Warning message:
@@ -19588,7 +19593,7 @@ logical(0)
 Error in duplicated.default(c(1, 2, 1), incomparables = function() 42) :
   cannot coerce type 'closure' to vector of type 'double'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#
 #{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) }
 [1] FALSE FALSE FALSE FALSE
 Warning message:
@@ -19599,7 +19604,7 @@ In duplicated.default(c(1, 2, 3, 2), incomparables = c(2 + (0+6i))) :
 #{ duplicated(c(1,2,3,4)) }
 [1] FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#
 #{ duplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") }
 [1] FALSE FALSE  TRUE  TRUE FALSE  TRUE
 Warning message:
@@ -20297,7 +20302,7 @@ numeric(0)
 #{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- c(NA,'col'); fr[1,2] }
 [1] 4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_dataframe.extractDataFrameWithNULLNames#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_dataframe.extractDataFrameWithNULLNames#
 #{ fr <- data.frame(1:3,4:6); attr(fr,'names') <- NULL; fr['col'] }
 
 1 NULL
@@ -20748,12 +20753,12 @@ logical(0)
 #{ x <- factor(c("a", "b", "a")); levels(x)<-c(7, 42); is.character(levels(x)) }
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#
 #{ x<-c("1","2","3"); class(x)<-"factor"; x }
 Error in class(x) <- "factor" :
   adding class "factor" to an invalid object
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#
 #{ x<-c(1,2,3); class(x)<-"factor"; x }
 Error in class(x) <- "factor" :
   adding class "factor" to an invalid object
@@ -20926,7 +20931,7 @@ In Ops.ordered(x, "a") : '+' is not meaningful for ordered factors
 #{ x<-factor(c("a", "b", "a", "c")); x == c("a", "b") }
 [1]  TRUE  TRUE  TRUE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#
 #{ x<-factor(c("c", "b", "a", "c")); y<-c(1); y[1]<-x; y }
 [1] 3
 Warning message:
@@ -20937,7 +20942,7 @@ In y[1] <- x :
 #{ x<-factor(c("c", "b", "a", "c")); y<-c(1); y[[1]]<-x; y }
 Error in y[[1]] <- x : more elements supplied than there are to replace
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#
 #{ x<-factor(c("c", "b", "a", "c")); y<-list(1); y[1]<-x; y }
 [[1]]
 [1] 3
@@ -22638,7 +22643,7 @@ Error: invalid 'pattern' argument
 #{ gsub("a","aa", "prAgue alley", fixed=TRUE) }
 [1] "prAgue aalley"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#
 #{ gsub("a","aa", "prAgue alley", fixed=TRUE, ignore.case=TRUE) }
 [1] "prAgue aalley"
 Warning message:
@@ -23575,7 +23580,7 @@ attr(,"Rd_tag")
 #{x <- 10;class(x) <- c("a", "b"); inherits(x,"a") ;}
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#
 #{x <- 10;class(x) <- c("a", "b");inherits(x, "a", 1) ;}
 Error in inherits(x, "a", 1) : 'which' must be a length 1 logical vector
 
@@ -23587,7 +23592,7 @@ Error in inherits(x, "a", 1) : 'which' must be a length 1 logical vector
 #{x <- 10;class(x) <- c("a", "b");inherits(x, "a", c(TRUE)) ;}
 [1] 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#
 #{x <- 10;class(x) <- c("a", "b");inherits(x, 2, c(TRUE)) ;}
 Error in inherits(x, 2, c(TRUE)) : 'what' must be a character vector
 
@@ -23740,7 +23745,7 @@ Error in inherits(x, 2, c(TRUE)) : 'what' must be a character vector
  [1] 01 01 00 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [26] 00 00 00 00 00 00 00
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#
 #intToBits('23rrff')
  [1] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [26] 00 00 00 00 00 00 01
@@ -23781,7 +23786,7 @@ Error in intToBits() : argument "x" is missing, with no default
  [1] 00 01 00 00 01 00 00 00 01 00 00 01 00 00 01 01 01 01 00 00 00 01 00 00 00
 [26] 00 00 00 00 00 00 00
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#
 #intToBits(5+7i)
  [1] 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [26] 00 00 00 00 00 00 00
@@ -23841,7 +23846,7 @@ raw(0)
 [101] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [126] 00 00 00
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_intToBits.testintToBits#
 #intToBits(list(c(5,5,7,8),88,6L))
 Error in intToBits(list(c(5, 5, 7, 8), 88, 6L)) :
   (list) object cannot be coerced to type 'integer'
@@ -24940,7 +24945,7 @@ Error: object 'f' not found
 #{is.factor(c)}
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfactor.testIsFactor#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfactor.testIsFactor#
 #{x<-1;class(x)<-"factor";is.factor(x)}
 Error in class(x) <- "factor" :
   adding class "factor" to an invalid object
@@ -25963,7 +25968,7 @@ FALSE FALSE
 Warning message:
 In is.na(is.na) : is.na() applied to non-(list or vector) of type 'builtin'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA#
 #is.na(quote(x()))
 [1] FALSE
 Warning message:
@@ -26187,7 +26192,7 @@ FALSE
 419  TRUE
 420 FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testisna29#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testisna29#
 #argv <- list(NULL);is.na(argv[[1]]);
 logical(0)
 Warning message:
@@ -26948,11 +26953,11 @@ logical(0)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#
 #{ x<-list(1,3); }
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#Output.IgnoreErrorContext#
 #{is.vector(c(1,2), TRUE);}
 Error in is.vector(x, mode) : invalid 'mode' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#Output.IgnoreErrorContext#
 #{is.vector(c(1,2), c("sss", "dddd"));}
 Error in is.vector(x, mode) : invalid 'mode' argument
 
@@ -27873,7 +27878,7 @@ Error in lengths(quote(a)) : 'x' must be a list or atomic vector
 #{ x <- 1 ; levels(x)<-4.5; levels(x);}
 [1] 4.5
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels#
 #{ x <- 1 ; levels(x)<-NULL; levels(notx)}
 Error in levels(notx) : object 'notx' not found
 
@@ -32040,7 +32045,7 @@ In max(NULL) : no non-missing arguments to max; returning -Inf
 #{ max(as.character(NA), as.character(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(as.character(NA), as.character(NA), na.rm=TRUE) }
 [1] NA
 Warning message:
@@ -32051,7 +32056,7 @@ In max(as.character(NA), as.character(NA), na.rm = TRUE) :
 #{ max(as.character(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(as.character(NA), na.rm=TRUE) }
 [1] NA
 Warning message:
@@ -32062,7 +32067,7 @@ In max(as.character(NA), na.rm = TRUE) :
 #{ max(as.double(NA), as.double(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(as.double(NA), as.double(NA), na.rm=TRUE) }
 [1] -Inf
 Warning message:
@@ -32073,7 +32078,7 @@ In max(as.double(NA), as.double(NA), na.rm = TRUE) :
 #{ max(as.double(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(as.double(NA), na.rm=TRUE) }
 [1] -Inf
 Warning message:
@@ -32372,7 +32377,7 @@ Time difference of 31 days
 #argv <- structure(list(x = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,     50), trim = 0.5), .Names = c('x', 'trim'));do.call('mean', argv)
 [1] 5.5
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_mean.testmean22#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mean.testmean22#
 #argv <- structure(list(x = structure(c(2L, 1L, 2L, 2L), .Label = c('FALSE',     'TRUE'), class = 'factor')), .Names = 'x');do.call('mean', argv)
 [1] NA
 Warning message:
@@ -32727,7 +32732,7 @@ In min(NULL) : no non-missing arguments to min; returning Inf
 #{ min(as.character(NA), as.character(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(as.character(NA), as.character(NA), na.rm=TRUE) }
 [1] NA
 Warning message:
@@ -32738,7 +32743,7 @@ In min(as.character(NA), as.character(NA), na.rm = TRUE) :
 #{ min(as.character(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(as.character(NA), na.rm=TRUE) }
 [1] NA
 Warning message:
@@ -32749,7 +32754,7 @@ In min(as.character(NA), na.rm = TRUE) :
 #{ min(as.double(NA), as.double(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(as.double(NA), as.double(NA), na.rm=TRUE) }
 [1] Inf
 Warning message:
@@ -32760,7 +32765,7 @@ In min(as.double(NA), as.double(NA), na.rm = TRUE) :
 #{ min(as.double(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(as.double(NA), na.rm=TRUE) }
 [1] Inf
 Warning message:
@@ -34037,7 +34042,7 @@ Error in argv[[4]] : subscript out of bounds
 #parent.env(new.env())
 <environment: R_GlobalEnv>
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(-1, "a", "b") }
 Error in ngettext(-1, "a", "b") : invalid 'n' argument
 
@@ -34045,7 +34050,7 @@ Error in ngettext(-1, "a", "b") : invalid 'n' argument
 #{ ngettext(0, "a", "b") }
 [1] "b"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1+1i, "a", "b") }
 [1] "a"
 Warning message:
@@ -34055,7 +34060,7 @@ In ngettext(1 + (0+1i), "a", "b") : imaginary parts discarded in coercion
 #{ ngettext(1, "a", "b") }
 [1] "a"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, "a", NULL) }
 Error in ngettext(1, "a", NULL) : 'msg2' must be a character string
 
@@ -34063,20 +34068,20 @@ Error in ngettext(1, "a", NULL) : 'msg2' must be a character string
 #{ ngettext(1, "a", c("b")) }
 [1] "a"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, "a", c("b", "c")) }
 Error in ngettext(1, "a", c("b", "c")) :
   'msg2' must be a character string
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, "a", c(1)) }
 Error in ngettext(1, "a", c(1)) : 'msg2' must be a character string
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, NULL, "b") }
 Error in ngettext(1, NULL, "b") : 'msg1' must be a character string
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, NULL, NULL) }
 Error in ngettext(1, NULL, NULL) : 'msg1' must be a character string
 
@@ -34084,12 +34089,12 @@ Error in ngettext(1, NULL, NULL) : 'msg1' must be a character string
 #{ ngettext(1, c("a"), "b") }
 [1] "a"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, c("a", "c"), "b") }
 Error in ngettext(1, c("a", "c"), "b") :
   'msg1' must be a character string
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ngettext.testNgettext#
 #{ ngettext(1, c(1), "b") }
 Error in ngettext(1, c(1), "b") : 'msg1' must be a character string
 
@@ -37715,7 +37720,7 @@ TRUE TRUE TRUE TRUE
 #argv <- list(34, 2L);`%/%`(argv[[1]],argv[[2]]);
 [1] 17
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators33#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators33#
 #argv <- list(c(20.8, 11.2, 6.2, 12.8, 43.4), c(10.4, 5.6, 3.1, 6.4, 21.7, 0, 10.4, 5.6, 3.1, 6.4, 21.7));`+`(argv[[1]],argv[[2]]);
  [1] 31.2 16.8  9.3 19.2 65.1 20.8 21.6 11.8 15.9 49.8 42.5
 Warning message:
@@ -39971,11 +39976,11 @@ character(0)
 #argv <- list(list(), NULL); .Internal(paste0(argv[[1]], argv[[2]]))
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation#
 #path.expand(42)
 Error in path.expand(42) : invalid 'path' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testArgsValidation#
 #path.expand(NULL)
 Error in path.expand(NULL) : invalid 'path' argument
 
@@ -40008,7 +40013,7 @@ character(0)
 #pmatch(1:5, c(1,3), duplicates.ok=42)
 [1]  1 NA  2 NA NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts#
 #pmatch(1:5, c(1,3), nomatch='str')
 [1]  1 NA  2 NA NA
 Warning message:
@@ -40054,11 +40059,11 @@ integer(0)
 #argv <- list(character(0), c('labels', 'col', 'alpha', 'adj', 'cex', 'lineheight', 'font'), NA_integer_, TRUE); .Internal(pmatch(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#
 #{ pmax(7+42i) }
 Error in pmax(7 + (0+42i)) : invalid input type
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#
 #{ pmax(as.raw(42)) }
 Error in pmax(as.raw(42)) : invalid input type
 
@@ -40078,7 +40083,7 @@ Error in pmax(as.raw(42)) : invalid input type
 #{ pmax(c("1", "7"), character()) }
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#
 #{ pmax(c("1", "7", "8"), c("1"), c("42", "1")) }
 [1] "42" "7"  "8"
 Warning message:
@@ -40109,7 +40114,7 @@ In pmax(c("1", "7", "8"), c("1"), c("42", "1")) :
 #{ pmax(c(1, 7), double()) }
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#
 #{ pmax(c(1, 7, 8), c(1), c(42, 1)) }
 [1] 42  7 42
 Warning message:
@@ -40132,7 +40137,7 @@ In pmax(c(1, 7, 8), c(1), c(42, 1)) :
 #{ pmax(c(1L, 7L), integer()) }
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmax.testPMax#
 #{ pmax(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }
 [1] 42  7 42
 Warning message:
@@ -40258,11 +40263,11 @@ Error in pmin(c(1, 2), c(3, 0), na.rm = NA) : invalid 'na.rm' value
 #pmin(c(1,2), c(3,NA), na.rm=c(42, 0))
 [1] 1 2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#
 #{ pmin(7+42i) }
 Error in pmin(7 + (0+42i)) : invalid input type
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#
 #{ pmin(as.raw(42)) }
 Error in pmin(as.raw(42)) : invalid input type
 
@@ -40282,7 +40287,7 @@ Error in pmin(as.raw(42)) : invalid input type
 #{ pmin(c("1", "7"), character()) }
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#
 #{ pmin(c("1", "7", "8"), c("1"), c("42", "1")) }
 [1] "1" "1" "1"
 Warning message:
@@ -40313,7 +40318,7 @@ In pmin(c("1", "7", "8"), c("1"), c("42", "1")) :
 #{ pmin(c(1, 7), double()) }
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#
 #{ pmin(c(1, 7, 8), c(1), c(42, 1)) }
 [1] 1 1 1
 Warning message:
@@ -40336,7 +40341,7 @@ In pmin(c(1, 7, 8), c(1), c(42, 1)) :
 #{ pmin(c(1L, 7L), integer()) }
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmin.testPMin#
 #{ pmin(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }
 [1] 1 1 1
 Warning message:
@@ -40512,7 +40517,7 @@ $n
 [1] 1
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_primUntrace.testArgsCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_primUntrace.testArgsCasts#
 #.primUntrace(42)
 Error in .primUntrace(42) : argument must be a function
 
@@ -41621,7 +41626,7 @@ attr(,"class")
 #{ x <- qr(c(3,1,2), LAPACK=TRUE) ; round( qr.coef(x, c(1,3,2)), digits=5 ) }
 [1] 0.71429
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_qr.testQr#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_qr.testQr#
 #{ x <- qr(cbind(1:10,2:11), LAPACK=TRUE) ; qr.coef(x, 1:2) }
 Error in qr.coef(x, 1:2) : right-hand side should have 10 not 2 rows
 
@@ -41767,7 +41772,7 @@ $ix
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_quit.testQuitEmptyEnv#
 #{ quit("yes") }
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_quit.testQuitErrorSave#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_quit.testQuitErrorSave#Output.ImprovedErrorContext#
 #{ quit("xx") }
 Error in quit(save, status, runLast) : unrecognized value of 'save'
 
@@ -42231,7 +42236,7 @@ Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
 #{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }
  [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteBinary#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteBinary#
 #{ zz <- rawConnection(raw(0), "wb"); x <- c("a", "this will be truncated", "abc"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = "\r\n"); res <- rawConnectionValue(zz); close(zz); res }
  [1] 61 00 00 74 68 69 73 20 77 69 6c 6c 20 61 62 63 61 0d 0a 00 74 68 69 73 20
 [26] 77 69 6c 6c 20 62 65 20 74 72 75 6e 63 61 74 65 64 0d 0a 00 61 62 63 0d 0a
@@ -43736,14 +43741,14 @@ In rep(7, each = integer()) : first element used of 'each' argument
 Warning message:
 In rep(7, length.out = NULL) : first element used of 'length.out' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
 #{ rep(7, length.out=c(7, 42)) }
 [1] 7 7 7 7 7 7 7
 Warning message:
 In rep(7, length.out = c(7, 42)) :
   first element used of 'length.out' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
 #{ rep(7, length.out=integer()) }
 [1] 7
 Warning message:
@@ -44277,7 +44282,7 @@ character(0)
 #{ rep.int(7, "7") }
 [1] 7 7 7 7 7 7 7
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
 #{ rep.int(7, NA)  }
 Error in rep.int(7, NA) : invalid 'times' value
 
@@ -44285,7 +44290,7 @@ Error in rep.int(7, NA) : invalid 'times' value
 #{ rep.int(7, NULL) }
 Error in rep.int(7, NULL) : incorrect type for second argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
 #{ rep.int(7, c(7, 42)) }
 Error in rep.int(7, c(7, 42)) : invalid 'times' value
 
@@ -44305,7 +44310,7 @@ numeric(0)
 #{ rep.int(c(1,2),2) }
 [1] 1 2 1 2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
 #{ rep.int(c(1,2,3),c(2,8)) }
 Error in rep.int(c(1, 2, 3), c(2, 8)) : invalid 'times' value
 
@@ -45223,11 +45228,11 @@ Error in sample.int(x, size, replace, prob) : invalid 'size' argument
 #set.seed(42); sample(3, c(2,3))
 [1] 3 2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
 #set.seed(42); sample(4, prob=c(-1,1,1,2))
 Error in sample.int(x, size, replace, prob) : negative probability
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
 #set.seed(42); sample(4, prob=c(1,2))
 Error in sample.int(x, size, replace, prob) :
   incorrect number of probabilities
@@ -45244,7 +45249,7 @@ Error in !replace : invalid argument type
 #set.seed(42); sample(4, replace=1.2)
 [1] 4 4 2 4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
 #set.seed(42); sample(4, replace=c(T,F))
 Error in sample.int(x, size, replace, prob) : invalid 'replace' argument
 
@@ -45500,7 +45505,7 @@ Read 3 items
 #{ con<-textConnection(c("HEADER", "7 2 3", "4 5 42")); scan(con, skip = 1, quiet=TRUE) }
 [1]  7  2  3  4  5 42
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#
 #{ con<-textConnection(c("HEADER", "7 2 3", "4 5 42")); scan(con, what = list("","","")) }
 Read 3 records
 [[1]]
@@ -45542,7 +45547,7 @@ Read 3 records
 [1] ""   "3"  "42"
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#
 #{ con<-textConnection(c("HEADER", "7 2 3", "4 5 42")); scan(con, what = list("","",""), multi.line=FALSE) }
 Error in scan(con, what = list("", "", ""), multi.line = FALSE) :
   line 1 did not have 3 elements
@@ -45561,7 +45566,7 @@ Read 4 items
 #{ con<-textConnection(c("TITLE extra line", "2 3 5 7", "11 13 17")); scan(con, skip = 1, quiet = TRUE) }
 [1]  2  3  5  7 11 13 17
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#
 #{ con<-textConnection(c("TITLE extra line", "2 3 5 7", "11 13 17")); scan(con, what = list("","","")) }
 Read 4 records
 [[1]]
@@ -58308,7 +58313,7 @@ integer(0)
  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#Output.IgnoreWarningContext#Output.IgnoreErrorContext#
 #{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) 'hello world'; seq_along(x) }
 Error: negative length vectors are not allowed
 In addition: Warning message:
@@ -58328,7 +58333,7 @@ NAs introduced by coercion
  [73]  73  74  75  76  77  78  79  80  81  82  83  84  85  86  87  88  89  90
  [91]  91  92  93  94  95  96  97  98  99 100
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_seq_along.testWithNonStandardLength#Output.IgnoreWarningContext#Output.IgnoreErrorContext#
 #{ x <- c(1,2,3); class(x) <- 'myclass'; length.myclass <- function(w) numeric(0); seq_along(x) }
 Error: negative length vectors are not allowed
 
@@ -59362,7 +59367,7 @@ In set.seed("hello world") : NAs introduced by coercion
 #.Internal(shortRowNames(42, '1'))
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testArgCasts#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_shortRowNames.testArgCasts#
 #.Internal(shortRowNames(42, -2))
 Error: invalid 'type' argument
 
@@ -61910,7 +61915,7 @@ Error: non-character argument
 [1] "abc"
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit#
 #{ strsplit("abc", ".", fixed = TRUE, perl=TRUE) }
 [[1]]
 [1] "abc"
@@ -63581,7 +63586,7 @@ if (x + y) {
 #{ substr(NA,1,2) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#
 #{ substr(c("abcdef", "aa"), 2, integer()) }
 Error in substr(c("abcdef", "aa"), 2, integer()) :
   invalid substring arguments
@@ -63602,7 +63607,7 @@ Error in substr(c("abcdef", "aa"), 2, integer()) :
 #{ substr(c("abcdef", "aa"), c(NA,8), 4) }
 [1] NA ""
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#
 #{ substr(c("abcdef", "aa"), integer(), 2) }
 Error in substr(c("abcdef", "aa"), integer(), 2) :
   invalid substring arguments
@@ -63635,11 +63640,11 @@ character(0)
 #{ x<-"abcdef"; substr(x,1,3)<-"0000"; x }
 [1] "000def"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext#
 #{ x<-"abcdef"; substr(x,1,3)<-NULL; x }
 Error in `substr<-`(`*tmp*`, 1, 3, value = NULL) : invalid value
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext#
 #{ x<-"abcdef"; substr(x,1,3)<-character(); x }
 Error in `substr<-`(`*tmp*`, 1, 3, value = character(0)) : invalid value
 
@@ -63651,7 +63656,7 @@ Error in `substr<-`(`*tmp*`, 1, 3, value = character(0)) : invalid value
 #{ x<-"abcdef"; substr(x,1,NA)<-"0"; x }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext#
 #{ x<-"abcdef"; substr(x,3,1)<-0; x }
 Error in `substr<-`(`*tmp*`, 3, 1, value = 0) : invalid value
 
@@ -63659,7 +63664,7 @@ Error in `substr<-`(`*tmp*`, 3, 1, value = 0) : invalid value
 #{ x<-"abcdef"; substr(x,NA,3)<-"0"; x }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testSubstring#Output.ImprovedErrorContext#
 #{ x<-"abcdef"; substr(x,integer(),3)<-NULL; x }
 Error in `substr<-`(`*tmp*`, integer(), 3, value = NULL) :
   invalid substring arguments
@@ -63825,14 +63830,14 @@ In sum(seq.int(-1, -1e+05)) : integer overflow - use sum(as.numeric(.))
 Warning message:
 In sum(seq.int(1, 1e+05)) : integer overflow - use sum(as.numeric(.))
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow#
 #sum(seq.int(from=-1, by=-1, length.out=100000))
 [1] NA
 Warning message:
 In sum(seq.int(from = -1, by = -1, length.out = 1e+05)) :
   integer overflow - use sum(as.numeric(.))
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testOveflow#
 #sum(seq.int(from=1, by=1, length.out=100000))
 [1] NA
 Warning message:
@@ -71791,11 +71796,11 @@ Warning message: In foo(42) : IgnoreWarningContext
 [1] 42
 
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs#
 #{ array(dim=c(-2,-2)); }
 Error in array(dim = c(-2, -2)) : the dims contain negative values
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testDefaultArgs#
 #{ array(dim=c(-2,2)); }
 Error in array(dim = c(-2, 2)) : negative length vectors are not allowed
 
@@ -75095,35 +75100,35 @@ Error in c(1, 0) && "1" : invalid 'y' type in 'x && y'
 #{ f <- function(a,b) { a && b } ;  f(c(TRUE, FALSE), logical()) }
 [1] NA
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#
 #{ as.raw(c(1,4)) | as.raw(c(1,5,4)) }
 [1] 01 05 05
 Warning message:
 In as.raw(c(1, 4)) | as.raw(c(1, 5, 4)) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#
 #{ as.raw(c(1,5,4)) | as.raw(c(1,4)) }
 [1] 01 05 05
 Warning message:
 In as.raw(c(1, 5, 4)) | as.raw(c(1, 4)) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#
 #{ c(TRUE, FALSE, FALSE) & c(TRUE,TRUE) }
 [1]  TRUE FALSE FALSE
 Warning message:
 In c(TRUE, FALSE, FALSE) & c(TRUE, TRUE) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#
 #{ c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) }
 [1]  TRUE FALSE FALSE
 Warning message:
 In c(TRUE, TRUE) & c(TRUE, FALSE, FALSE) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testNonvectorizedLogicalLengthChecks#
 #{ c(a=TRUE, TRUE) | c(TRUE, b=FALSE, FALSE) }
         b
 TRUE TRUE TRUE
@@ -76334,28 +76339,28 @@ numeric(0)
 #{ c(3,4) %/% 2 }
 [1] 1 2
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#
 #{ 1:2+1:3 }
 [1] 2 4 4
 Warning message:
 In 1:2 + 1:3 :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#
 #{ 1:3*1:2 }
 [1] 1 4 3
 Warning message:
 In 1:3 * 1:2 :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#
 #{ 1:3+c(1,2+2i) }
 [1] 2+0i 4+2i 4+0i
 Warning message:
 In 1:3 + c(1, 2 + (0+2i)) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testVectorsLengthWarning#
 #{ c(1,2+2i)+1:3 }
 [1] 2+0i 4+2i 4+0i
 Warning message:
@@ -76898,11 +76903,11 @@ Error in x[[, 1, 1]] : invalid subscript type 'symbol'
 #{ a = array(1:10, dim = c(2,6)); length(a) }
 [1] 12
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin#
 #{ array(NA, dim=c(-2,-2)); }
 Error in array(NA, dim = c(-2, -2)) : the dims contain negative values
 
-##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleArrays.testArrayBuiltin#
 #{ array(NA, dim=c(-2,2)); }
 Error in array(NA, dim = c(-2, 2)) :
   negative length vectors are not allowed
@@ -79187,14 +79192,14 @@ logical(0)
 #{ TRUE == 1:3 }
 [1]  TRUE FALSE FALSE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ as.raw(c(1,2)) < as.raw(c(2,1,4)) }
 [1]  TRUE FALSE  TRUE
 Warning message:
 In as.raw(c(1, 2)) < as.raw(c(2, 1, 4)) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ as.raw(c(2,1,4)) < as.raw(c(1,2)) }
 [1] FALSE  TRUE FALSE
 Warning message:
@@ -79209,7 +79214,7 @@ logical(0)
 #{ b <- 1:3 ; z <- FALSE ; b[2==2] }
 [1] 1 2 3
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c("cau", "ahoj") != c("hi","hello","bye") }
 [1] TRUE TRUE TRUE
 Warning message:
@@ -79236,7 +79241,7 @@ logical(0)
 #{ c("hello", NA) >= "hi" }
 [1] FALSE    NA
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c("hi","hello","bye") > c("cau", "ahoj") }
 [1]  TRUE  TRUE FALSE
 Warning message:
@@ -79251,7 +79256,7 @@ In c("hi", "hello", "bye") > c("cau", "ahoj") :
 #{ c(1+1i,2+1i) == c(0/0+1i,2+1i) }
 [1]   NA TRUE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(1+1i,2+2i) == c(2+1i,1+2i,1+1i) }
 [1] FALSE FALSE  TRUE
 Warning message:
@@ -79262,7 +79267,7 @@ In c(1 + (0+1i), 2 + (0+2i)) == c(2 + (0+1i), 1 + (0+2i), 1 + (0+1i)) :
 #{ c(1+2i, 3+4i) == (1+2i)[0] }
 logical(0)
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(1,2) < c(2,1,4) }
 [1]  TRUE FALSE  TRUE
 Warning message:
@@ -79293,7 +79298,7 @@ logical(0)
 #{ c(1L, NA) > c(NA, 2L) }
 [1] NA NA
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(1L,2L) < c(2L,1L,4L) }
 [1]  TRUE FALSE  TRUE
 Warning message:
@@ -79304,21 +79309,21 @@ In c(1L, 2L) < c(2L, 1L, 4L) :
 #{ c(1L,NA,2L) < 2L }
 [1]  TRUE    NA FALSE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(2+1i,1+2i,1+1i) == c(1+1i, 2+2i) }
 [1] FALSE FALSE  TRUE
 Warning message:
 In c(2 + (0+1i), 1 + (0+2i), 1 + (0+1i)) == c(1 + (0+1i), 2 + (0+2i)) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(2,1,4) < c(1,2) }
 [1] FALSE  TRUE FALSE
 Warning message:
 In c(2, 1, 4) < c(1, 2) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(2L,1L,4L) < c(1L,2L) }
 [1] FALSE  TRUE FALSE
 Warning message:
@@ -79333,14 +79338,14 @@ In c(2L, 1L, 4L) < c(1L, 2L) :
 #{ c(TRUE,FALSE) < logical() }
 logical(0)
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(TRUE,FALSE,FALSE) < c(TRUE,TRUE) }
 [1] FALSE  TRUE  TRUE
 Warning message:
 In c(TRUE, FALSE, FALSE) < c(TRUE, TRUE) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleComparison.testVectors#
 #{ c(TRUE,TRUE) == c(TRUE,FALSE,FALSE) }
 [1]  TRUE FALSE FALSE
 Warning message:
@@ -79636,7 +79641,7 @@ $class
 #{ x<-as.raw(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm="x"); is.data.frame(y); }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#
 #{ x<-c(7L,42L); y<-as.data.frame(x, row.names="r1", nm="x"); attributes(y); }
 $names
 [1] "x"
@@ -79679,7 +79684,7 @@ $class
 [1] "data.frame"
 
 
-##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#
 #{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c("r1", "r2", "r3"), nm="x"); attributes(y); }
 $names
 [1] "x"
@@ -80094,74 +80099,74 @@ Error: object 'v' not found
 #{ typeof(a~b) }
 [1] "language"
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ f <- function(a) { if (is.na(a)) { 1 } else { 2 } } ; f(5) ; f(1:3)}
 [1] 2
 Warning message:
 In if (is.na(a)) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(c(TRUE,FALSE)) ; f(1) }
 [1] TRUE
 Warning message:
 In if (cond) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(c(TRUE,FALSE)) ; f(FALSE) }
 [1] 2
 Warning message:
 In if (cond) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ f <- function(cond) { if (cond) { TRUE } else { 2 }  } ; f(logical()) }
 Error in if (cond) { : argument is of length zero
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ f <- function(cond) { if (cond) { TRUE } else { 2 } } ; f(1:3) ; f(2) }
 [1] TRUE
 Warning message:
 In if (cond) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (1:3) { TRUE } }
 [1] TRUE
 Warning message:
 In if (1:3) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (1[2:1]) { TRUE } }
 Error in if (1[2:1]) { : argument is not interpretable as logical
 In addition: Warning message:
 In if (1[2:1]) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (c(0,0,0)) { TRUE } else { 2 } }
 [1] 2
 Warning message:
 In if (c(0, 0, 0)) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (c(0L,0L,0L)) { TRUE } else { 2 } }
 [1] 2
 Warning message:
 In if (c(0L, 0L, 0L)) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (c(1L,0L,0L)) { TRUE } else { 2 } }
 [1] TRUE
 Warning message:
 In if (c(1L, 0L, 0L)) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (c(1L[2],0L,0L)) { TRUE } else { 2 } }
 Error in if (c(1L[2], 0L, 0L)) { :
   argument is not interpretable as logical
@@ -80169,7 +80174,7 @@ In addition: Warning message:
 In if (c(1L[2], 0L, 0L)) { :
   the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testCast#
 #{ if (integer()) { TRUE } }
 Error in if (integer()) { : argument is of length zero
 
@@ -80177,11 +80182,11 @@ Error in if (integer()) { : argument is of length zero
 #{ f <- function(v) { if (FALSE==v) TRUE else FALSE } ; f(TRUE) ; f(1) }
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ f <- function(x) { if (x == 2) 1 else 2 } ; f(1) ; f(NA) }
 Error in if (x == 2) 1 else 2 : missing value where TRUE/FALSE needed
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f("hello") }
 Error in if (x) 1 else 2 : argument is not interpretable as logical
 
@@ -80189,7 +80194,7 @@ Error in if (x) 1 else 2 : argument is not interpretable as logical
 #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(FALSE) }
 [1] 2
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(NA) }
 Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed
 
@@ -80197,11 +80202,11 @@ Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed
 #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(TRUE) }
 [1] 1
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(logical()) }
 Error in if (x) 1 else 2 : argument is of length zero
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ f <- function(x) { if (x) 1 else 2 } ; f(NA)  }
 Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed
 
@@ -80217,12 +80222,12 @@ Error in if (x) 1 else 2 : missing value where TRUE/FALSE needed
 #{ if (FALSE==TRUE) TRUE else FALSE }
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ if (NA == TRUE) TRUE else FALSE }
 Error in if (NA == TRUE) TRUE else FALSE :
   missing value where TRUE/FALSE needed
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ if (TRUE == NA) TRUE else FALSE }
 Error in if (TRUE == NA) TRUE else FALSE :
   missing value where TRUE/FALSE needed
@@ -80235,11 +80240,11 @@ Error in if (TRUE == NA) TRUE else FALSE :
 #{ x <- 2 ; if (1==x) TRUE else 2 }
 [1] 2
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ x <- 2 ; if (NA) x <- 3 ; x }
 Error in if (NA) x <- 3 : missing value where TRUE/FALSE needed
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIf#
 #{ x<-list(1,2); if (x) 7 else 42 }
 Error in if (x) 7 else 42 : argument is not interpretable as logical
 In addition: Warning message:
@@ -80261,7 +80266,7 @@ In if (x) 7 else 42 :
 ##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfDanglingElseIgnore#
 #if(FALSE) if (FALSE) 1 else 2
 
-##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfIgnore#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfIgnore#
 #{ f <- function(x) { if (x) 1 else 2 } ; f(1) ; f(1:3) }
 [1] 1
 Warning message:
@@ -80817,7 +80822,7 @@ $z
 #a<- NULL; a <- `$<-`(a, "a", 1); dput(a)
 structure(list(a = 1), .Names = "a")
 
-##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment#
+##com.oracle.truffle.r.test.library.base.TestSimpleLists.testNullListAssignment#Output.IgnoreErrorContext#
 #a<- NULL; a <- `$<-`(a, 1, 1); dput(a)
 Error: invalid subscript type 'double'
 
@@ -80969,7 +80974,7 @@ Error: unexpected '$' in "{ next(1,2,$"
 #{ next; }
 Error: no loop for break/next, jumping to top level
 
-##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrors#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleLoop.testLoopsErrors#
 #{ while (1 < NA) { 1 } }
 Error in while (1 < NA) { : missing value where TRUE/FALSE needed
 
@@ -82938,7 +82943,7 @@ In addition: Warning messages:
 2: In c(1, 2) < c(1, 3, 4) :
   longer object length is not a multiple of shorter object length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleTruffle.testWarningsAndErrors#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleTruffle.testWarningsAndErrors#
 #{ 1i > (c(1, 2) < c(1, 2, 3)) }
 Error in 0+1i > (c(1, 2) < c(1, 2, 3)) :
   invalid comparison with complex values
@@ -114938,7 +114943,7 @@ Error in x[["a", "d"]] : subscript out of bounds
 #{ c("1L","hello") %in% 1:10 }
 [1] FALSE FALSE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testIn#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testIn#
 #{ x <- function(){1} ; x %in% TRUE }
 Error in match(x, table, nomatch = 0L) :
   'match' requires vector arguments
@@ -117920,7 +117925,7 @@ Error in x[[c(TRUE, TRUE)]] :
 #{ x<-1:4;  x[c(0, 1)]<-42; x }
 [1] 42  2  3  4
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4;  x[c(0, 1)]<-c(7, 42); x }
 [1] 7 2 3 4
 Warning message:
@@ -117931,7 +117936,7 @@ In x[c(0, 1)] <- c(7, 42) :
 #{ x<-1:4;  x[c(1, 0)]<-42; x }
 [1] 42  2  3  4
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4;  x[c(1, 0)]<-c(7, 42); x }
 [1] 7 2 3 4
 Warning message:
@@ -118203,7 +118208,7 @@ Error in `[[<-`(`*tmp*`, list(1, 2, 3), value = c(42, 43)) :
 [1,]    1    3
 [2,]    2    4
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2); x[c(0,0,1)]<-c(42, 43); x }
      [,1] [,2]
 [1,]   42    3
@@ -118212,7 +118217,7 @@ Warning message:
 In x[c(0, 0, 1)] <- c(42, 43) :
   number of items to replace is not a multiple of replacement length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2); x[c(0,1)]<-c(42, 43); x }
      [,1] [,2]
 [1,]   42    3
@@ -118261,7 +118266,7 @@ Error in x[c(1 + (0+1i), 42 + (0+7i), 3 + (0+3i))] <- c(42, 43) :
 [1,]    7    3
 [2,]    2    4
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x }
      [,1] [,2]
 [1,]   42    3
@@ -118270,7 +118275,7 @@ Warning message:
 In x[c(1, 0)] <- c(42, 43) :
   number of items to replace is not a multiple of replacement length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2); x[c(1,0,0)]<-c(42, 43); x }
      [,1] [,2]
 [1,]   42    3
@@ -118389,7 +118394,7 @@ Error in x[list(1, 2, 3)] <- c(42, 43) : invalid subscript type 'list'
 #{ x<-1:4; x[1]<-NULL; x }
 Error in x[1] <- NULL : replacement has length zero
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; x[1]<-c(1,1); x }
 [1] 1 2 3 4
 Warning message:
@@ -119716,7 +119721,7 @@ numeric(0)
 #{ x <- NULL; x[1] <- c(); x; }
 NULL
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#
 #{ x <- NULL; x[1] <- c(1,5); x; }
 [1] 1
 Warning message:
@@ -119815,7 +119820,7 @@ Error in `[[<-`(`*tmp*`, c(1, 2), value = 5) :
 #{ x <- NULL; x[c(0,1)] <- c(); x; }
 NULL
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#
 #{ x <- NULL; x[c(0,1)] <- c(1,5); x; }
 [1] 1
 Warning message:
@@ -119830,7 +119835,7 @@ In x[c(0, 1)] <- c(1, 5) :
 #{ x <- NULL; x[c(0,2)] <- c(); x; }
 NULL
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#
 #{ x <- NULL; x[c(0,2)] <- c(1,5); x; }
 [1] NA  1
 Warning message:
@@ -119845,7 +119850,7 @@ In x[c(0, 2)] <- c(1, 5) :
 #{ x <- NULL; x[c(1,0)] <- c(); x; }
 NULL
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#
 #{ x <- NULL; x[c(1,0)] <- c(1,5); x; }
 [1] 1
 Warning message:
@@ -122488,7 +122493,7 @@ Error in b[3] <- as.raw(13) :
 #{ b <- c(1,2) ; z <- b ; b[3L] <- FALSE ; b }
 [1] 1 2 0
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarUpdate#
 #{ b <- c(1,2) ; z <- c(10,11) ; attr(z,"my") <- 4 ; b[2] <- z ; b }
 [1]  1 10
 Warning message:
@@ -123042,7 +123047,7 @@ $b
 attr(,"my")
 [1] 21
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate#
 #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1+2i,3:1,4:6) ; f(c(X=1,a=2),c("X","b",NA),c(TRUE,NA)) }
    X    a    b <NA>
    1    2   NA    1
@@ -123174,7 +123179,7 @@ $a
 [1] FALSE
 
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testStringUpdate#
 #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,3:1,4:6) ; f(c(X=1,a=2),c("a","X","a","b"),list(3,TRUE,FALSE)) }
 $X
 [1] TRUE
@@ -123852,7 +123857,7 @@ Error in b[i] <- v :
 Error in b[[c(NA, 1)]] <- c(2, 10) :
   attempt to select more than one element in integerOneIndex
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ b <- 3:4 ; b[c(0,1)] <- c(2,10,11) ; b }
 [1] 2 4
 Warning message:
@@ -123978,7 +123983,7 @@ attr(,"my")
 Error in b[c(FALSE, NA, NA)] <- c("X", "y") :
   NAs are not allowed in subscripted assignments
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ b <- c("a","b","c") ; b[c(FALSE,TRUE,TRUE)] <- c("X","y","z") ; b }
 [1] "a" "X" "y"
 Warning message:
@@ -124038,7 +124043,7 @@ Error in b[c(FALSE, TRUE, NA)] <- c("X", "z") :
 #{ b <- c(1,2,5) ;  x <- as.double(NA) ; attr(x,"my") <- 2 ; b[c(1,NA,2)==2] <- x ; b }
 [1]  1  2 NA
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ b <- c(1,2,5) ;  x <- c(2,2,-1) ; b[x==2] <- c(10,11,5) ; b }
 [1] 10 11  5
 Warning message:
@@ -124093,7 +124098,7 @@ Error in b[c(TRUE, NA, TRUE)] <- list(TRUE, 1 + (0+2i)) :
 #{ b <- c(1,2,5) ; b[logical()] <- NULL ; b }
 [1] 1 2 5
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ b <- c(1,4,5) ;  x <- c(2,2) ; b[x==2] <- c(10,11) ; b }
 [1] 10 11 10
 Warning message:
@@ -124124,7 +124129,7 @@ In b[x == 2] <- c(10, 11) :
 #{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,FALSE,TRUE,TRUE)] <- c(FALSE,NA,NA) ; b }
 [1] FALSE    NA    NA    NA
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ b <- c(TRUE,NA,FALSE) ; b[c(TRUE,TRUE)] <- c(FALSE,NA) ; b }
 [1] FALSE    NA FALSE
 Warning message:
@@ -124145,7 +124150,7 @@ attr(,"my")
 #{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,FALSE)] <- c(FALSE,NA) ; b }
 [1] FALSE    NA FALSE    NA
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ b <- c(TRUE,NA,FALSE,TRUE) ; b[c(TRUE,FALSE,TRUE,FALSE)] <- b ; b }
 [1] TRUE   NA   NA TRUE
 Warning message:
@@ -124305,7 +124310,7 @@ $x
 #{ f <- function(a) { a }; x<-1:5 ; x[x[4]<-2] <- ({x[4]<-100; f(x)[4]}) ; x }
 [1]   1 100   3   2   5
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.ImprovedErrorContext#
 #{ f <- function(b, i, v) { b[[i]] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }
 Error in `[[<-`(`*tmp*`, i, value = 5:6) :
   attempt to select more than one element in vectorIndex
@@ -124408,7 +124413,7 @@ Error in b[i] <- v : object of type 'closure' is not subsettable
 #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3, 1:2, 3:4); f(c(TRUE,FALSE), 2:1, 1:2) }
 [1] 2 1
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(1:3,c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }
 [1] 3 4 5
 Warning message:
@@ -124545,7 +124550,7 @@ Error in b[i] <- v :
 #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,NA), 4:5) }
 Error in b[i] <- v : NAs are not allowed in subscripted assignments
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ f <- function(b, i, v) { b[i] <- v ; b } ; f(c(1,2,3),c(TRUE,FALSE,TRUE),5:6) ; f(3:5, c(FALSE,TRUE,TRUE), 4:6) }
 [1] 3 4 5
 Warning message:
@@ -124775,7 +124780,7 @@ Error in b[i] <- v : only 0's may be mixed with negative subscripts
 #{ f <- function(b,i,v) { b[[i]] <- v ; b } ; f(1:2,"hi",3L) ; f(1:2,c(2),10) ; f(1:2, -1, 10) }
 [1]  1 10
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ f <- function(b,i,v) { b[b] <- b ; b } ; f(c(TRUE,FALSE,FALSE,TRUE)) ; f(1:3) }
 [1] 1 2 3
 Warning message:
@@ -125142,7 +125147,7 @@ attr(,"my")
 #{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- 5:6 ; x }
 [1] 5 2 6 4
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ x <- c(1L,2L,3L,4L) ; x[c(TRUE,FALSE)] <- rev(x) ; x }
 [1] 4 2 3 4
 Warning message:
@@ -125234,7 +125239,7 @@ $b
 [1] "b"
 
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ x <- list(1,0) ; attr(x,"my") <- 20 ; x[c(TRUE,FALSE)] <- c(11,12) ; x }
 [[1]]
 [1] 11
@@ -125248,7 +125253,7 @@ Warning message:
 In x[c(TRUE, FALSE)] <- c(11, 12) :
   number of items to replace is not a multiple of replacement length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ x <- list(1,0) ; x[as.logical(x)] <- c(10,11); x }
 [[1]]
 [1] 10
@@ -125260,7 +125265,7 @@ Warning message:
 In x[as.logical(x)] <- c(10, 11) :
   number of items to replace is not a multiple of replacement length
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ x <- list(1,0) ; x[c(TRUE,FALSE)] <- x[2:1] ; x }
 [[1]]
 [1] 0
@@ -125308,7 +125313,7 @@ In x[c(TRUE, FALSE)] <- x[2:1] :
 [1] 0
 
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testVectorUpdate#
 #{ x <- list(1,2) ; attr(x,"my") <- 10; x[c(TRUE,TRUE)] <- c(10,11,12); x }
 [[1]]
 [1] 10
@@ -131809,7 +131814,7 @@ In qwilcox(log(c(0, 4.2e-79, 0.1, 0.5, 0.7, 1 - 4.2e-79, 1)), 4,  :
  [1] 0.000000 0.000000 0.000000 1.333333 6.000000 5.666667 5.000000 0.000000
  [9] 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
 
-##com.oracle.truffle.r.test.library.stats.TestExternal_BinDist.testBinDistWrongArgs#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.stats.TestExternal_BinDist.testBinDistWrongArgs#
 #.Call(stats:::C_BinDist, 0, 0, 'string', 3, 5)
  [1] 0 0 0 0 0 0 0 0 0 0
 Warning message:
@@ -131985,7 +131990,7 @@ In qgamma(10, 1) : NaNs produced
 #set.seed(42); rbinom('10', 10, 0.5)
  [1] 7 7 4 7 6 5 6 3 6 6
 
-##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.stats.TestExternal_rbinom.testRbinom#
 #set.seed(42); rbinom('aa', 10, 0.5)
 Error in rbinom("aa", 10, 0.5) : invalid arguments
 In addition: Warning message:
@@ -134905,7 +134910,7 @@ Error in rwilcox(30, c(NA, 0, NaN, 1/0, -1/0), c(NaN, NaN, NA, 0, 1/0,  :
 #length(runif(c(1,2,3)))
 [1] 3
 
-##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testFunctions2Infrastructure#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testFunctions2Infrastructure#
 #runif('hello')
 Error in runif("hello") : invalid arguments
 In addition: Warning message:
@@ -135017,7 +135022,7 @@ In rhyper(1, NA, 5, 20) : NAs produced
 Warning message:
 In RNGkind(NULL, gen) : buggy version of Kinderman-Ramage generator used
 
-##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testRmultinom#Output.IgnoreErrorContext#Output.IgnoreErrorMessage#
+##com.oracle.truffle.r.test.library.stats.TestRandGenerationFunctions.testRmultinom#
 #rmultinom('string', 1, 0.15)
 Error in rmultinom("string", 1, 0.15) : invalid first argument 'n'
 In addition: Warning message:
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
index 4f6b89d198..6ab794a48f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
@@ -153,7 +153,7 @@ public class TestBuiltin_anyDuplicated extends TestBase {
         assertEval("{ anyDuplicated(c(1+1i, 4-6i, 4-6i, 6+7i)) }");
         assertEval("{ anyDuplicated(c(1, 4+6i, 7+7i, 1), incomparables = c(1, 2)) }");
 
-        assertEval(Output.IgnoreWarningContext, "{ anyDuplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }");
-        assertEval(Output.IgnoreWarningContext, "{ anyDuplicated(c(1,2,3,2), incomparables = c(2+6i)) }");
+        assertEval("{ anyDuplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }");
+        assertEval("{ anyDuplicated(c(1,2,3,2), incomparables = c(2+6i)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
index 35c8c1b6b1..11385e6c40 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
@@ -395,16 +395,16 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testAsVector() {
-        assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"integer\") }");
-        assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"double\") }");
-        assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"numeric\") }");
+        assertEval("{ as.vector(\"foo\", \"integer\") }");
+        assertEval("{ as.vector(\"foo\", \"double\") }");
+        assertEval("{ as.vector(\"foo\", \"numeric\") }");
         assertEval("{ as.vector(\"foo\", \"logical\") }");
-        assertEval(Output.IgnoreWarningContext, "{ as.vector(\"foo\", \"raw\") }");
+        assertEval("{ as.vector(\"foo\", \"raw\") }");
         assertEval("{ as.vector(\"foo\", \"character\") }");
         assertEval("{ as.vector(\"foo\", \"list\") }");
         assertEval("{ as.vector(\"foo\") }");
         assertEval(Output.ImprovedErrorContext, "{ as.vector(\"foo\", \"bar\") }");
-        assertEval(Output.IgnoreWarningContext, "{ as.vector(c(\"foo\", \"bar\"), \"raw\") }");
+        assertEval("{ as.vector(c(\"foo\", \"bar\"), \"raw\") }");
         assertEval("x<-c(a=1.1, b=2.2); as.vector(x, \"raw\")");
         assertEval("x<-c(a=1L, b=2L); as.vector(x, \"complex\")");
         assertEval("{ x<-c(a=FALSE, b=TRUE); attr(x, \"foo\")<-\"foo\"; y<-as.vector(x); attributes(y) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java
index 3040237600..4af409dd94 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java
@@ -126,8 +126,8 @@ public class TestBuiltin_duplicated extends TestBase {
         assertEval("{ duplicated(c(1+1i, 4-6i, 4-6i, 6+7i)) }");
         assertEval("{ duplicated(c(1, 4+6i, 7+7i, 1), incomparables = c(1, 2)) }");
 
-        assertEval(Output.IgnoreWarningContext, "{ duplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }");
-        assertEval(Output.IgnoreWarningContext, "{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) }");
+        assertEval("{ duplicated(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = \"cat\") }");
+        assertEval("{ duplicated(c(1,2,3,2), incomparables = c(2+6i)) }");
 
         assertEval("{ duplicated(NULL, 0); }");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
index 5ccb8c0e1e..bb55cca660 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
@@ -91,7 +91,7 @@ public class TestBuiltin_pmax extends TestBase {
     public void testPMax() {
         assertEval("{ pmax(c(1L, 7L), c(42L, 1L)) }");
         assertEval("{ pmax(c(1L, 7L), integer()) }");
-        assertEval(Output.IgnoreWarningContext, "{ pmax(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }");
+        assertEval("{ pmax(c(1L, 7L, 8L), c(1L), c(42L, 1L)) }");
         assertEval("{ pmax(c(1L, 7L), c(42L, as.integer(NA))) }");
         assertEval("{ pmax(c(1L, 7L), c(42L, as.integer(NA)), na.rm=TRUE) }");
 
@@ -103,7 +103,7 @@ public class TestBuiltin_pmax extends TestBase {
 
         assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", \"1\")) }");
         assertEval("{ pmax(c(\"1\", \"7\"), character()) }");
-        assertEval(Output.IgnoreWarningContext, "{ pmax(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
+        assertEval("{ pmax(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
         assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }");
         assertEval("{ pmax(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }");
         assertEval("{ pmax(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
index 29710a9eae..a1cd197065 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
@@ -88,7 +88,7 @@ public class TestBuiltin_pmin extends TestBase {
 
         assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", \"1\")) }");
         assertEval("{ pmin(c(\"1\", \"7\"), character()) }");
-        assertEval(Output.IgnoreWarningContext, "{ pmin(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
+        assertEval("{ pmin(c(\"1\", \"7\", \"8\"), c(\"1\"), c(\"42\", \"1\")) }");
         assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA))) }");
         assertEval("{ pmin(c(\"1\", \"7\"), c(\"42\", as.character(NA)), na.rm=TRUE) }");
         assertEval("{ pmin(c(\"1\", as.character(NA)), c(\"42\", \"1\"), na.rm=TRUE) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java
index 79296c9ac3..83462672a3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java
@@ -32,7 +32,7 @@ public class TestExternal_rbinom extends TestBase {
     public void testRbinom() {
         assertEval("set.seed(42); rbinom(10, 10, 0.5)");
         assertEval("set.seed(42); rbinom('10', 10, 0.5)");
-        assertEval(Output.IgnoreWarningContext, "set.seed(42); rbinom('aa', 10, 0.5)");
+        assertEval("set.seed(42); rbinom('aa', 10, 0.5)");
         assertEval("set.seed(42); rbinom(10, 2:10, c(0.1, 0.5, 0.9))");
         assertEval("set.seed(42); rbinom(1:10, 2:10, c(0.1, 0.5, 0.9))");
         assertEval("set.seed(42); rbinom(c(1,2), 11:12, c(0.1, 0.5, 0.9))");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
index 3098d53ec1..69ce1013d4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
@@ -51,7 +51,7 @@ public class TestRandGenerationFunctions extends TestBase {
         assertEval("length(runif(c('a', 'b', 'b', 'd')))");
         assertEval("length(runif('3'))");
         // wrong size argument
-        assertEval(Output.IgnoreWarningContext, "runif('hello')");
+        assertEval("runif('hello')");
         // empty parameters
         assertEval("runif(2, numeric(), 2)");
         assertEval("runif(2, 2, numeric())");
-- 
GitLab


From 9bb88e5df0b4b6c130dea4c141866962327d1e01 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 24 Feb 2017 19:13:56 +0100
Subject: [PATCH 059/402] fix copyrights

---
 .../com/oracle/truffle/r/nodes/builtin/base/Contributors.java   | 2 +-
 .../src/com/oracle/truffle/r/nodes/builtin/base/License.java    | 2 +-
 .../src/com/oracle/truffle/r/nodes/builtin/base/Missing.java    | 2 +-
 .../truffle/r/nodes/access/ReadVariadicComponentNode.java       | 2 +-
 .../com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java  | 2 +-
 .../oracle/truffle/r/nodes/access/vector/CachedVectorNode.java  | 2 +-
 .../truffle/r/nodes/access/vector/RecursiveSubscriptNode.java   | 2 +-
 .../truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java | 2 +-
 .../com/oracle/truffle/r/nodes/builtin/casts/MessageData.java   | 2 +-
 .../r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java      | 2 +-
 .../src/com/oracle/truffle/r/nodes/control/OperatorNode.java    | 2 +-
 .../src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java     | 2 +-
 .../src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java       | 2 +-
 .../src/com/oracle/truffle/r/test/S4/TestS4.java                | 2 +-
 .../truffle/r/test/builtins/TestBuiltin_Syssetlocale.java       | 2 +-
 .../src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java | 2 +-
 .../truffle/r/test/builtins/TestBuiltin_anyDuplicated.java      | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java   | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java   | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java  | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java  | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java  | 2 +-
 .../truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java      | 2 +-
 .../truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java      | 2 +-
 .../src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java   | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java    | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java  | 2 +-
 .../truffle/r/test/builtins/TestBuiltin_extract_dataframe.java  | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java  | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_inherits.java    | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java   | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java    | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java    | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_isvector.java    | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java  | 2 +-
 .../src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java    | 2 +-
 .../src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java    | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java  | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java  | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java    | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java    | 2 +-
 .../oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java | 2 +-
 .../src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java  | 2 +-
 .../src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java  | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java  | 2 +-
 .../com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java    | 2 +-
 .../truffle/r/test/library/base/TestSimpleArithmetic.java       | 2 +-
 .../oracle/truffle/r/test/library/base/TestSimpleArrays.java    | 2 +-
 .../truffle/r/test/library/base/TestSimpleComparison.java       | 2 +-
 .../truffle/r/test/library/base/TestSimpleIfEvaluator.java      | 2 +-
 .../com/oracle/truffle/r/test/library/base/TestSimpleLoop.java  | 2 +-
 .../oracle/truffle/r/test/library/base/TestSimpleTruffle.java   | 2 +-
 .../truffle/r/test/library/stats/TestExternal_rbinom.java       | 2 +-
 57 files changed, 57 insertions(+), 57 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
index cd0f1324ed..2a64ec2f8e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
index 2e9f08ddef..6c6bc4795b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
index 92cad61f05..a7ed208b7c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java
index 5b4dd38552..cf54077f80 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
index 62d420220e..d019c7e235 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java
index 7755156678..bc1808ef44 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
index f294ca9f1b..0e4e9b5030 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
index 673c3be0be..82f194dd2f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
index 714387dcc5..5d875a64a4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/MessageData.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java
index 359c638900..c5b0f8e93c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/FindFirstNodeBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java
index 03698070ae..cf77ea161c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/OperatorNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
index a3d342a25f..12212196eb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
index 068243c102..ef9b7f15c4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 691383aecf..01287bcef7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
index cc310553ac..b13bdb9886 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java
index 805844fbc3..6f66c04a96 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_all.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
index 6ab794a48f..4459a88831 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
index fa9e4a7732..9bd788df9e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
index 341cea102c..43a54a0dd2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java
index b5bbe5f6d2..845dfe6bb6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attach.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
index e26626578d..e69737300c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java
index e3cee63390..1f872e33ec 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseNot.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
index b122941859..d750ef4512 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
index 1fab7d1275..de9c5d5ae2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java
index 7b92ea2e08..14c81d8038 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cat.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
index 61a835aef8..74a1c7a8e1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java
index 5741c165e1..d21234fe96 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dfltWarn.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java
index 4af409dd94..7fd5356776 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_duplicated.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java
index c50fd3e298..d078eccb01 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_dataframe.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java
index afeeea62aa..85b20fc02c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_factor.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
index 7a7ba51168..6bbed855de 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java
index fbead7016d..7f45267721 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_intToBits.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java
index d0ca51b6e3..9b14bf8048 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfactor.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
index 59cd8da598..0322c2fb15 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
index 5eb2c4fbf5..372f103da4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
index e2e5405b40..e327a1ad7c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_levels.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
index 1ac1ef7f5b..592a227d53 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
index cd6cea5290..fa34857033 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
index 685a13c6d2..6611a99ccc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java
index 2164d33db1..640757eabc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ngettext.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
index a929a4004d..0b873424d1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
index 019a276b8d..70bc9c36d2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
index bb55cca660..426e2c4d77 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmax.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
index a1cd197065..d3624ecd3a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmin.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java
index 3a86e0a772..d910a6cdea 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
index 4adce90c62..397aa78e82 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qr.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
index 5591689a05..b8e0d6b946 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
index fe634e2b20..7a99ff8e09 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
index d21d73c43b..1531169e52 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
index 2f2074ef28..7856a43ce5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java
index ec16560044..59bec36ada 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArithmetic.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java
index 9ccc585559..b2b0daed5f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleArrays.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java
index 557546aaeb..163f682083 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleComparison.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
index d7063ba2a9..60dc992cb1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
index ce3819fa70..2c34e86d42 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLoop.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java
index e347c051f5..8112db7c94 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleTruffle.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java
index 83462672a3..74edb90098 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_rbinom.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From c5e9f44dbe866e2b1dc901773ea490da62511bfc Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Feb 2017 10:50:45 +0100
Subject: [PATCH 060/402] smaller default size for weak hash maps

---
 .../truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 8455c58c0c..a5cc3f5cce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -169,7 +169,7 @@ public final class FrameSlotChangeMonitor {
     private static final class FrameDescriptorMetaData {
         private final String name; // name for debug purposes
         private final WeakReference<MaterializedFrame> singletonFrame;
-        private final Set<FrameDescriptor> subDescriptors = Collections.newSetFromMap(new WeakHashMap<>());
+        private final Set<FrameDescriptor> subDescriptors = Collections.newSetFromMap(new WeakHashMap<>(2));
 
         /**
          * This set contains all lookups that have been performed "across" this frame descriptor. If
@@ -180,7 +180,7 @@ public final class FrameSlotChangeMonitor {
         /**
          * A set of all lookups that started in this frame descriptor.
          */
-        private final WeakHashMap<Object, WeakReference<LookupResult>> lookupResults = new WeakHashMap<>();
+        private final WeakHashMap<Object, WeakReference<LookupResult>> lookupResults = new WeakHashMap<>(2);
 
         private WeakReference<FrameDescriptor> enclosingFrameDescriptor = new WeakReference<>(null);
         private Assumption enclosingFrameDescriptorAssumption = Truffle.getRuntime().createAssumption("enclosing frame descriptor");
-- 
GitLab


From 0e63ceb05554a4ec98cf9cfaeab8611ed5c3c79f Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 20 Feb 2017 18:02:35 -0800
Subject: [PATCH 061/402] [GR-378] Create an internal package repo for package
 tests

---
 .gitignore                                    |    6 +-
 ci.hocon                                      |    9 +
 .../r/engine/shell/RscriptCommand.java        |   12 +-
 .../src/com/oracle/truffle/r/runtime/DCF.java |    7 +-
 .../oracle/truffle/r/runtime/REnvVars.java    |   12 +-
 .../truffle/r/runtime/RStartParams.java       |   12 +-
 com.oracle.truffle.r.test.native/Makefile     |    6 +-
 .../packages/Makefile                         |    4 +-
 .../packages/PACKAGES                         |   17 +
 .../packages/Rutils/template.R                |   76 +
 .../packages/package.mk                       |   30 +-
 .../packages/pkg-filelist                     |    3 +
 .../packages/testrffi/testrffi/DESCRIPTION    |    7 +-
 .../testrffi/testrffi/man/testrffi-package.Rd |   13 +-
 .../testrffi/testrffi/man/testrffi.Rd         |   35 -
 .../packages/testrffi/testrffi/src/init.c     |    6 +
 .../testrffi/testrffi/tests/asTests.Rin       |    6 +
 .../testrffi/testrffi/tests/coerceTests.Rin   |   42 +
 .../testrffi/testrffi/tests/simpleTests.R     |   24 +
 .../packages/vanilla/vanilla/man/vanilla.Rd   |   35 -
 .../initial.package.blacklist                 |    0
 .../ok.packages                               |    0
 .../r/install.package.R                       |    5 +-
 .../r/install.packages.R                      |  108 +-
 .../r/test.package.R                          |    2 +-
 .../recommended                               |    0
 .../top100                                    |    0
 .../top100test                                |    0
 .../truffle/r/test/ExpectedTestOutput.test    | 1283 -----------------
 .../truffle/r/test/rffi/TestRFFIPackage.java  |  219 ---
 .../r/test/rffi/TestRFFIPackageCoercions.java |   90 --
 .../r/test/rpackages/TestRPackages.java       |  206 ---
 .../rpackages/TestRecommendedPackages.java    |   90 --
 .../r/test/rpackages/TestS4TestPackage.java   |   69 -
 .../r/test/rpackages/TestVanillaPackage.java  |   63 -
 documentation/dev/testing.md                  |   41 +-
 mx.fastr/mx_fastr.py                          |   12 +-
 mx.fastr/mx_fastr_dists.py                    |   15 +-
 mx.fastr/mx_fastr_pkgs.py                     |  119 +-
 mx.fastr/suite.py                             |    2 +-
 40 files changed, 445 insertions(+), 2241 deletions(-)
 create mode 100644 com.oracle.truffle.r.test.native/packages/PACKAGES
 create mode 100644 com.oracle.truffle.r.test.native/packages/Rutils/template.R
 create mode 100644 com.oracle.truffle.r.test.native/packages/pkg-filelist
 delete mode 100644 com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd
 create mode 100644 com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin
 create mode 100644 com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin
 create mode 100644 com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
 delete mode 100644 com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/initial.package.blacklist (100%)
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/ok.packages (100%)
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/r/install.package.R (93%)
 rename com.oracle.truffle.r.test.cran/r/install.cran.packages.R => com.oracle.truffle.r.test.packages/r/install.packages.R (90%)
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/r/test.package.R (95%)
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/recommended (100%)
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/top100 (100%)
 rename {com.oracle.truffle.r.test.cran => com.oracle.truffle.r.test.packages}/top100test (100%)
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java

diff --git a/.gitignore b/.gitignore
index 9c8ffbab24..fa2967697f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,7 @@
 /com.oracle.truffle.r.native/fficall/jniboot.done
 /com.oracle.truffle.r.native.recommended/install.recommended
 /com.oracle.truffle.r.test.native/packages/copy_recommended
+/com.oracle.truffle.r.test.native/packages/repo/*
 /com.oracle.truffle.r.test.native/packages/recommended
 /com.oracle.truffle.r.test.native/packages/*/lib/*
 /com.oracle.truffle.r.test.native/urand/lib/liburand.so
@@ -127,10 +128,13 @@ R.tokens
 findbugs.html
 test_gnur
 test_fastr
-lib.install.cran*
+lib.install.packages*
 package.blacklist
 *.ll
 *.su
 *.bc
 com.oracle.truffle.r.test.native/embedded/lib
 bench-results.json
+com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.R
+com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.R
+com.oracle.truffle.r.native/version.built
diff --git a/ci.hocon b/ci.hocon
index 752f2f46a7..94646dd855 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -134,6 +134,14 @@ rbcheck : ${common} {
   ]
 }
 
+internalPkgtest: ${common} {
+  run : [
+    ["mx", "build"]
+    ["mx", "pkgtest", "--repos", "FASTR", "--pkg-filelist", "com.oracle.truffle.r.test.native/packages/pkg-filelist"]
+  ]
+  logs: ${common.logs}
+}
+
 # The standard set of gate builds. N.B. the style/builtin checks are only run on Linux as they are not OS-dependent.
 
 builds = [
@@ -142,4 +150,5 @@ builds = [
   ${gateTestDarwin}           {capabilities : [darwin, amd64], targets : [gate, post-merge], name: "gate-test-darwin-amd64"}
   ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-style-linux-amd64"}
   ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-rbcheck-linux-amd64"}
+  ${internalPkgtest}          {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-internal-pkgtest-linux-amd64"}
 ]
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
index 1af3eff3eb..03ffb7af58 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.engine.shell;
 
+import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES;
 import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.EXPR;
 import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.FILE;
 import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.HELP;
@@ -43,7 +44,6 @@ import com.oracle.truffle.r.runtime.RVersionNumber;
  * to R, as evidenced by the script {@code print(commandArgs())}. We don't implement it quite that
  * way but the effect is similar.
  *
- * TODO support {@code --default-packages} option.
  */
 public class RscriptCommand {
     // CheckStyle: stop system..print check
@@ -77,6 +77,14 @@ public class RscriptCommand {
                 options.setValue(FILE, arguments[firstNonOptionArgIndex]);
             }
         }
+        String defaultPackagesArg = options.getString(DEFAULT_PACKAGES);
+        String defaultPackagesEnv = System.getenv("R_DEFAULT_PACKAGES");
+        if (defaultPackagesArg == null && defaultPackagesEnv == null) {
+            defaultPackagesArg = "datasets,utils,grDevices,graphics,stats";
+        }
+        if (defaultPackagesEnv == null) {
+            options.setValue(DEFAULT_PACKAGES, defaultPackagesArg);
+        }
         // copy up to non-option args
         int rx = 1;
         while (rx < firstNonOptionArgIndex) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java
index 5f5fa9f83c..48069f9e2f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DCF.java
@@ -70,8 +70,11 @@ public class DCF {
                     fieldContent = new StringBuffer();
                 }
                 if (endOfParagraph(line)) {
-                    result.paragraphs.add(fields);
-                    fields = new Fields();
+                    fieldName = null;
+                    if (!fields.fieldMap.isEmpty()) {
+                        result.paragraphs.add(fields);
+                        fields = new Fields();
+                    }
                     continue;
                 }
                 int ix = line.indexOf(':');
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index 86e5fd3060..dac1239411 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
@@ -57,7 +59,13 @@ public final class REnvVars implements RContext.ContextState {
     @Override
     public RContext.ContextState initialize(RContext context) {
         // explicit environment settings in nested contexts must be installed first
-        checkExplciitEnvSettings(context);
+        checkExplicitEnvSettings(context);
+        RCmdOptions cmdOptions = context.getStartParams().getRCmdOptions();
+        // If running Rscript, R_DEFAULT_PACKAGES may need to be set
+        String defaultPackages = cmdOptions.getString(DEFAULT_PACKAGES);
+        if (defaultPackages != null) {
+            envVars.put("R_DEFAULT_PACKAGES", defaultPackages);
+        }
         // set the standard vars defined by R
         checkRHome();
         // Always read the system file
@@ -119,7 +127,7 @@ public final class REnvVars implements RContext.ContextState {
         return new REnvVars();
     }
 
-    private void checkExplciitEnvSettings(RContext context) {
+    private void checkExplicitEnvSettings(RContext context) {
         String[] envs = context.getEnvSettings();
         if (envs == null || envs.length == 0) {
             return;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
index 854b3c93b6..cdadca6a12 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
@@ -86,9 +86,9 @@ public class RStartParams {
     private boolean noReadline;
 
     /**
-     * The original command line arguments that were parsed by {@link RCmdOptions}.
+     * The result from parsing the command line options.
      */
-    private final String[] arguments;
+    private final RCmdOptions cmdOptions;
 
     /**
      * Indicates that FastR is running embedded.
@@ -96,7 +96,7 @@ public class RStartParams {
     private boolean embedded;
 
     public RStartParams(RCmdOptions options, boolean embedded) {
-        this.arguments = options.getArguments();
+        this.cmdOptions = options;
         this.embedded = embedded;
         if (options.getBoolean(VERBOSE)) {
             this.verbose = true;
@@ -246,8 +246,12 @@ public class RStartParams {
         return this.noReadline;
     }
 
+    public RCmdOptions getRCmdOptions() {
+        return cmdOptions;
+    }
+
     public String[] getArguments() {
-        return arguments;
+        return cmdOptions.getArguments();
     }
 
     public void setEmbedded() {
diff --git a/com.oracle.truffle.r.test.native/Makefile b/com.oracle.truffle.r.test.native/Makefile
index d996da3e45..9c3c1b9ffc 100644
--- a/com.oracle.truffle.r.test.native/Makefile
+++ b/com.oracle.truffle.r.test.native/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -26,9 +26,12 @@
 export TOPDIR = $(CURDIR)
 # all output goes into the com.oracle.truffle.r.test project for packaging into a single distribution
 export MX_OUTPUT_DIR = $(abspath $(TOPDIR)/../mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test)
+export REPO_DIR := $(TOPDIR)/packages/repo/src/contrib
 OSNAME := $(shell uname)
 
 all:
+	mkdir -p $(REPO_DIR)
+	cp packages/PACKAGES $(REPO_DIR)
 	$(MAKE) -C urand
 	$(MAKE) -C packages
 ifneq ($(OSNAME), SunOS)
@@ -41,3 +44,4 @@ clean:
 ifneq ($(OSNAME), SunOS)
 	$(MAKE) -C embedded clean
 endif
+	rm -f $(REPO_DIR)/*
diff --git a/com.oracle.truffle.r.test.native/packages/Makefile b/com.oracle.truffle.r.test.native/packages/Makefile
index 1ddf9d6a2f..501b4d81f6 100644
--- a/com.oracle.truffle.r.test.native/packages/Makefile
+++ b/com.oracle.truffle.r.test.native/packages/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,7 @@
 SUBDIRS = testrffi vanilla tests4
 NATIVE_PROJECT = $(subst test.native,native,$(TOPDIR))
 R_VERSION := $(notdir $(wildcard $(NATIVE_PROJECT)/gnur/R-*))
-GNUR_HOME := $(NATIVE_PROJECT)/gnur/$(R_VERSION)
+export GNUR_HOME := $(NATIVE_PROJECT)/gnur/$(R_VERSION)
 GNUR_RECOMMENDED := $(wildcard $(GNUR_HOME)/src/library/Recommended/*.tgz)
 
 # We have to copy the GNU R recommended packages into this project
diff --git a/com.oracle.truffle.r.test.native/packages/PACKAGES b/com.oracle.truffle.r.test.native/packages/PACKAGES
new file mode 100644
index 0000000000..aa815aabd4
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/PACKAGES
@@ -0,0 +1,17 @@
+Package: testrffi
+Version: 1.0
+Depends: R
+License: GPL-2
+NeedsCompilation: yes
+
+Package: tests4
+Version: 1.0
+Depends: R
+License: GPL-2
+NeedsCompilation: no
+
+Package: vanilla
+Version: 1.0
+Depends: R
+License: GPL-2
+NeedsCompilation: no
diff --git a/com.oracle.truffle.r.test.native/packages/Rutils/template.R b/com.oracle.truffle.r.test.native/packages/Rutils/template.R
new file mode 100644
index 0000000000..33c6e2b15b
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/Rutils/template.R
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+expandTemplate <- function(template, ...) {
+	resultLength <- 1
+	params <- list(...)
+	for (i in seq_along(params)) {
+		resultLength <- resultLength * length(params[[i]])
+	}
+	index <- 1
+	result <- character(resultLength)
+	positions <- rep(1, length(params))
+	while (index <= resultLength) {
+		currentString <- template
+		for (i in seq_along(params)) {
+			currentPos <- positions[[i]]
+			currentString <- sub(paste0("%", i - 1), params[[i]][[currentPos]], currentString)
+		}
+		result[[index]] <- currentString
+		index <- index + 1
+
+		for (i in seq_along(params)) {
+			positions[[i]] <- positions[[i]] + 1
+			if (positions[[i]] >= length(params[[i]])) {
+				positions[[i]] <- 1
+			} else {
+				break
+			}
+		}
+	}
+	result
+}
+
+initialTest <- function(libname, template, ...) {
+	tests <- expandTemplate(template, ...)
+	Rfile <- sub("\\.Rin$", ".R", commandArgs(T))
+	sink(Rfile)
+	requireLibrary(libname)
+	outputTests(tests)
+}
+
+extraTest <- function(template, ...) {
+	tests <- expandTemplate(template, ...)
+	outputTests(tests)
+}
+
+outputTests <- function(tests) {
+	# errors must not cause halt, so wrap in try
+	for (i in seq_along(tests)) {
+		cat(paste0("try(", tests[[i]], ")\n"))
+	}
+}
+
+requireLibrary <- function(libname) {
+	cat(paste0("stopifnot(require(", libname, "))\n"))
+}
diff --git a/com.oracle.truffle.r.test.native/packages/package.mk b/com.oracle.truffle.r.test.native/packages/package.mk
index c7e7565abc..e98e4d3f6d 100644
--- a/com.oracle.truffle.r.test.native/packages/package.mk
+++ b/com.oracle.truffle.r.test.native/packages/package.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -23,19 +23,35 @@
 
 # This "builds" a test package, resulting in a tar file,
 # which is then loaded by the unit tests in TestRPackages.
+# It uses R CMD build ...
+# Currently we can't use FastR for this step as FastR isn't completely built
+# when this is built (it's part of the build)
+# The resulting package is stored in the "repo/src/contrib" folder
+
+# test packages may include .Rin files that are preprocessed to create an
+# actual test file. Unfortunately while R CND check will do this, tools::testInstalledPackage
+# does not (surely a bug). So we generate the files here.
 
 .PHONY: all
 
-PKG_FILES = $(shell find $(PACKAGE)/ -type f -name '*')
+PKG_FILES = $(shell find $(PACKAGE) -type f -name '*')
+
+PKG_TAR = $(REPO_DIR)/$(PACKAGE)_1.0.tar.gz
 
-PKG_TAR = lib/$(PACKAGE).tar
+RIN_FILES = $(shell find $(PACKAGE) -type f -name '*.Rin')
+RIN_R_FILES = $(subst .Rin,.R, $(RIN_FILES))
+TEMPLATE_FILE := ../Rutils/template.R
 
-all: $(PKG_TAR)
+all: $(RIN_R_FILES) $(PKG_TAR)
 
 $(PKG_TAR): $(PKG_FILES)
-	mkdir -p lib
-	tar cf $(PKG_TAR) $(PACKAGE)
+	(cd $(REPO_DIR); TZDIR=/usr/share/zoneinfo/ $(GNUR_HOME)/bin/R CMD build $(CURDIR)/$(PACKAGE))
+
+$(RIN_R_FILES): $(RIN_FILES)
+	for rf in $(RIN_FILES); do \
+		TEMPLATE_FILE=$(TEMPLATE_FILE) $(GNUR_HOME)/bin/Rscript $$rf $$rf || exit 1; \
+	done
 
 clean:
-	rm -f $(PKG_TAR)
+	rm -f $(PKG_TAR) $(RIN_R_FILES)
 
diff --git a/com.oracle.truffle.r.test.native/packages/pkg-filelist b/com.oracle.truffle.r.test.native/packages/pkg-filelist
new file mode 100644
index 0000000000..55e8fe1d11
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/pkg-filelist
@@ -0,0 +1,3 @@
+vanilla
+tests4
+testrffi
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION
index 6469b3112f..a21a01b707 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/DESCRIPTION
@@ -1,9 +1,10 @@
 Package: testrffi
 Type: Package
-Title: Tests a package with native code
+Title: Tests The R FFI interface
 Version: 1.0
-Date: 2014-08-21
+Date: 2017-02-2
 Author: FastR Tester
 Maintainer: FastR Tester <fastr@yahoogroups.com>
-Description: Tests a package with native code
+Description: Tests The R FFI interface
 License: GPL-2
+NeedsCompilation: yes
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd
index f73ed8ca85..2ea30d34d2 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd
@@ -2,14 +2,20 @@
 \alias{testrffi-package}
 \alias{testrffi}
 \docType{package}
-\title{Tests a package with native code}
-\description{Tests a package with native code}
+\title{Tests the R FFI interface}
+\description{Tests the R FFI interface via a collection of R functions that
+call down to native code using .Call which then typically make R FFI upcalls to
+test the individual functions. The set of tests is not comprehensive.
+
+The individual functions are not documented here as there are far too many
+and they are not intended for user-level usage.
+}
 \details{
 \tabular{ll}{
 Package: \tab testrffi\cr
 Type: \tab Package\cr
 Version: \tab 1.0\cr
-Date: \tab 2014-08-21\cr
+Date: \tab 2017-02-20\cr
 License: \tab GPL-2\cr
 }
 
@@ -27,5 +33,4 @@ Maintainer: fastr@yahoogroups.com
 
 }
 \examples{
-
 }
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd
deleted file mode 100644
index edb39851ba..0000000000
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi.Rd
+++ /dev/null
@@ -1,35 +0,0 @@
-\name{testrffi}
-\alias{testrffi}
-%- Also NEED an '\alias' for EACH other topic documented here.
-\title{
-testrffi
-}
-\description{
-Tests the R FFI interface
-}
-\usage{
-addint(2,3)
-}
-
-\details{
-
-}
-\value{
-invisble NULL
-}
-\references{
-
-}
-\author{
-FastR Team
-}
-\note{
-
-}
-
-\seealso{
-%
-}
-\examples{
-addint(2,3)
-}
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
index cf78dd91c9..cfddf3c96f 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
@@ -32,6 +32,12 @@ static const R_CMethodDef CEntries[]  = {
 
 #define CALLDEF(name, n)  {#name, (DL_FUNC) &name, n}
 
+/* It is not strictly necessary to include every C function in this table, as
+ * it simply enables a call to be made with the "C_name" variable style of .Call,
+ * as opposed to simply using the string "name". The latter is the default mechanism
+ * used in testrffi.c.
+*/
+
 static const R_CallMethodDef CallEntries[] = {
         CALLDEF(addInt, 2),
         CALLDEF(addDouble, 2),
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin
new file mode 100644
index 0000000000..13e6e52b1d
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.Rin
@@ -0,0 +1,6 @@
+source(Sys.getenv("TEMPLATE_FILE"))
+
+as_values <- c("1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)", "as.symbol(\"sym\")", "list()")
+as_funs <- c("Char", "Integer", "Real", "Logical")
+
+initialTest("testrffi", "rffi.as%0(%1)",  as_funs, as_values)
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin
new file mode 100644
index 0000000000..17d7899930
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.Rin
@@ -0,0 +1,42 @@
+source(Sys.getenv("TEMPLATE_FILE"))
+
+NILSXP <- as.character(0)
+SYMSXP <- as.character(1)
+LISTSXP <- as.character(2)
+CLOSXP <- as.character(3)
+ENVSXP <- as.character(4)
+PROMSXP <- as.character(5)
+LANGSXP <- as.character(6)
+SPECIALSXP <- as.character(7)
+BUILTINSXP <- as.character(8)
+CHARSXP <- as.character(9)
+LGLSXP <- as.character(10)
+INTSXP <- as.character(13)
+REALSXP <- as.character(14)
+CPLXSXP <- as.character(15)
+STRSXP <- as.character(16)
+DOTSXP <- as.character(17)
+ANYSXP <- as.character(18)
+VECSXP <- as.character(19)
+EXPRSXP <- as.character(20)
+BCODESXP <- as.character(21)
+EXTPTRSXP <- as.character(22)
+WEAKREFSXP <- as.character(23)
+RAWSXP <- as.character(24)
+S4SXP <- as.character(25)
+
+coercion_values_for_expr <- c("2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)",
+                    "list()", "structure(2.2, names='b',dim=c(1,1),myattr='q')", "structure(T, names='c',dim=c(1,1),myattr='q'")
+
+coercion_values <- c("1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)",
+                    "c(T, F)", "list()", "structure(1L,names='a',dim=c(1,1),myattr='q')", "structure(2.2, names='b',dim=c(1,1),myattr='q')",
+                    "structure(T, names='c',dim=c(1,1),myattr='q')", "structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'")
+
+coercion_modes <- c(SYMSXP, NILSXP, VECSXP, INTSXP, REALSXP, LGLSXP, STRSXP, CPLXSXP, RAWSXP)
+
+initialTest("testrffi", "rffi.coerceVector(%0, %1)", coercion_values, coercion_modes)
+
+extraTest("rffi.coerceVector(%0, %1)", coercion_values_for_expr, EXPRSXP)
+
+# Ignored.Unimplemented
+# extraTest(paste0("rffi.coerceVector(structure(list(1,'x'), names=c('q','w'),dim=c(2,1),myattr='q'), ", EXPRSXP, ")"))
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
new file mode 100644
index 0000000000..92cf03a236
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
@@ -0,0 +1,24 @@
+stopifnot(require(testrffi))
+
+rffi.addInt(2L, 3L)
+rffi.addDouble(2, 3)
+rffi.populateIntVector(5)
+rffi.populateLogicalVector(5)
+rffi.mkStringFromChar()
+rffi.mkStringFromBytes()
+rffi.null()
+try(rffi.null.E())
+rffi.null.C()
+rffi.isRString(character(0))
+a <- c(1L,2L,3L); rffi.iterate_iarray(a)
+a <- c(1L,2L,3L); rffi.iterate_iptr(a)
+rffi.dotCModifiedArguments(c(0,1,2,3))
+rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12))
+rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12))
+rffi.invoke12()
+rffi.TYPEOF(3L)
+rffi.isRString("hello")
+rffi.isRString(NULL)
+rffi.interactive()
+x <- 1; rffi.findvar("x", globalenv())
+x <- "12345"; rffi.char_length(x)
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd b/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd
deleted file mode 100644
index 21eb5aea52..0000000000
--- a/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/man/vanilla.Rd
+++ /dev/null
@@ -1,35 +0,0 @@
-\name{vanilla}
-\alias{vanilla}
-%- Also NEED an '\alias' for EACH other topic documented here.
-\title{
-vanilla
-}
-\description{
-prints A vaniila R package
-}
-\usage{
-vanilla()
-}
-
-\details{
-
-}
-\value{
-invisble NULL
-}
-\references{
-
-}
-\author{
-FastR Team
-}
-\note{
-
-}
-
-\seealso{
-%
-}
-\examples{
-vanilla()
-}
diff --git a/com.oracle.truffle.r.test.cran/initial.package.blacklist b/com.oracle.truffle.r.test.packages/initial.package.blacklist
similarity index 100%
rename from com.oracle.truffle.r.test.cran/initial.package.blacklist
rename to com.oracle.truffle.r.test.packages/initial.package.blacklist
diff --git a/com.oracle.truffle.r.test.cran/ok.packages b/com.oracle.truffle.r.test.packages/ok.packages
similarity index 100%
rename from com.oracle.truffle.r.test.cran/ok.packages
rename to com.oracle.truffle.r.test.packages/ok.packages
diff --git a/com.oracle.truffle.r.test.cran/r/install.package.R b/com.oracle.truffle.r.test.packages/r/install.package.R
similarity index 93%
rename from com.oracle.truffle.r.test.cran/r/install.package.R
rename to com.oracle.truffle.r.test.packages/r/install.package.R
index e3a4f99e85..70e6958084 100644
--- a/com.oracle.truffle.r.test.cran/r/install.package.R
+++ b/com.oracle.truffle.r.test.packages/r/install.package.R
@@ -21,7 +21,7 @@
 # questions.
 #
 
-# A script to do a single package installation (+dependents), called from install.cran.packages.R.
+# A script to do a single package installation (+dependents), called from install.packages.R.
 # It exists as a separate script only to avoid internal FastR errors from killing the
 # entire installation process for multiple package installation tests.
 
@@ -33,14 +33,13 @@ args <- commandArgs(TRUE)
 parse.args <- function() {
 	if (length(args)) {
 		pkgname <<- args[[1]]
-		contriburl<<- args[[2]]
+		contriburl <<- strsplit(args[[2]], ",")[[1]]
 		lib.install <<- args[[3]]
 	}
 }
 
 run <- function() {
 	parse.args()
-	# TODO install Suggests for vingette testing
 	install.packages(pkgname, contriburl=contriburl, type="source", lib=lib.install, INSTALL_opts="--install-tests")
 }
 
diff --git a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R
similarity index 90%
rename from com.oracle.truffle.r.test.cran/r/install.cran.packages.R
rename to com.oracle.truffle.r.test.packages/r/install.packages.R
index a9e905e9a5..397c82bec3 100644
--- a/com.oracle.truffle.r.test.cran/r/install.cran.packages.R
+++ b/com.oracle.truffle.r.test.packages/r/install.packages.R
@@ -21,7 +21,7 @@
 # questions.
 #
 
-# A script to install and optionally test CRAN packages, with a blacklist mechanism starting
+# A script to install and optionally test packages (typically from CRAN), with a blacklist mechanism starting
 # from a known set of packages that we cannot handle, e.g. Rcpp (due to C++)
 # By default all packages are candidates for installation, but this
 # can be limited in the following ways:
@@ -31,21 +31,32 @@
 # 3. from the set of installed packages found in the lib install directory (option --pkg-list-installed)
 #    (useful primarily for testing a set of pre-installed packages
 
+# This script can install packages from a variety of sources PROVIDED that they follow the
+# structure used by CRAN, which is the main source of packages in the R world. (I.e. they support
+# utils::available.packages and utils::install.packages).
+# Other sources include:
+#
+# BioConductor
+# GitHub
+# FastR internal packages
+
+# BioConductor has it's own install mechanism but it is layered on the CRAN model.
+
 # By default, we use the CRAN mirror specified by --cran-mirror or env var CRAN_MIRROR.
-# If unset, defaults to "http://cran.cnr.berkeley.edu/"
-# However, a local copy of the CRAN repo can be used either by setting the LOCAL_CRAN_REPO env variable or setting --contrib-url
+# If unset, it defaults to "http://cran.cnr.berkeley.edu/"
 
 # Packages are installed into the directory specified by the --lib arg (or R_LIBS_USER env var)
 
-# Blacklisted packages nor their dependents will not be installed. By default the list of blacklisted
-# packages will be read from the file in the --blacklist-file arg or the PACKAGE_BLACKLIST env var.
-# If unset, defaults to "package.blacklist", and will be created if necessary. The initial set of
-# blacklisted packages are read from the file specified by --initial-blacklist-file (defaults to
-# value of env var INITIAL_PACKAGE_BLACKLIST or initial.package.blacklist if unset). This is
-# DCF file with entries of the form:
+# By default, blacklisted packages nor their dependents will not be installed. The list of blacklisted
+# packages will be read from the file in the --blacklist-file arg (defaults to "package.blacklist"),
+# and will be created if necessary. The initial set of blacklisted packages are read from the file specified by
+# --initial-blacklist-file (defaults to "com.oracle.truffle.r.test.packages/initial.package.blacklist").
+# This is a DCF file with entries of the form:
 # Package: name
 # Reason: reason
 
+# The --ignore-blacklist option can be used to suppress the use of the blacklist.
+
 # The env var R_LIBS_USER or the option --lib must be set to the directory where the install should take place.
 # N.B. --lib works for installation. However, when running tests ( --run-tests), it does not and
 # R_LIBS_USER must be set instead (as well) since some of the test code has explicit "library(foo)" calls
@@ -91,7 +102,7 @@
 args <- commandArgs(TRUE)
 
 usage <- function() {
-	cat(paste("usage: Rscript [--contriburl url] [--cran-mirror url] ",
+	cat(paste("usage: Rscript [--cran-mirror url] ",
                       "[--verbose | -v] [-V] [--dryrun]",
                       "[--no-install | -n] ",
 				      "[--create-blacklist] [--blacklist-file file] [--ignore-blacklist]",
@@ -243,34 +254,34 @@ abort <- function(msg) {
 	quit("no", status=100)
 }
 
-set.contriburl <- function() {
-	# if contriburl is set explicitly that's all we need
-	if (!is.na(contriburl)) {
-		return(contriburl)
-	}
-
-	# check for env var setting
-	contriburl <<- Sys.getenv("LOCAL_CRAN_REPO", unset=NA)
-	if (!is.na(contriburl)) {
-		return(contriburl)
+set.repos <- function() {
+	# Based on the value of repos.list we set the "repos" option
+	# which is used by available.packages etc.
+	repos <- character()
+	needCran <- F
+	if ("BIOC" %in% repo.list) {
+		repos["BIOC"] <- "https://bioconductor.org/packages/3.4/bioc"
+		needCran <- T
+	}
+	if (needCran || "CRAN" %in% repo.list) {
+		# set from the cran-mirror value
+		if (is.na(cran.mirror)) {
+			# not set on command line
+			cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/")
+		}
+		repos["CRAN"] <- cran.mirror
 	}
-
-	# set from the cran-mirror value
-	if (is.na(cran.mirror)) {
-		# not set on command line
-		cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/")
+	if ("FASTR" %in% repo.list) {
+		# set the FastR internal repo
+		repos["FASTR"] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo"))
 	}
-	r <- getOption("repos")
-	r["CRAN"] <- cran.mirror
-	options(repos = r)
-	contriburl <<- contrib.url(r, "source")
-	contriburl
+	options(repos = repos)
 }
 
 set.package.blacklist <- function() {
 	if (is.na(blacklist.file)) {
 	    # not set on command line
-		blacklist.file <<- Sys.getenv("PACKAGE_BLACKLIST", unset="package.blacklist")
+		blacklist.file <<- "package.blacklist"
 	}
 	if (!create.blacklist.file && !ignore.blacklist) {
 		if (!file.exists(blacklist.file)) {
@@ -280,12 +291,12 @@ set.package.blacklist <- function() {
 	}
 }
 
-this.package <- "com.oracle.truffle.r.test.cran"
+this.package <- "com.oracle.truffle.r.test.packages"
 
 set.initial.package.blacklist <- function() {
 	if (is.na(initial.blacklist.file)) {
 		# not set on command line
-		initial.blacklist.file <<- Sys.getenv("INITIAL_PACKAGE_BLACKLIST", unset=file.path(this.package, "initial.package.blacklist"))
+		initial.blacklist.file <<- file.path(this.package, "initial.package.blacklist")
 	}
 
 }
@@ -357,7 +368,7 @@ check.installed.pkgs <- function() {
 	pkgs.ok
 }
 
-# find the available packages from contriburl and match those against the
+# find the available packages and match those against the
 # requested set of candidate packages
 # sets global variables avail.pkgs and toinstall.pkgs, the latter being
 # of the same type as avail.pkgs but containing only those packages to install
@@ -370,14 +381,14 @@ get.pkgs <- function() {
 		quit(save="no", status=100)
 	}
 	tryCatch({
-	    avail.pkgs <<- available.packages(contriburl=contriburl, type="source")
+	    avail.pkgs <<- available.packages(type="source")
     }, warning=my.warning)
 
     # Owing to a FastR bug, we may not invoke the handler above, but
 	# if length(avail.pkgs) == 0, that also means it failed
 	if (length(avail.pkgs) == 0) {
 		if (!quiet) {
-		  print("Fatal error: no packages found in repo")
+		  print("Fatal error: no packages found in repo(s)")
     	}
 		quit(save="no", status=100)
 	}
@@ -420,6 +431,11 @@ get.pkgs <- function() {
 	}
 	matched.avail.pkgs <- apply(avail.pkgs, 1, match.fun)
 	toinstall.pkgs <<-avail.pkgs[matched.avail.pkgs, , drop=F]
+	if (length(toinstall.pkgs) == 0) {
+		print("Fatal error: requested package(s) found in repo(s)")
+		quit(save="no", status=100)
+
+	}
 
 	if (!is.na(random.count)) {
 		# install random.count packages taken at random from toinstall.pkgs
@@ -654,7 +670,7 @@ do.it <- function() {
 }
 
 # Should package "x" be included in the install?
-# No, if it is inthe blacklist set (what about --ignore-blacklist?)
+# No, if it is in the blacklist set (what about --ignore-blacklist?)
 # Nor if it is in ok.pkg.filelist (what does this achieve)
 include.package <- function(x, blacklist) {
 	return (!(x["Package"] %in% blacklist || x["Package"] %in% ok.pkg.filelist))
@@ -674,7 +690,7 @@ install.pkg <- function(pkgname) {
 	if (run.mode == "system") {
 		system.install(pkgname)
 	} else if (run.mode == "internal") {
-		install.packages(pkgname, contriburl=contriburl, type="source", lib=lib.install, INSTALL_opts="--install-tests")
+		install.packages(pkgname, type="source", lib=lib.install, INSTALL_opts="--install-tests")
 	} else if (run.mode == "context") {
 		stop("context run-mode not implemented\n")
 	}
@@ -705,13 +721,13 @@ gnu_rscript <- function() {
 }
 
 system.install <- function(pkgname) {
-	script <- normalizePath("com.oracle.truffle.r.test.cran/r/install.package.R")
+	script <- normalizePath("com.oracle.truffle.r.test.packages/r/install.package.R")
 	if (is.fastr()) {
 		rscript = file.path(R.home(), "bin", "Rscript")
 	} else {
 		rscript = gnu_rscript()
 	}
-	args <- c(script, pkgname, contriburl, lib.install)
+	args <- c(script, pkgname, paste0(contrib.url(getOption("repos"), "source"), collapse=","), lib.install)
 	rc <- system2(rscript, args)
 	rc
 }
@@ -749,7 +765,7 @@ is.fastr <- function() {
 }
 
 system.test <- function(pkgname) {
-	script <- normalizePath("com.oracle.truffle.r.test.cran/r/test.package.R")
+	script <- normalizePath("com.oracle.truffle.r.test.packages/r/test.package.R")
 	if (is.fastr()) {
 		rscript = file.path(R.home(), "bin", "Rscript")
 	} else {
@@ -779,8 +795,6 @@ parse.args <- function() {
 		a <- args[1L]
 		if (a %in% c("-h", "--help")) {
 			usage()
-		} else if (a == "--contriburl") {
-			contriburl <<- get.argvalue()
 		} else if (a == "--verbose" || a == "-v") {
 			verbose <<- T
 		} else if (a == "-V") {
@@ -800,6 +814,8 @@ parse.args <- function() {
 			blacklist.file <<- get.argvalue()
 		} else if (a == "--initial-blacklist-file") {
 			initial.blacklist.file <<- get.argvalue()
+		} else if (a == "--repos") {
+			repo.list <<- strsplit(get.argvalue(), ",")[[1]]
 		} else if (a == "--cran-mirror") {
 			cran.mirror <<- get.argvalue()
 		} else if (a == "--random") {
@@ -870,7 +886,6 @@ parse.args <- function() {
 cat.args <- function() {
 	if (verbose) {
 		cat("cran.mirror:", cran.mirror, "\n")
-		cat("contriburl:", contriburl, "\n")
 		cat("initial.blacklist.file:", initial.blacklist.file, "\n")
 		cat("blacklist.file:", blacklist.file, "\n")
 		cat("lib.install:", lib.install, "\n")
@@ -880,7 +895,6 @@ cat.args <- function() {
 		cat("create.blacklist.file:", create.blacklist.file, "\n")
 		cat("ignore.blacklist:", ignore.blacklist, "\n")
 		cat("pkg.pattern:", pkg.pattern, "\n")
-		cat("contriburl:", contriburl, "\n")
 		cat("random.count:", random.count, "\n")
 		cat("count.daily:", count.daily, "\n")
 		cat("run.mode:", run.mode, "\n")
@@ -925,7 +939,7 @@ run.setup <- function() {
 	parse.args()
 	check.libs()
 	check.pkgfilelist()
-	set.contriburl()
+	set.repos()
 	set.initial.package.blacklist()
 	set.package.blacklist()
 	lib.install <<- normalizePath(lib.install)
@@ -938,8 +952,8 @@ run <- function() {
 }
 
 quiet <- F
+repo.list <- c("CRAN")
 cran.mirror <- NA
-contriburl <- NA
 blacklist.file <- NA
 initial.blacklist.file <- NA
 lib.install <- NA
diff --git a/com.oracle.truffle.r.test.cran/r/test.package.R b/com.oracle.truffle.r.test.packages/r/test.package.R
similarity index 95%
rename from com.oracle.truffle.r.test.cran/r/test.package.R
rename to com.oracle.truffle.r.test.packages/r/test.package.R
index 9c24412015..40ceb1276e 100644
--- a/com.oracle.truffle.r.test.cran/r/test.package.R
+++ b/com.oracle.truffle.r.test.packages/r/test.package.R
@@ -21,7 +21,7 @@
 # questions.
 #
 
-# A script to do a single package test, called from install.cran.packages.R.
+# A script to do a single package test, called from install.packages.R.
 # It exists as a separate script only to avoid internal FastR errors from killing the
 # entire test process for multiple package tests.
 
diff --git a/com.oracle.truffle.r.test.cran/recommended b/com.oracle.truffle.r.test.packages/recommended
similarity index 100%
rename from com.oracle.truffle.r.test.cran/recommended
rename to com.oracle.truffle.r.test.packages/recommended
diff --git a/com.oracle.truffle.r.test.cran/top100 b/com.oracle.truffle.r.test.packages/top100
similarity index 100%
rename from com.oracle.truffle.r.test.cran/top100
rename to com.oracle.truffle.r.test.packages/top100
diff --git a/com.oracle.truffle.r.test.cran/top100test b/com.oracle.truffle.r.test.packages/top100test
similarity index 100%
rename from com.oracle.truffle.r.test.cran/top100test
rename to com.oracle.truffle.r.test.packages/top100test
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 735f194785..f918bad3c3 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
@@ -139275,1200 +139275,6 @@ non-integer value 12345678909876543212L qualified with L; using numeric value
 #'\ ' == ' '
 [1] TRUE
 
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.TestLENGTH#Output.MayIgnoreErrorContext#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.LENGTH(1)); x <- append(x, rffi.LENGTH(c(1,2,3))); x <- append(x, rffi.LENGTH(list(1,2,3))); x <- append(x, rffi.LENGTH(expression(1,2))); ; detach("package:testrffi", unload=T); x }
-[[1]]
-[1] 1
-
-[[2]]
-[1] 3
-
-[[3]]
-[1] 3
-
-[[4]]
-[1] 2
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testAsFunctions#Output.MayIgnoreWarningContext#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.asChar(1L)); x <- append(x, rffi.asInteger(1L)); x <- append(x, rffi.asReal(1L)); x <- append(x, rffi.asLogical(1L)); x <- append(x, rffi.asChar(2)); x <- append(x, rffi.asInteger(2)); x <- append(x, rffi.asReal(2)); x <- append(x, rffi.asLogical(2)); x <- append(x, rffi.asChar(2.2)); x <- append(x, rffi.asInteger(2.2)); x <- append(x, rffi.asReal(2.2)); x <- append(x, rffi.asLogical(2.2)); x <- append(x, rffi.asChar(T)); x <- append(x, rffi.asInteger(T)); x <- append(x, rffi.asReal(T)); x <- append(x, rffi.asLogical(T)); x <- append(x, rffi.asChar(integer())); x <- append(x, rffi.asInteger(integer())); x <- append(x, rffi.asReal(integer())); x <- append(x, rffi.asLogical(integer())); x <- append(x, rffi.asChar(numeric())); x <- append(x, rffi.asInteger(numeric())); x <- append(x, rffi.asReal(numeric())); x <- append(x, rffi.asLogical(numeric())); x <- append(x, rffi.asChar(logical())); x <- append(x, rffi.asInteger(logical())); x <- append(x, rffi.asReal(logical())); x <- append(x, rffi.asLogical(logical())); x <- append(x, rffi.asChar(character())); x <- append(x, rffi.asInteger(character())); x <- append(x, rffi.asReal(character())); x <- append(x, rffi.asLogical(character())); x <- append(x, rffi.asChar(c(5,6))); x <- append(x, rffi.asInteger(c(5,6))); x <- append(x, rffi.asReal(c(5,6))); x <- append(x, rffi.asLogical(c(5,6))); x <- append(x, rffi.asChar(c(2.3, 3.4))); x <- append(x, rffi.asInteger(c(2.3, 3.4))); x <- append(x, rffi.asReal(c(2.3, 3.4))); x <- append(x, rffi.asLogical(c(2.3, 3.4))); x <- append(x, rffi.asChar(c(T, F))); x <- append(x, rffi.asInteger(c(T, F))); x <- append(x, rffi.asReal(c(T, F))); x <- append(x, rffi.asLogical(c(T, F))); x <- append(x, rffi.asChar(as.symbol("sym"))); x <- append(x, rffi.asInteger(as.symbol("sym"))); x <- append(x, rffi.asReal(as.symbol("sym"))); x <- append(x, rffi.asLogical(as.symbol("sym"))); x <- append(x, rffi.asChar(list())); x <- append(x, rffi.asInteger(list())); x <- append(x, rffi.asReal(list())); x <- append(x, rffi.asLogical(list())); ; detach("package:testrffi", unload=T); x }
-[[1]]
-[1] "1"
-
-[[2]]
-[1] 1
-
-[[3]]
-[1] 1
-
-[[4]]
-[1] TRUE
-
-[[5]]
-[1] "2"
-
-[[6]]
-[1] 2
-
-[[7]]
-[1] 2
-
-[[8]]
-[1] TRUE
-
-[[9]]
-[1] "2.2"
-
-[[10]]
-[1] 2
-
-[[11]]
-[1] 2.2
-
-[[12]]
-[1] TRUE
-
-[[13]]
-[1] "TRUE"
-
-[[14]]
-[1] 1
-
-[[15]]
-[1] 1
-
-[[16]]
-[1] TRUE
-
-[[17]]
-[1] NA
-
-[[18]]
-[1] NA
-
-[[19]]
-[1] NA
-
-[[20]]
-[1] NA
-
-[[21]]
-[1] NA
-
-[[22]]
-[1] NA
-
-[[23]]
-[1] NA
-
-[[24]]
-[1] NA
-
-[[25]]
-[1] NA
-
-[[26]]
-[1] NA
-
-[[27]]
-[1] NA
-
-[[28]]
-[1] NA
-
-[[29]]
-[1] NA
-
-[[30]]
-[1] NA
-
-[[31]]
-[1] NA
-
-[[32]]
-[1] NA
-
-[[33]]
-[1] "5"
-
-[[34]]
-[1] 5
-
-[[35]]
-[1] 5
-
-[[36]]
-[1] TRUE
-
-[[37]]
-[1] "2.3"
-
-[[38]]
-[1] 2
-
-[[39]]
-[1] 2.3
-
-[[40]]
-[1] TRUE
-
-[[41]]
-[1] "TRUE"
-
-[[42]]
-[1] 1
-
-[[43]]
-[1] 1
-
-[[44]]
-[1] TRUE
-
-[[45]]
-[1] "sym"
-
-[[46]]
-[1] NA
-
-[[47]]
-[1] NA
-
-[[48]]
-[1] NA
-
-[[49]]
-[1] NA
-
-[[50]]
-[1] NA
-
-[[51]]
-[1] NA
-
-[[52]]
-[1] NA
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testListFunctions#Output.MayIgnoreErrorContext#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.CAR(pairlist(1,2))); x <- append(x, rffi.CDR(pairlist(1,2))); x <- append(x, rffi.CAR(pairlist(x=1L, y=2L))); x <- append(x, rffi.CDR(pairlist(x=1L, y=2L))); ; detach("package:testrffi", unload=T); x }
-[[1]]
-[1] 1
-
-[[2]]
-[1] 2
-
-[[3]]
-[1] 1
-
-$y
-[1] 2
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI1#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.addInt(2L, 3L); detach("package:testrffi", unload=T); x }
-[1] 5
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI10#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); a <- c(1L,2L,3L); x <- rffi.iterate_iptr(a); detach("package:testrffi", unload=T); x }
-[1] 1 2 3
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI11#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.dotCModifiedArguments(c(0,1,2,3)); detach("package:testrffi", unload=T); x }
-[[1]]
-[1] 4
-
-[[2]]
-[1] 1 2 3 4
-
-[[3]]
-[1] 0.0 0.2 0.4 0.6
-
-[[4]]
-[1]  TRUE FALSE FALSE FALSE
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI12#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi", unload=T); x }
-[[1]]
-[[1]][[1]]
-NULL
-
-[[1]][[2]]
-[1] 1
-
-
-[[2]]
-[[2]][[1]]
-NULL
-
-[[2]][[2]]
-[1] 3
-
-
-[[3]]
-[[3]][[1]]
-NULL
-
-[[3]][[2]]
-[1] 1
-
-
-[[4]]
-[[4]][[1]]
-NULL
-
-[[4]][[2]]
-[1] "a"
-
-
-[[5]]
-[[5]][[1]]
-NULL
-
-[[5]][[2]]
-[1] "b"
-
-
-[[6]]
-[[6]][[1]]
-NULL
-
-[[6]][[2]]
-[1] 1
-
-
-[[7]]
-[[7]][[1]]
-NULL
-
-[[7]][[2]]
-[1] 0c
-
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI13#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12)); detach("package:testrffi", unload=T); x }
-[[1]]
-[[1]][[1]]
-x
-
-[[1]][[2]]
-[1] 1
-
-
-[[2]]
-[[2]][[1]]
-NULL
-
-[[2]][[2]]
-[1] 3
-
-
-[[3]]
-[[3]][[1]]
-NULL
-
-[[3]][[2]]
-[1] 1
-
-
-[[4]]
-[[4]][[1]]
-y
-
-[[4]][[2]]
-[1] "a"
-
-
-[[5]]
-[[5]][[1]]
-NULL
-
-[[5]][[2]]
-[1] "b"
-
-
-[[6]]
-[[6]][[1]]
-NULL
-
-[[6]][[2]]
-[1] 1
-
-
-[[7]]
-[[7]][[1]]
-NULL
-
-[[7]][[2]]
-[1] 0c
-
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI14#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.invoke12(); detach("package:testrffi", unload=T); x }
-[1] 12
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI15#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.TYPEOF(3L); detach("package:testrffi", unload=T); x }
-[1] 13
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI16#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.isRString("hello"); detach("package:testrffi", unload=T); x }
-[1] TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI17#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.isRString(NULL); detach("package:testrffi", unload=T); x }
-[1] FALSE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI18#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.interactive(); detach("package:testrffi", unload=T); x }
-[1] FALSE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI19#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- 1; x <- rffi.findvar("x", globalenv()); detach("package:testrffi", unload=T); x }
-[1] 1
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI2#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.addDouble(2, 3); detach("package:testrffi", unload=T); x }
-[1] 5
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI20#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- "12345"; x <- rffi.char_length(x); detach("package:testrffi", unload=T); x }
-[1] 5
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI3#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.populateIntVector(5); detach("package:testrffi", unload=T); x }
-[1] 0 1 2 3 4
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI4#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.populateLogicalVector(5); detach("package:testrffi", unload=T); x }
-[1]  TRUE    NA FALSE FALSE FALSE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI5#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.mkStringFromChar(); detach("package:testrffi", unload=T); x }
-[1] "hello"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI6#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.mkStringFromBytes(); detach("package:testrffi", unload=T); x }
-[1] "hello"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI7#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.null(); detach("package:testrffi", unload=T); x }
-NULL
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI7C#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.null.C(); detach("package:testrffi", unload=T); x }
-NULL
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI7E#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.null.E(); detach("package:testrffi", unload=T); x }
-Error in .Call("null", PACKAGE = "foo") :
-  "null" not available for .Call() for package "foo"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI8#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.isRString(character(0)); detach("package:testrffi", unload=T); x }
-[1] TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI9#
-#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); a <- c(1L,2L,3L); x <- rffi.iterate_iarray(a); detach("package:testrffi", unload=T); x }
-[1] 1 2 3
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(1L, 0) :
-  cannot coerce type 'integer' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 1); detach('package:testrffi', unload=T); x }
-`1`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 10); detach('package:testrffi', unload=T); x }
-[1] TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 13); detach('package:testrffi', unload=T); x }
-[1] 1
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 14); detach('package:testrffi', unload=T); x }
-[1] 1
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 15); detach('package:testrffi', unload=T); x }
-[1] 1+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 16); detach('package:testrffi', unload=T); x }
-[1] "1"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] 1
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(1L, 24); detach('package:testrffi', unload=T); x }
-[1] 01
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(2, 0) :
-  cannot coerce type 'double' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 1); detach('package:testrffi', unload=T); x }
-`2`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 10); detach('package:testrffi', unload=T); x }
-[1] TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 13); detach('package:testrffi', unload=T); x }
-[1] 2
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 14); detach('package:testrffi', unload=T); x }
-[1] 2
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 15); detach('package:testrffi', unload=T); x }
-[1] 2+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 16); detach('package:testrffi', unload=T); x }
-[1] "2"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] 2
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 24); detach('package:testrffi', unload=T); x }
-[1] 02
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(2.2, 0) :
-  cannot coerce type 'double' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 1); detach('package:testrffi', unload=T); x }
-`2.2`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 10); detach('package:testrffi', unload=T); x }
-[1] TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 13); detach('package:testrffi', unload=T); x }
-[1] 2
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 14); detach('package:testrffi', unload=T); x }
-[1] 2.2
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 15); detach('package:testrffi', unload=T); x }
-[1] 2.2+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 16); detach('package:testrffi', unload=T); x }
-[1] "2.2"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] 2.2
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 24); detach('package:testrffi', unload=T); x }
-[1] 02
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(T, 0) :
-  cannot coerce type 'logical' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 1); detach('package:testrffi', unload=T); x }
-`TRUE`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 10); detach('package:testrffi', unload=T); x }
-[1] TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 13); detach('package:testrffi', unload=T); x }
-[1] 1
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 14); detach('package:testrffi', unload=T); x }
-[1] 1
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 15); detach('package:testrffi', unload=T); x }
-[1] 1+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 16); detach('package:testrffi', unload=T); x }
-[1] "TRUE"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] TRUE
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 24); detach('package:testrffi', unload=T); x }
-[1] 01
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(c(2.3, 3.4), 0) :
-  cannot coerce type 'double' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 1); detach('package:testrffi', unload=T); x }
-`2.3`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 10); detach('package:testrffi', unload=T); x }
-[1] TRUE TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 13); detach('package:testrffi', unload=T); x }
-[1] 2 3
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 14); detach('package:testrffi', unload=T); x }
-[1] 2.3 3.4
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 15); detach('package:testrffi', unload=T); x }
-[1] 2.3+0i 3.4+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 16); detach('package:testrffi', unload=T); x }
-[1] "2.3" "3.4"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] 2.3
-
-[[2]]
-[1] 3.4
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 24); detach('package:testrffi', unload=T); x }
-[1] 02 03
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(c(5, 6), 0) :
-  cannot coerce type 'double' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 1); detach('package:testrffi', unload=T); x }
-`5`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 10); detach('package:testrffi', unload=T); x }
-[1] TRUE TRUE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 13); detach('package:testrffi', unload=T); x }
-[1] 5 6
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 14); detach('package:testrffi', unload=T); x }
-[1] 5 6
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 15); detach('package:testrffi', unload=T); x }
-[1] 5+0i 6+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 16); detach('package:testrffi', unload=T); x }
-[1] "5" "6"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] 5
-
-[[2]]
-[1] 6
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 24); detach('package:testrffi', unload=T); x }
-[1] 05 06
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(c(T, F), 0) :
-  cannot coerce type 'logical' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 1); detach('package:testrffi', unload=T); x }
-`TRUE`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 10); detach('package:testrffi', unload=T); x }
-[1]  TRUE FALSE
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 13); detach('package:testrffi', unload=T); x }
-[1] 1 0
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 14); detach('package:testrffi', unload=T); x }
-[1] 1 0
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 15); detach('package:testrffi', unload=T); x }
-[1] 1+0i 0+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 16); detach('package:testrffi', unload=T); x }
-[1] "TRUE"  "FALSE"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 19); detach('package:testrffi', unload=T); x }
-[[1]]
-[1] TRUE
-
-[[2]]
-[1] FALSE
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 24); detach('package:testrffi', unload=T); x }
-[1] 01 00
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(character(), 0) :
-  cannot coerce type 'character' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 1); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(character(), 1) :
-  invalid data of mode 'character' (too short)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 10); detach('package:testrffi', unload=T); x }
-logical(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 13); detach('package:testrffi', unload=T); x }
-integer(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 14); detach('package:testrffi', unload=T); x }
-numeric(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 15); detach('package:testrffi', unload=T); x }
-complex(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 16); detach('package:testrffi', unload=T); x }
-character(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 19); detach('package:testrffi', unload=T); x }
-list()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 24); detach('package:testrffi', unload=T); x }
-raw(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(integer(), 0) :
-  cannot coerce type 'integer' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 1); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(integer(), 1) :
-  invalid data of mode 'integer' (too short)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 10); detach('package:testrffi', unload=T); x }
-logical(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 13); detach('package:testrffi', unload=T); x }
-integer(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 14); detach('package:testrffi', unload=T); x }
-numeric(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 15); detach('package:testrffi', unload=T); x }
-complex(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 16); detach('package:testrffi', unload=T); x }
-character(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 19); detach('package:testrffi', unload=T); x }
-list()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 24); detach('package:testrffi', unload=T); x }
-raw(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(list(), 0) :
-  unimplemented type 'list' in 'coerceVectorList'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 1); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(list(), 1) :
-  invalid type/length (symbol/0) in vector allocation
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 10); detach('package:testrffi', unload=T); x }
-logical(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 13); detach('package:testrffi', unload=T); x }
-integer(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 14); detach('package:testrffi', unload=T); x }
-numeric(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 15); detach('package:testrffi', unload=T); x }
-complex(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 16); detach('package:testrffi', unload=T); x }
-character(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 19); detach('package:testrffi', unload=T); x }
-list()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 24); detach('package:testrffi', unload=T); x }
-raw(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(logical(), 0) :
-  cannot coerce type 'logical' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 1); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(logical(), 1) :
-  invalid data of mode 'logical' (too short)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 10); detach('package:testrffi', unload=T); x }
-logical(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 13); detach('package:testrffi', unload=T); x }
-integer(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 14); detach('package:testrffi', unload=T); x }
-numeric(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 15); detach('package:testrffi', unload=T); x }
-complex(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 16); detach('package:testrffi', unload=T); x }
-character(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 19); detach('package:testrffi', unload=T); x }
-list()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 24); detach('package:testrffi', unload=T); x }
-raw(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(numeric(), 0) :
-  cannot coerce type 'double' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 1); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(numeric(), 1) :
-  invalid data of mode 'double' (too short)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 10); detach('package:testrffi', unload=T); x }
-logical(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 13); detach('package:testrffi', unload=T); x }
-integer(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 14); detach('package:testrffi', unload=T); x }
-numeric(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 15); detach('package:testrffi', unload=T); x }
-complex(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 16); detach('package:testrffi', unload=T); x }
-character(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 19); detach('package:testrffi', unload=T); x }
-list()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 24); detach('package:testrffi', unload=T); x }
-raw(0)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(structure(1L, names = "a", dim = c(1, 1), myattr = "q"),  :
-  cannot coerce type 'integer' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 1); detach('package:testrffi', unload=T); x }
-`1`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 10); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] TRUE
-attr(,"names")
-[1] "a"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 13); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]    1
-attr(,"names")
-[1] "a"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 14); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]    1
-attr(,"names")
-[1] "a"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 15); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] 1+0i
-attr(,"names")
-[1] "a"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 16); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] "1"
-attr(,"names")
-[1] "a"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 19); detach('package:testrffi', unload=T); x }
-$a
-[1] 1
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(1L,names='a',dim=c(1,1),myattr='q'), 24); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]   01
-attr(,"names")
-[1] "a"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(structure(2.2, names = "b", dim = c(1, 1),  :
-  cannot coerce type 'double' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 1); detach('package:testrffi', unload=T); x }
-`2.2`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 10); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] TRUE
-attr(,"names")
-[1] "b"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 13); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]    2
-attr(,"names")
-[1] "b"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 14); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]  2.2
-attr(,"names")
-[1] "b"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 15); detach('package:testrffi', unload=T); x }
-       [,1]
-[1,] 2.2+0i
-attr(,"names")
-[1] "b"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 16); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] "2.2"
-attr(,"names")
-[1] "b"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 19); detach('package:testrffi', unload=T); x }
-$b
-[1] 2.2
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 24); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]   02
-attr(,"names")
-[1] "b"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(structure(T, names = "c", dim = c(1, 1), myattr = "q"),  :
-  cannot coerce type 'logical' to vector of type 'NULL'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 1); detach('package:testrffi', unload=T); x }
-`TRUE`
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 10); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] TRUE
-attr(,"names")
-[1] "c"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 13); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]    1
-attr(,"names")
-[1] "c"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 14); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]    1
-attr(,"names")
-[1] "c"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 15); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] 1+0i
-attr(,"names")
-[1] "c"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 16); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] "TRUE"
-attr(,"names")
-[1] "c"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 19); detach('package:testrffi', unload=T); x }
-$c
-[1] TRUE
-
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 24); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,]   01
-attr(,"names")
-[1] "c"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 0); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(structure(list(1, "42"), names = c("q", "w"),  :
-  unimplemented type 'list' in 'coerceVectorList'
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 1); detach('package:testrffi', unload=T); x }
-Error in rffi.coerceVector(structure(list(1, "42"), names = c("q", "w"),  :
-  invalid type/length (symbol/2) in vector allocation
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 10); detach('package:testrffi', unload=T); x }
-   q    w
-TRUE   NA
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 13); detach('package:testrffi', unload=T); x }
- q  w
- 1 42
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 14); detach('package:testrffi', unload=T); x }
- q  w
- 1 42
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 15); detach('package:testrffi', unload=T); x }
-    q     w
- 1+0i 42+0i
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 16); detach('package:testrffi', unload=T); x }
-   q    w
- "1" "42"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 19); detach('package:testrffi', unload=T); x }
-     [,1]
-[1,] 1
-[2,] "42"
-attr(,"names")
-[1] "q" "w"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVector#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q'), 24); detach('package:testrffi', unload=T); x }
- q  w
-01 2a
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2, 20); detach('package:testrffi', unload=T); x }
-expression(2)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(2.2, 20); detach('package:testrffi', unload=T); x }
-expression(2.2)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(T, 20); detach('package:testrffi', unload=T); x }
-expression(TRUE)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(2.3, 3.4), 20); detach('package:testrffi', unload=T); x }
-expression(2.3, 3.4)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(5,6), 20); detach('package:testrffi', unload=T); x }
-expression(5, 6)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(c(T, F), 20); detach('package:testrffi', unload=T); x }
-expression(TRUE, FALSE)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(character(), 20); detach('package:testrffi', unload=T); x }
-expression()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(integer(), 20); detach('package:testrffi', unload=T); x }
-expression()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(list(), 20); detach('package:testrffi', unload=T); x }
-expression()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(logical(), 20); detach('package:testrffi', unload=T); x }
-expression()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(numeric(), 20); detach('package:testrffi', unload=T); x }
-expression()
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(2.2, names='b',dim=c(1,1),myattr='q'), 20); detach('package:testrffi', unload=T); x }
-expression(2.2)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Output.IgnoreErrorMessage#Output.MayIgnoreWarningContext#Output.MayIgnoreErrorContext#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(T, names='c',dim=c(1,1),myattr='q'), 20); detach('package:testrffi', unload=T); x }
-expression(TRUE)
-
-##com.oracle.truffle.r.test.rffi.TestRFFIPackageCoercions.testCoerceVectorToExpression#Ignored.Unimplemented#
-#{ library('testrffi', lib.loc = 'tmptest/com.oracle.truffle.r.test.rpackages'); x <- rffi.coerceVector(structure(list(1,'x'), names=c('q','w'),dim=c(2,1),myattr='q'), 20); detach('package:testrffi', unload=T); x }
-expression(q = 1, w = "x")
-attr(,"names")
-[1] "q" "w"
-attr(,"myattr")
-[1] "q"
-
-##com.oracle.truffle.r.test.rffi.TestUserRNG.testUserRNG#
-#{ dyn.load("com.oracle.truffle.r.test.native/urand/lib/liburand.so"); RNGkind("user"); print(RNGkind()); set.seed(4567); runif(10) }
-[1] "user-supplied" "Inversion"
- [1] 0.45336386 0.38848030 0.94576608 0.11726267 0.21542351 0.08672997
- [7] 0.35201276 0.16919220 0.93579263 0.26084486
-
 ##com.oracle.truffle.r.test.rng.TestRRNG.testDirectReadingSeed#
 #invisible(runif(1)); length(.Random.seed)
 [1] 626
@@ -140605,92 +139411,3 @@ In runif(3) :
 #invisible(runif(5)); RNGkind('Marsaglia-Multicarry'); set.seed(2); runif(5);
 [1] 0.8431527 0.5749091 0.1531976 0.3460321 0.2313936
 
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(KernSmooth, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:KernSmooth"); }
-KernSmooth 2.23 loaded
-Copyright M. P. Wand 1997-2009
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(MASS, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:MASS"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(Matrix, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:Matrix"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(boot, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:boot"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(class, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:class"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(cluster, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:cluster"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(codetools, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:codetools"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(foreign, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:foreign"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(lattice, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:lattice"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(nlme, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:nlme"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(nnet, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:nnet"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(rpart, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:rpart"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(spatial, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:spatial"); }
-
-##com.oracle.truffle.r.test.rpackages.TestRecommendedPackages.testLoad#Ignored.OutputFormatting#Context.NonShared#Context.LongTimeout#
-#{ library(survival, lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:survival"); }
-
-##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute#
-#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Car"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r }
-Looking for rust
-Checking seat belts
-NULL
-NULL
-
-##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute#
-#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Car"), new("StateInspector"))); detach("package:tests4"); unloadNamespace("tests4"); r }
-Looking for rust
-Checking seat belts
-Checking insurance
-NULL
-NULL
-
-##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute#
-#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Truck"), new("Inspector"))); detach("package:tests4"); unloadNamespace("tests4"); r }
-Looking for rust
-Checking cargo attachments
-NULL
-NULL
-
-##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Execute#
-#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-print(tests4:::inspect.vehicle(new("Truck"), new("StateInspector"))); detach("package:tests4"); unloadNamespace("tests4"); r }
-Looking for rust
-Checking cargo attachments
-NULL
-NULL
-
-##com.oracle.truffle.r.test.rpackages.TestS4TestPackage.testS4Load#
-#{ library("tests4", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); detach("package:tests4"); unloadNamespace("tests4") }
-
-##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testLoadVanilla#
-#{ library("vanilla", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r <- vanilla(); detach("package:vanilla"); r }
-[1] "A vanilla R package"
-[1] "A vanilla R package"
-
-##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testQualifiedReplacement#
-#{ library("vanilla", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r<-42; vanilla::foo(r)<-7; detach("package:vanilla"); r }
-[1] 7
-
-##com.oracle.truffle.r.test.rpackages.TestVanillaPackage.testSimpleFunction#
-#{ library("vanilla", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); r <- functionTest(c(1,2,3,4,5,6),8:10); detach("package:vanilla"); r }
-[1]  2  3  4  5  6  7  8  9 10
-
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
deleted file mode 100644
index 58fc5690fd..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.rffi;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-import com.oracle.truffle.r.test.TestTrait;
-import com.oracle.truffle.r.test.rpackages.TestRPackages;
-
-public class TestRFFIPackage extends TestRPackages {
-
-    private static final String[] TEST_PACKAGES = new String[]{"testrffi"};
-
-    @BeforeClass
-    public static void setupInstallMyTestPackages() {
-        setupInstallTestPackages(TEST_PACKAGES);
-    }
-
-    @AfterClass
-    public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages();
-    }
-
-    /**
-     * This is somewhat expensive to do per test, but the only alternative is to put all the
-     * micro-tests in one big test. It might be that this should be switched to an R file-based
-     * approach as the number of tests increase.
-     */
-    private void assertEvalWithLibWithSetupAndTrait(TestTrait trait, String setup, String test) {
-        String[] tests = TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); " + setup + "x <- " + test + "; detach(\"package:testrffi\", unload=T); x }",
-                        new String[]{TestRPackages.libLoc()});
-        if (trait == null) {
-            assertEval(tests);
-        } else {
-            assertEval(trait, tests);
-        }
-    }
-
-    private void assertEvalWithLib(String test) {
-        assertEvalWithLibWithSetupAndTrait(null, "", test);
-    }
-
-    private void assertEvalWithLibWithSetup(String setup, String test) {
-        assertEvalWithLibWithSetupAndTrait(null, setup, test);
-    }
-
-    @Test
-    public void testRFFI1() {
-        assertEvalWithLib("rffi.addInt(2L, 3L)");
-    }
-
-    @Test
-    public void testRFFI2() {
-        assertEvalWithLib("rffi.addDouble(2, 3)");
-    }
-
-    @Test
-    public void testRFFI3() {
-        assertEvalWithLib("rffi.populateIntVector(5)");
-    }
-
-    @Test
-    public void testRFFI4() {
-        assertEvalWithLib("rffi.populateLogicalVector(5)");
-    }
-
-    @Test
-    public void testRFFI5() {
-        assertEvalWithLib("rffi.mkStringFromChar()");
-    }
-
-    @Test
-    public void testRFFI6() {
-        assertEvalWithLib("rffi.mkStringFromBytes()");
-    }
-
-    @Test
-    public void testRFFI7() {
-        assertEvalWithLib("rffi.null()");
-    }
-
-    @Test
-    public void testRFFI7E() {
-        assertEvalWithLib("rffi.null.E()");
-    }
-
-    @Test
-    public void testRFFI7C() {
-        assertEvalWithLib("rffi.null.C()");
-    }
-
-    @Test
-    public void testRFFI8() {
-        assertEvalWithLib("rffi.isRString(character(0))");
-    }
-
-    @Test
-    public void testRFFI9() {
-        assertEvalWithLibWithSetup("a <- c(1L,2L,3L); ", "rffi.iterate_iarray(a)");
-    }
-
-    @Test
-    public void testRFFI10() {
-        assertEvalWithLibWithSetup("a <- c(1L,2L,3L); ", "rffi.iterate_iptr(a)");
-    }
-
-    @Test
-    public void testRFFI11() {
-        assertEvalWithLib("rffi.dotCModifiedArguments(c(0,1,2,3))");
-    }
-
-    @Test
-    public void testRFFI12() {
-        assertEvalWithLib("rffi.dotExternalAccessArgs(1L, 3, c(1,2,3), c('a', 'b'), 'b', TRUE, as.raw(12))");
-    }
-
-    @Test
-    public void testRFFI13() {
-        assertEvalWithLib("rffi.dotExternalAccessArgs(x=1L, 3, c(1,2,3), y=c('a', 'b'), 'b', TRUE, as.raw(12))");
-    }
-
-    @Test
-    public void testRFFI14() {
-        assertEvalWithLib("rffi.invoke12()");
-    }
-
-    @Test
-    public void testRFFI15() {
-        assertEvalWithLib("rffi.TYPEOF(3L)");
-    }
-
-    @Test
-    public void testRFFI16() {
-        assertEvalWithLib("rffi.isRString(\"hello\")");
-    }
-
-    @Test
-    public void testRFFI17() {
-        assertEvalWithLib("rffi.isRString(NULL)");
-    }
-
-    @Test
-    public void testRFFI18() {
-        assertEvalWithLib("rffi.interactive()");
-    }
-
-    @Test
-    public void testRFFI19() {
-        assertEvalWithLibWithSetup("x <- 1; ", "rffi.findvar(\"x\", globalenv())");
-    }
-
-    @Test
-    public void testRFFI20() {
-        assertEvalWithLibWithSetup("x <- \"12345\"; ", "rffi.char_length(x)");
-    }
-
-    private static final String[] AS_VALUES = new String[]{"1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)",
-                    "as.symbol(\"sym\")", "list()"};
-
-    private static final String[] AS_FUNS = new String[]{"Char", "Integer", "Real", "Logical"};
-
-    @Test
-    public void testAsFunctions() {
-        String[] asCalls = template("x <- append(x, rffi.as%0(%1)); ", AS_FUNS, AS_VALUES);
-        assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreWarningContext, "x <- list(); ", flatten(asCalls));
-    }
-
-    private static final String[] LIST_FUNS = new String[]{"CAR", "CDR"};
-
-    private static final String[] LIST_VALUES = new String[]{"pairlist(1,2)", "pairlist(x=1L, y=2L)"};
-
-    @Test
-    public void testListFunctions() {
-        String[] calls = template("x <- append(x, rffi.%0(%1)); ", LIST_FUNS, LIST_VALUES);
-        assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls));
-
-    }
-
-    private static String flatten(String[] tests) {
-        StringBuilder sb = new StringBuilder();
-        for (String test : tests) {
-            sb.append(test);
-        }
-        return sb.toString();
-    }
-
-    private static final String[] LENGTH_VALUES = new String[]{"1", "c(1,2,3)", "list(1,2,3)", "expression(1,2)"};
-
-    // Checkstyle: stop method name check
-    @Test
-    public void TestLENGTH() {
-        String[] calls = template("x <- append(x, rffi.LENGTH(%0)); ", LENGTH_VALUES);
-        assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls));
-    }
-
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java
deleted file mode 100644
index 12c06a7162..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackageCoercions.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.rffi;
-
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.CPLXSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.EXPRSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.INTSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.LGLSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.NILSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.RAWSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.REALSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.STRSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.SYMSXP;
-import static com.oracle.truffle.r.runtime.gnur.SEXPTYPE.VECSXP;
-
-import java.util.Arrays;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
-import com.oracle.truffle.r.test.rpackages.TestRPackages;
-
-public class TestRFFIPackageCoercions extends TestRPackages {
-
-    private static final String[] TEST_PACKAGES = new String[]{"testrffi"};
-
-    @BeforeClass
-    public static void setupInstallMyTestPackages() {
-        setupInstallTestPackages(TEST_PACKAGES);
-    }
-
-    @AfterClass
-    public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages();
-    }
-
-    private static String addLib(String test) {
-        return "{ library('testrffi', lib.loc = '" + TestRPackages.libLoc() + "'); x <- " + test + "; detach('package:testrffi', unload=T); x }";
-    }
-
-    private static final String[] COERCION_VALUES_FOR_EXPR = new String[]{
-                    "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)",
-                    "list()", "structure(2.2, names='b',dim=c(1,1),myattr='q')", "structure(T, names='c',dim=c(1,1),myattr='q')"};
-
-    private static final String[] COERCION_VALUES = new String[]{
-                    "1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)",
-                    "c(T, F)", "list()", "structure(1L,names='a',dim=c(1,1),myattr='q')", "structure(2.2, names='b',dim=c(1,1),myattr='q')",
-                    "structure(T, names='c',dim=c(1,1),myattr='q')", "structure(list(1,'42'), names=c('q','w'),dim=c(2,1),myattr='q')"};
-
-    private static final SEXPTYPE[] COERCION_TYPES = new SEXPTYPE[]{SYMSXP, NILSXP, VECSXP, INTSXP, REALSXP, LGLSXP, STRSXP, CPLXSXP, RAWSXP};
-
-    private static final String[] COERCION_MODES = Arrays.stream(COERCION_TYPES).map(x -> Integer.toString(x.code)).toArray(n -> new String[n]);
-
-    @Test
-    public void testCoerceVector() {
-        String[] tests = template(addLib("rffi.coerceVector(%0, %1)"), COERCION_VALUES, COERCION_MODES);
-        assertEval(Output.MayIgnoreWarningContext, Output.MayIgnoreErrorContext, tests);
-    }
-
-    @Test
-    public void testCoerceVectorToExpression() {
-        // Note: inconsistency when printing expression(1L) FastR prints just "expression(1)"
-        String[] tests = template(addLib("rffi.coerceVector(%0, %1)"), COERCION_VALUES_FOR_EXPR, new String[]{Integer.toString(EXPRSXP.code)});
-        assertEval(Output.IgnoreErrorMessage, Output.MayIgnoreWarningContext, Output.MayIgnoreErrorContext, tests);
-        // removes the attributes when its single value, but keeps them when it's a list
-        assertEval(Ignored.Unimplemented, addLib("rffi.coerceVector(structure(list(1,'x'), names=c('q','w'),dim=c(2,1),myattr='q'), " + EXPRSXP.code + ")"));
-    }
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
deleted file mode 100644
index 40e4f8d269..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.rpackages;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Assert;
-
-import com.oracle.truffle.r.runtime.REnvVars;
-import com.oracle.truffle.r.runtime.RVersionNumber;
-import com.oracle.truffle.r.test.TestBase;
-
-/**
- * Tests related to the loading, etc. of R packages.
- *
- * THis class should be subclassed by a test that wishes to install one or more packages and
- * possibly run additional tests after installation using a pattern of the form
- * {@code library(pkg, lib.loc="%0"); sometest()}. Note the use of the {@code %0}, which must be
- * satisfied by passing the value of {@code libLoc()}. This is required because the test VM is not
- * aware of the test install location so it must be explicitly specified. The use of the {@code %0}
- * parameter mechanism also requires the use of {@link TestBase#template} in the test itself.
- *
- * A subclass must provide {@code @BeforeClass} and {@code @AfterClass}methods that call
- * {@link #setupInstallTestPackages} and {@link #tearDownUninstallTestPackages}, respectively, to
- * install/remove the specific set of packages relevant to the test.
- *
- * N.B. The same directory is used when generating expected output with GnuR, and running FastR, to
- * keep the {@code lib_loc} argument the same in the test string. So the install is destructive, but
- * ok as there is never a clash.
- *
- * The install directory is cleaned on every call to {@link #setupInstallTestPackages} in case a
- * previous install failed to complete {@link #tearDownUninstallTestPackages} successfully.
- */
-public abstract class TestRPackages extends TestBase {
-
-    private static final String SYSTEM2_COMMAND = "system2('%s', c('CMD', 'INSTALL', '%s'), env='R_LIBS=%s', stdout=T, stderr=T)";
-
-    private static String[] installedPackages;
-    private static Resolver resolver;
-    private static boolean needsInstall;
-
-    private static final class PackagePath {
-        /**
-         * The path containing the package distributions as tar files.
-         */
-        private final Path path;
-
-        private PackagePath(Path path) {
-            this.path = path;
-        }
-    }
-
-    /**
-     * The path to the install directory. This is fixed across all tests.
-     */
-    private static Path installDir;
-
-    /**
-     * Map from package name to info on its location.
-     */
-    private static final Map<String, PackagePath> packageMap = new HashMap<>();
-
-    private static Path installDir() {
-        if (installDir == null) {
-            installDir = TestBase.createTestDir("com.oracle.truffle.r.test.rpackages");
-        }
-        return installDir;
-    }
-
-    protected static String libLoc() {
-        return installDir().toString();
-    }
-
-    private static boolean uninstallPackage(String packageName) {
-        Path packageDir = installDir().resolve(packageName);
-        try {
-            deleteDir(packageDir);
-        } catch (Throwable e) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Pass a custom subclass of this class to override the actual location of the package tar file.
-     */
-    protected static class Resolver {
-        Path getPath(String p) {
-            return testNativePath().resolve(p).resolve("lib").resolve(p + ".tar");
-        }
-    }
-
-    private static Path testNativePath() {
-        Path p = TestBase.getNativeProjectFile(Paths.get("packages"));
-        return p;
-    }
-
-    private static PackagePath getPackagePaths(String pkg, Path path) {
-        PackagePath result = packageMap.get(pkg);
-        if (result == null) {
-            result = new PackagePath(path);
-            packageMap.put(pkg, result);
-        }
-        return result;
-    }
-
-    private static boolean installPackage(PackagePath packagePath) {
-        String cmd;
-        Path binBase;
-        if (generatingExpected()) {
-            // use GnuR (internal)
-            binBase = Paths.get(REnvVars.rHome(), "com.oracle.truffle.r.native", "gnur", RVersionNumber.R_HYPHEN_FULL);
-        } else {
-            // use FastR
-            binBase = Paths.get(REnvVars.rHome());
-        }
-        cmd = binBase.resolve("bin").resolve("R").toString();
-        try {
-            String result = evalInstallPackage(String.format(SYSTEM2_COMMAND, cmd, packagePath.path.toString(), installDir().toString()));
-            boolean success = result.contains("* DONE (");
-            if (!success) {
-                System.out.println(result);
-            }
-            return success;
-        } catch (Throwable t) {
-            t.printStackTrace();
-            return false;
-        }
-    }
-
-    protected static void setupInstallTestPackages(String[] testPackages) {
-        setupInstallTestPackages(testPackages, new Resolver());
-    }
-
-    protected static void setupInstallTestPackages(String[] testPackages, Resolver resolver) {
-        if (!checkOnly()) {
-            assert installedPackages == null && TestRPackages.resolver == null : "inconsistent calls to setupInstallTestPackages / tearDownUninstallTestPackages " + installedPackages + " " + resolver;
-            TestRPackages.installedPackages = testPackages;
-            TestRPackages.resolver = resolver;
-            TestRPackages.needsInstall = true;
-        }
-    }
-
-    private boolean packagesInstallSuccess = true;
-
-    @Override
-    public void beforeEval() {
-        if (needsInstall) {
-            needsInstall = false;
-
-            TestBase.deleteDir(installDir());
-            installDir().toFile().mkdirs();
-            System.out.printf(".begin install.");
-            for (String p : installedPackages) {
-                // Takes time, provide user feedback
-                System.out.printf(".pkg: %s.", p);
-                PackagePath packagePath = getPackagePaths(p, resolver.getPath(p));
-                if (!installPackage(packagePath)) {
-                    packagesInstallSuccess = false;
-                    Assert.fail(String.format("package %s failed to install", p));
-                }
-            }
-            System.out.printf(".end install.");
-        }
-        // This makes sure that any consequent tests fail with informative error
-        Assert.assertTrue("Error during package installation process.", packagesInstallSuccess);
-    }
-
-    protected static void tearDownUninstallTestPackages() {
-        if (!checkOnly()) {
-            assert installedPackages != null && resolver != null : "inconsistent calls to setupInstallTestPackages / tearDownUninstallTestPackages";
-            if (!needsInstall) {
-                for (String p : installedPackages) {
-                    if (!uninstallPackage(p)) {
-                        System.err.println("WARNING: error deleting package: " + p);
-                    }
-                }
-            }
-            installedPackages = null;
-            resolver = null;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java
deleted file mode 100644
index 04ab1ce911..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRecommendedPackages.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.rpackages;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-/**
- * Test the installation of the "recommended" packages that come with GnuR. N.B. There are no
- * specific tests beyond install/load as that is handled separately in the package testing
- * framework. We are primarily concerned with detecting installation regressions.
- *
- * N.B. The package 'tgz' files have been copied to the com.oracle.truffle.r.test project output
- * directory by the com.oracle.truffle.r.test.native Makefile. to allow them to be packaged into a
- * distribution and avoid any dependency on source paths.
- *
- */
-public class TestRecommendedPackages extends TestRPackages {
-    // order matters due to dependencies
-    private static final String[] DEFAULT_PACKAGES = new String[]{"codetools", "MASS", "boot", "class", "cluster",
-                    "lattice", "nnet", "spatial", "Matrix", "survival", "KernSmooth", "foreign", "nlme",
-                    "rpart"};
-    private static String[] packages = DEFAULT_PACKAGES;
-
-    /**
-     * Allows an external agent to ignore certain packages that are known to fail.
-     */
-    public static void ignorePackages(String[] ignoredPackages) {
-        String[] testPackages = new String[DEFAULT_PACKAGES.length - ignoredPackages.length];
-        int k = 0;
-        outer: for (int i = 0; i < DEFAULT_PACKAGES.length; i++) {
-            for (int j = 0; j < ignoredPackages.length; j++) {
-                if (DEFAULT_PACKAGES[i].equals(ignoredPackages[j])) {
-                    continue outer;
-                }
-            }
-            testPackages[k] = DEFAULT_PACKAGES[i];
-            k++;
-        }
-        packages = testPackages;
-    }
-
-    @BeforeClass
-    public static void setupInstallMyTestPackages() {
-        setupInstallTestPackages(packages, new Resolver() {
-            @Override
-            Path getPath(String p) {
-                return TestBase.getNativeProjectFile(Paths.get("packages")).resolve("recommended").resolve(p + ".tgz");
-            }
-        });
-    }
-
-    @AfterClass
-    public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages();
-    }
-
-    @Test
-    public void testLoad() {
-        // This is perhaps redundant as package installation tests whether the package will load.
-        assertEval(Ignored.OutputFormatting, Context.NonShared, Context.LongTimeout,
-                        TestBase.template("{ library(%1, lib.loc = \"%0\"); detach(\"package:%1\"); }", new String[]{TestRPackages.libLoc()}, packages));
-    }
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java
deleted file mode 100644
index 5843ad45da..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestS4TestPackage.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.rpackages;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-/**
- * Tests related to the loading, etc. of R packages.
- */
-public class TestS4TestPackage extends TestRPackages {
-
-    private static final String[] TEST_PACKAGES = new String[]{"tests4"};
-
-    @BeforeClass
-    public static void setupInstallMyTestPackages() {
-        setupInstallTestPackages(TEST_PACKAGES);
-    }
-
-    @AfterClass
-    public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages();
-    }
-
-    @Test
-    public void testS4Load() {
-        assertEval(TestBase.template("{ library(\"tests4\", lib.loc = \"%0\"); detach(\"package:tests4\"); unloadNamespace(\"tests4\") }",
-                        new String[]{TestRPackages.libLoc()}));
-    }
-
-    @Test
-    public void testS4Execute() {
-        assertEval(TestBase.template(
-                        "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Car\"), new(\"Inspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }",
-                        new String[]{TestRPackages.libLoc()}));
-        assertEval(TestBase.template(
-                        "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Truck\"), new(\"Inspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }",
-                        new String[]{TestRPackages.libLoc()}));
-        assertEval(TestBase.template(
-                        "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Car\"), new(\"StateInspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }",
-                        new String[]{TestRPackages.libLoc()}));
-        assertEval(TestBase.template(
-                        "{ library(\"tests4\", lib.loc = \"%0\"); r<-print(tests4:::inspect.vehicle(new(\"Truck\"), new(\"StateInspector\"))); detach(\"package:tests4\"); unloadNamespace(\"tests4\"); r }",
-                        new String[]{TestRPackages.libLoc()}));
-    }
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java
deleted file mode 100644
index 637377fa32..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestVanillaPackage.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.rpackages;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-/**
- * Tests related to the loading, etc. of R packages.
- */
-public class TestVanillaPackage extends TestRPackages {
-
-    private static final String[] TEST_PACKAGES = new String[]{"vanilla"};
-
-    @BeforeClass
-    public static void setupInstallMyTestPackages() {
-        setupInstallTestPackages(TEST_PACKAGES);
-    }
-
-    @AfterClass
-    public static void tearDownUninstallMyTestPackages() {
-        tearDownUninstallTestPackages();
-    }
-
-    @Test
-    public void testLoadVanilla() {
-        assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- vanilla(); detach(\"package:vanilla\"); r }", new String[]{TestRPackages.libLoc()}));
-    }
-
-    @Test
-    public void testSimpleFunction() {
-        assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r <- functionTest(c(1,2,3,4,5,6),8:10); detach(\"package:vanilla\"); r }",
-                        new String[]{TestRPackages.libLoc()}));
-    }
-
-    @Test
-    public void testQualifiedReplacement() {
-        assertEval(TestBase.template("{ library(\"vanilla\", lib.loc = \"%0\"); r<-42; vanilla::foo(r)<-7; detach(\"package:vanilla\"); r }", new String[]{TestRPackages.libLoc()}));
-    }
-}
diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index a3a1bf75f1..0e6ed21eab 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -10,8 +10,7 @@ The unit testing works by executing the R test and the comparing the output with
 The unit tests reside mainly in the `com.oracle.truffle.r.test` project, with a smaller number in the and `com.oracle.truffle.r.nodes.test` project. To execute the unit tests use the `mx junit` command. The standard set of unit tests is available via the `mx junitdefault` command and the following additional variants are available:
 
 1. `mx junitsimple`: everything except the package tests and the `com.oracle.truffle.r.nodes.test`
-2. `mx junitnopkgs`: everything except the package tests
-3. `mx junit --tests list`: `list` is a comma-separated list of test patterns, where a pattern is a package or class. For example to just run the "builtin" tests run `mx junit --tests com.oracle.truffle.r.test.builtins`.
+2. `mx junit --tests list`: `list` is a comma-separated list of test patterns, where a pattern is a package or class. For example to just run the "builtin" tests run `mx junit --tests com.oracle.truffle.r.test.builtins`.
 
 As with most FastR `mx` commands, additional parameters can be passed to the underlying FastR process using the `--J` option. For example to debug a unit test under an IDE, it is important to disable the internal timeout mechanism that detects looping tests, vis:
 
@@ -55,16 +54,16 @@ Package developers can provide tests in several ways. To enable the full set of
 
 ### Package Installation and Testing
 
-Package installation and testing is partly handled by a R script `install_cran_packages.R` in the `com.oracle.truffle.r.test.cran` project and partly by an `mx` script. There are two relevant `mx` commands, `installpkgs` and `pkgtest`. The former is simply a wrapper to `install_cran_packages.R`, whereas `pkgtest` contains additional code to gather and compare test outputs.
+Package installation and testing is partly handled by a R script `install.packages.R` in the `com.oracle.truffle.r.test.packages` project and partly by an `mx` script. There are two relevant `mx` commands, `installpkgs` and `pkgtest`. The former is simply a wrapper to `install.packages.R`, whereas `pkgtest` contains additional code to gather and compare test outputs.
 
-#### The install_cran_packages.R script
+#### The install.packages.R script
 
 While normally run with FastR using the `mx installpkgs` wrapper, this script can be used standalone using `Rscript`, thereby allowing to to be used by GNU R also.
 The command has a rather daunting set of options but, for normal use, most of these do not need to be set.
 
 ##### Usage
 
-    mx installpkgs [--contriburl url] [--cran-mirror url]
+    mx installpkgs [--repos list] [--cran-mirror url]
                    [--verbose | -v] [-V]
                    [--dryrun]
                    [--no-install | -n]
@@ -94,24 +93,20 @@ Key concepts are discussed below.
 
 ##### Package Blacklist
 
-There are many packages that cannot be installed due to either missing functionality or fundamental limitations in FastR and this set is seeded from a a DCF file, `initial.package.blacklist`, in the `com.oracle.truffle.r.test.cran` project. `install_cran_packages` operates in two modes, either creating a complete blacklist from an initial blacklist or reading a previously created blacklist file. In the latter case, if the blacklist file does not exist, it will be created. The complete blacklist file can specified in three ways:
+There are many packages that cannot be installed due to either missing functionality or fundamental limitations in FastR and this set is seeded from a a DCF file, `initial.package.blacklist`, in the `com.oracle.truffle.r.test.packages` project. `install.packages` operates in two modes, either creating a complete blacklist from an initial blacklist or reading a previously created blacklist file. In the latter case, if the blacklist file does not exist, it will be created. The complete blacklist file can specified in three ways:
 
-1. using the command line argument `--blacklist-file`
-2. from the environment variable `PACKAGE_BLACKLIST`
-3. the file `package.blacklist`
-
-The alternatives are tried in order. So, usually, this is all automatic.
+1. using the command line argument `--blacklist-file`; if omitted defaults to the file `package.blacklist`
 
 ##### CRAN Mirror
-Packages are downloaded and installed from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install_cran_packages` has a number of ways of specifying a mirror, including the use of a "local mirror" in the file system. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with the command line argument `--cran-mirror` or the environment variable `CRAN_MIRROR`.  When running locally a file system copy of a CRAN mirror containing just the `src/contrib` directory can be used by either setting the command line argument `--contrib-url` or the `LOCAL_CRAN_REPO` environment variable to a file: URL, e.g. `file:///users/mjj/cran/LOCAL_REPO/src/contrib`.
+Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with the command line argument `--cran-mirror` or the environment variable `CRAN_MIRROR`.  The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. It also implies `CRAN`.
 
 ##### Installation Directory
-The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation.
+The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation (the testing system does not honor the `--lib` argument).
 
 ##### Specifying packages to Install
-If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed.pkgs` option will cause `install_cran_packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely:
+If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed.pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely:
 
-    --ok-only: sets it to the file `com.oracle.truffle.r.test.cran.ok.packages`. This file is a list of packages that are known to install.
+    --ok-only: sets it to the file `com.oracle.truffle.r.test.packages.ok.packages`. This file is a list of packages that are known to install.
 
 N.B. The is file is updated only occasionally. Regressions, bug fixes, can render it inaccurate.
 
@@ -125,18 +120,18 @@ Finally, the `--invert-pkgset` option starts with the set from `available.packag
 N.B. By default the candidate set is always reduced by omitting any package in the package blacklist set, but this can be turned off by setting `--ignore-blacklist`. N.B. also that `--pkg-filelist` and `--pkg-pattern` are mutually exclusive.
 
 ##### Installing Dependent Packages:
-`install_cran_packages` installs the list of requested packages one by one. By default `utils::install.packages` always installs dependent packages, even if the dependent package has already been installed. This can be particularly wasteful if the package fails to install. Setting `--install-dependents-first` causes `install_cran_packages` to analyse the dependents and install them one by one first, aborting the installation of the depending package if any fail.
+`install.packages` installs the list of requested packages one by one. By default `utils::install.packages` always installs dependent packages, even if the dependent package has already been installed. This can be particularly wasteful if the package fails to install. Setting `--install-dependents-first` causes `install.packages` to analyse the dependents and install them one by one first, aborting the installation of the depending package if any fail.
 
 ##### Run Mode
-GNU R uses R/Rscript sub-processes in the internals of package installation and testing, but multiple package installations (e.g. using `--pkg-filelist`) would normally be initiated from a single top-level R process. This assumes that the package installation process itself is robust. This mode is defined as the `internal` mode variant of the `--run-mode` option. Since FastR is still under development, in `internal` mode a failure of FastR during a single package installation would abort the entire `install_cran_packages` execution. Therefore by default `install_cran_packages` runs each installation in  a separate FastR sub-process, referred to as `system` mode (because the R `system` function is used to launch the sub-process).
+GNU R uses R/Rscript sub-processes in the internals of package installation and testing, but multiple package installations (e.g. using `--pkg-filelist`) would normally be initiated from a single top-level R process. This assumes that the package installation process itself is robust. This mode is defined as the `internal` mode variant of the `--run-mode` option. Since FastR is still under development, in `internal` mode a failure of FastR during a single package installation would abort the entire `install.packages` execution. Therefore by default `install.packages` runs each installation in  a separate FastR sub-process, referred to as `system` mode (because the R `system` function is used to launch the sub-process).
 
-When running `install_cran_packages` under GNU R, it makes sense to set `--run-mode internal`.
+When running `install.packages` under GNU R, it makes sense to set `--run-mode internal`.
 
 ##### Use with GNU R
 
 Basic usage is:
 
-    $ Rscript $FASTR_HOME/fastr/com.oracle.truffle.r.test.cran/r/install.cran.packages.R --run-mode internal [options]
+    $ Rscript $FASTR_HOME/fastr/com.oracle.truffle.r.test.packages/r/install.packages.R --run-mode internal [options]
 
 where `FASTR_HOME` is the location of the FastR source.
 
@@ -157,11 +152,11 @@ Testing packages requires that they are first installed, so all of the above is
 
 #### Examples
 
-    $ export R_LIBS_USER=`pwd`/lib.install.cran
+    $ export R_LIBS_USER=`pwd`/lib.install.packages
 
     $ mx installpkgs --pkg-pattern '^A3$'
 
-Install the A3 package (and its dependents) in `$R_LIBS_USER`, creating the `package.blacklist` file first if it does not exist. The dependents (xtable, pbapply) will be installed implicitly by the  underlying R install.packages function
+Install the `A3` package (and its dependents) in `$R_LIBS_USER`, creating the `package.blacklist` file first if it does not exist. The dependents (`xtable`, `pbapply`) will be installed implicitly by the  underlying R install.packages function
 
     $ mx installpkgs --install-dependents-first--pkg-pattern '^A3$'
 
@@ -177,7 +172,7 @@ Install exactly those packages (and their dependents) specified, one per line, i
 
     $ mx installpkgs --ok-only --invert-pkgset --random-count 100
 
-Install 100 randomly chosen packages that are not in the file `com.oracle.truffle.r.test.cran/ok.packages`.
+Install 100 randomly chosen packages that are not in the file `com.oracle.truffle.r.test.packages/ok.packages`.
 
     $ mx installpkgs --ignore-blacklist '^Rcpp$'
 
@@ -193,6 +188,6 @@ To debug why a test fails requires first that the package is installed locally p
 
     $ FASTR_LOG_SYSTEM=1 mx installpkgs '^digest$'
 
-First, note that, by default,  the `installpkgs` command itself introduces an extra level on sub-process in order to avoid a failure from aborting the entire install command when installing/testing multiple packages. You can see this by setting the environment variable `FASTR_LOG_SYSTEM` to any value. The first sub-process logged will be running the command `com.oracle.truffle.r.test.cran/r/install.package.R` and the second will be the one running `R CMD INSTALL --install-tests` of the digest package. For ease of debugging you can set the `--run-mode` option to `internal`, which executes the first phase of the install in the process running `installpkgs`. Similar considerations apply to the testing phase. By default a sub-process is used to run the `com.oracle.truffle.r.test.cran/r/test.package.R script`, which then runs the actual test using a sub-process to invoke `R CMD BATCH`. Again the first sub-process can be avoided using `--run-mode internal`. N.B. If you run the tests for `digest` you will see that there are four separate sub-processes used to run different tests. The latter three are the specific tests for digest that were made available by installing with `--install-tests`. Not all packages have such additional tests. Note that there is no way to avoid the tests being run in sub-processes so setting the `-d` option to the `installpkgs` command will have no effect on those. Instead set the environment variable `MX_R_GLOBAL_ARGS=-d` which will cause the sub-processes to run under the debugger. Note that you will not (initially) see the `Listening for transport dt_socket at address: 8000` message on the console, but activating the debug launch from the IDE will connect to the sub-process.
+First, note that, by default,  the `installpkgs` command itself introduces an extra level on sub-process in order to avoid a failure from aborting the entire install command when installing/testing multiple packages. You can see this by setting the environment variable `FASTR_LOG_SYSTEM` to any value. The first sub-process logged will be running the command `com.oracle.truffle.r.test.packages/r/install.package.R` and the second will be the one running `R CMD INSTALL --install-tests` of the digest package. For ease of debugging you can set the `--run-mode` option to `internal`, which executes the first phase of the install in the process running `installpkgs`. Similar considerations apply to the testing phase. By default a sub-process is used to run the `com.oracle.truffle.r.test.packages/r/test.package.R script`, which then runs the actual test using a sub-process to invoke `R CMD BATCH`. Again the first sub-process can be avoided using `--run-mode internal`. N.B. If you run the tests for `digest` you will see that there are four separate sub-processes used to run different tests. The latter three are the specific tests for digest that were made available by installing with `--install-tests`. Not all packages have such additional tests. Note that there is no way to avoid the tests being run in sub-processes so setting the `-d` option to the `installpkgs` command will have no effect on those. Instead set the environment variable `MX_R_GLOBAL_ARGS=-d` which will cause the sub-processes to run under the debugger. Note that you will not (initially) see the `Listening for transport dt_socket at address: 8000` message on the console, but activating the debug launch from the IDE will connect to the sub-process.
 
 
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index e19d9ffd43..4555be425a 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -391,9 +391,6 @@ def junit_simple(args):
 def junit_noapps(args):
     return mx.command_function('junit')(['--tests', _gate_noapps_unit_tests()] + args)
 
-def junit_nopkgs(args):
-    return mx.command_function('junit')(['--tests', ','.join([_simple_unit_tests(), _nodes_unit_tests()])] + args)
-
 def junit_default(args):
     return mx.command_function('junit')(['--tests', _all_unit_tests()] + args)
 
@@ -412,9 +409,6 @@ def _simple_generated_unit_tests():
 def _simple_unit_tests():
     return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
 
-def _package_unit_tests():
-    return ','.join(map(_test_subpackage, ['rffi', 'rpackages']))
-
 def _nodes_unit_tests():
     return 'com.oracle.truffle.r.nodes.test'
 
@@ -422,7 +416,7 @@ def _apps_unit_tests():
     return _test_subpackage('apps')
 
 def _gate_noapps_unit_tests():
-    return ','.join([_simple_unit_tests(), _nodes_unit_tests(), _package_unit_tests()])
+    return ','.join([_simple_unit_tests(), _nodes_unit_tests()])
 
 def _gate_unit_tests():
     return ','.join([_gate_noapps_unit_tests(), _apps_unit_tests()])
@@ -431,7 +425,7 @@ def _all_unit_tests():
     return _gate_unit_tests()
 
 def _all_generated_unit_tests():
-    return ','.join([_simple_generated_unit_tests(), _package_unit_tests()])
+    return ','.join([_simple_generated_unit_tests()])
 
 def testgen(args):
     '''generate the expected output for unit tests, and All/Failing test classes'''
@@ -591,7 +585,6 @@ _commands = {
     'junitdefault' : [junit_default, ['options']],
     'junitgate' : [junit_gate, ['options']],
     'junitnoapps' : [junit_noapps, ['options']],
-    'junitnopkgs' : [junit_nopkgs, ['options']],
     'unittest' : [unittest, ['options']],
     'rbcheck' : [rbcheck, '--filter [gnur-only,fastr-only,both,both-diff]'],
     'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep=lite | --sweep=total] [--mnonly] [--noSelfTest] [--matchLevel=same | --matchLevel=error] [--maxSweeps=N] [--outMaxLev=N]'],
@@ -599,6 +592,7 @@ _commands = {
     'rembed' : [rembed, '[options]'],
     'r-cp' : [r_classpath, '[options]'],
     'pkgtest' : [mx_fastr_pkgs.pkgtest, ['options']],
+    'pkgtest-cmp' : [mx_fastr_pkgs.pkgtest_cmp, ['gnur_path fastr_path']],
     'installpkgs' : [mx_fastr_pkgs.installpkgs, '[options]'],
     'mkgramrd': [mx_fastr_mkgramrd.mkgramrd, '[options]'],
     'rcopylib' : [mx_copylib.copylib, '[]'],
diff --git a/mx.fastr/mx_fastr_dists.py b/mx.fastr/mx_fastr_dists.py
index 3892b38573..68066b43ce 100644
--- a/mx.fastr/mx_fastr_dists.py
+++ b/mx.fastr/mx_fastr_dists.py
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -131,18 +131,7 @@ class FastRTestNativeProject(FastRProjectAdapter):
         results = []
 
         self._get_files(join('packages', 'recommended'), results)
-
-        fastr_packages = []
-        fastr_packages_dir = join(self.dir, 'packages')
-        for root, dirs, _ in os.walk(fastr_packages_dir):
-            for d in dirs:
-                if d == 'recommended':
-                    continue
-                if os.path.isdir(join(root, d)):
-                    fastr_packages.append(d)
-            break
-        for p in fastr_packages:
-            results.append(join(fastr_packages_dir, p, 'lib', p + '.tar'))
+        self._get_files(join('packages', 'repo'), results)
 
         results.append(join(self.dir, 'urand', 'lib', 'liburand.so'))
         return results
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index 730622e8a3..6261292563 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -30,7 +30,7 @@ by the environment variable 'FASTR_GRAALVM' being set. (GRAALVM_FASTR is also ac
 Evidently in case 2, there is the potential for a version mismatch between FastR and GNU R, and this is checked.
 
 In either case all the output is placed in the fastr suite dir. Separate directories are used for FastR and GNU R package installs
-and tests, namely 'lib.install.cran.{fastr,gnur}' and 'test.{fastr,gnur}' (sh syntax).
+and tests, namely 'lib.install.packages.{fastr,gnur}' and 'test.{fastr,gnur}' (sh syntax).
 '''
 from os.path import join, relpath
 import shutil, os, re
@@ -79,10 +79,10 @@ def _graalvm():
 
 def _create_libinstall(rvm, test_installed):
     '''
-    Create lib.install.cran.<rvm>/install.tmp.<rvm>/test.<rvm> for <rvm>: fastr or gnur
+    Create lib.install.packages.<rvm>/install.tmp.<rvm>/test.<rvm> for <rvm>: fastr or gnur
     If use_installed_pkgs is True, assume lib.install exists and is populated (development)
     '''
-    libinstall = join(_fastr_suite_dir(), "lib.install.cran." + rvm)
+    libinstall = join(_fastr_suite_dir(), "lib.install.packages." + rvm)
     if not test_installed:
         # make sure its empty
         shutil.rmtree(libinstall, ignore_errors=True)
@@ -100,18 +100,18 @@ def _log_step(state, step, rvariant):
     if not quiet:
         print "{0} {1} with {2}".format(state, step, rvariant)
 
-def _cran_test_project():
-    return 'com.oracle.truffle.r.test.cran'
+def _packages_test_project():
+    return 'com.oracle.truffle.r.test.packages'
 
-def _cran_test_project_dir():
-    return mx.project(_cran_test_project()).dir
+def _packages_test_project_dir():
+    return mx.project(_packages_test_project()).dir
 
 def installpkgs(args):
     _installpkgs(args)
 
 def _installpkgs_script():
-    cran_test = _cran_test_project_dir()
-    return join(cran_test, 'r', 'install.cran.packages.R')
+    packages_test = _packages_test_project_dir()
+    return join(packages_test, 'r', 'install.packages.R')
 
 def _installpkgs(args, **kwargs):
     '''
@@ -141,7 +141,7 @@ def pkgtest(args):
         global quiet
         quiet = True
 
-    install_args = args
+    install_args = list(args)
 
     class OutputCapture:
         def __init__(self):
@@ -212,7 +212,7 @@ def pkgtest(args):
             install_args += ['--print-install-status']
 
     _log_step('BEGIN', 'install/test', 'FastR')
-    # Currently installpkgs does not set a return code (in install.cran.packages.R)
+    # Currently installpkgs does not set a return code (in install.packages.packages.R)
     rc = _installpkgs(install_args, nonZeroIsFatal=False, env=env, out=out, err=out)
     if rc == 100:
         # fatal error connecting to package repo
@@ -230,7 +230,7 @@ def pkgtest(args):
         # in order to compare the test output with GnuR we have to install/test the same
         # set of packages with GnuR
         ok_pkgs = [k for k, v in out.install_status.iteritems() if v]
-        _gnur_install_test(ok_pkgs, gnur_libinstall, gnur_install_tmp)
+        _gnur_install_test(_args_to_forward_to_gnur(args), ok_pkgs, gnur_libinstall, gnur_install_tmp)
         _set_test_status(out.test_info)
         print 'Test Status'
         for pkg, test_status in out.test_info.iteritems():
@@ -297,7 +297,7 @@ def _get_test_outputs(rvm, pkg_name, test_info):
             test_info[pkg_name] = TestStatus()
         for f in files:
             ext = os.path.splitext(f)[1]
-            if f == 'test_time' or ext == '.R' or ext == '.prev':
+            if f == 'test_time' or ext == '.R' or ext == '.Rin' or ext == '.prev':
                 continue
             # suppress .pdf's for now (we can't compare them)
             if ext == '.pdf':
@@ -314,7 +314,25 @@ def _get_test_outputs(rvm, pkg_name, test_info):
             relfile = relpath(absfile, pkg_testdir)
             test_info[pkg_name].testfile_outputs[relfile] = TestFileStatus(status, absfile)
 
-def _gnur_install_test(pkgs, gnur_libinstall, gnur_install_tmp):
+def _args_to_forward_to_gnur(args):
+    forwarded_args = ['--repos', '--run-mode']
+    result = []
+    i = 0
+    while i < len(args):
+        arg = args[i]
+        if arg in forwarded_args:
+            result.append(arg)
+            i = i + 1
+            result.append(args[i])
+        i = i + 1
+    return result
+
+def _gnur_install_test(forwarded_args, pkgs, gnur_libinstall, gnur_install_tmp):
+    '''
+    Install/test with GNU R  exactly those packages that installe3d correctly with FastR.
+    N.B. That means that regardless of how the packages were specified to pkgtest
+    we always use a --pkg-filelist' arg to GNU R
+    '''
     gnur_packages = join(_fastr_suite_dir(), 'gnur.packages')
     with open(gnur_packages, 'w') as f:
         for pkg in pkgs:
@@ -328,11 +346,11 @@ def _gnur_install_test(pkgs, gnur_libinstall, gnur_install_tmp):
     args = []
     if _graalvm():
         args += [_gnur_rscript()]
+    # forward any explicit args to pkgtest
     args += [_installpkgs_script()]
+    args += forwarded_args
     args += ['--pkg-filelist', gnur_packages]
     args += ['--run-tests']
-# GNU R will abort the entire run otherwise if a failure occurs
-#    args += ['--run-mode', 'internal']
     args += ['--ignore-blacklist']
     args += ['--testdir', 'test.gnur']
     _log_step('BEGIN', 'install/test', 'GnuR')
@@ -445,6 +463,20 @@ def _find_end(content):
     # not all files have a Time elapsed:
     return len(content) - 1
 
+def _find_line(gnur_line, fastr_content, fastr_i):
+    '''
+    Search forward in fastr_content from fastr_i searching for a match with gnur_line.
+    Do not match empty lines!
+    '''
+    if gnur_line == '\n':
+        return -1
+    while fastr_i < len(fastr_content):
+        fastr_line = fastr_content[fastr_i]
+        if fastr_line == gnur_line:
+            return fastr_i
+        fastr_i = fastr_i + 1
+    return -1
+
 def _fuzzy_compare(gnur_content, fastr_content):
     gnur_start = _find_start(gnur_content)
     gnur_end = _find_end(gnur_content)
@@ -452,20 +484,55 @@ def _fuzzy_compare(gnur_content, fastr_content):
     fastr_len = len(fastr_content)
     if not gnur_start or not gnur_end or not fastr_start:
         return -1
-    gnur_start = gnur_start + 1 # Gnu has extra empty line
+    gnur_i = gnur_start + 1 # Gnu has extra empty line
+    fastr_i = fastr_start
     result = 0
-    i = gnur_start
-    while i + gnur_start < gnur_end:
-        gnur_line = gnur_content[i + gnur_start]
-        if i + fastr_start >= fastr_len:
+    while gnur_i < gnur_end:
+        gnur_line = gnur_content[gnur_i]
+        if fastr_i >= fastr_len:
             result = 1
             break
 
-        fastr_line = fastr_content[i + fastr_start]
+        fastr_line = fastr_content[fastr_i]
         if gnur_line != fastr_line:
-            result = 1
-            break
-        i = i + 1
+            # we are fuzzy on Error/Warning as FastR often differs
+            # in the context/format of the error/warniong message AND GnuR is sometimes
+            # inconsistent over which error message it uses. Unlike the unit test environment,
+            # we cannot tag tests in any way, so we simply check that FastR does report
+            # an error. We then scan forward to try to get the files back in sync, as the
+            # the number of error/warning lines may differ.
+            if gnur_line.startswith(('Error', 'Warning')):
+                to_match = 'Error' if gnur_line.startswith('Error') else 'Warning'
+                if not fastr_line.startswith(to_match):
+                    result = 1
+                    break
+                else:
+                    # skip until lines match (or not)
+                    gnur_i = gnur_i + 1
+                    fastr_i = fastr_i + 1
+                    ni = -1
+                    while gnur_i < gnur_end:
+                        ni = _find_line(gnur_content[gnur_i], fastr_content, fastr_i)
+                        if ni > 0:
+                            break
+                        gnur_i = gnur_i + 1
+                    if ni > 0:
+                        fastr_i = ni
+                        continue
+                    else:
+                        result = 1
+                        break
+            else:
+                # genuine difference
+                result = 1
+                break
+        gnur_i = gnur_i + 1
+        fastr_i = fastr_i + 1
     return result
 
-
+def pkgtest_cmp(args):
+    with open(args[0]) as f:
+        gnur_content = f.readlines()
+    with open(args[1]) as f:
+        fastr_content = f.readlines()
+    _fuzzy_compare(gnur_content, fastr_content)
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 72888b9907..c21926d4d3 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -184,7 +184,7 @@ suite = {
       "workingSets" : "FastR",
     },
 
-    "com.oracle.truffle.r.test.cran" : {
+    "com.oracle.truffle.r.test.packages" : {
       "sourceDirs" : ["r"],
       "javaCompliance" : "1.8",
       "workingSets" : "FastR",
-- 
GitLab


From 90fc01619409bf2ed76abc20ad0b5c83bbd8402f Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Feb 2017 19:43:49 +0100
Subject: [PATCH 062/402] small fix in tests

---
 .../truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java   | 2 +-
 .../truffle/r/test/library/base/TestSimpleDataFrames.java     | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index a5cc3f5cce..a3a7abc4f0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
index 38e697cebf..bec24a8982 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleDataFrames.java
@@ -101,8 +101,8 @@ public class TestSimpleDataFrames extends TestBase {
         assertEval("{ x<-as.complex(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }");
         assertEval("{ x<-as.raw(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm=\"x\"); is.data.frame(y); }");
         assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=\"r1\", nm=\"x\"); attributes(y); }");
-        assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\"), nm=\"x\"); attributes(y); }");
-        assertEval("{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\", \"r3\"), nm=\"x\"); attributes(y); }");
+        assertEval("{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\"), nm=\"x\"); attributes(y); }");
+        assertEval(Output.MayIgnoreWarningContext, "{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c(\"r1\", \"r2\", \"r3\"), nm=\"x\"); attributes(y); }");
         assertEval("{ x<-matrix(c(1,2,3,4), nrow=2); y<-as.data.frame(x, row.names=NULL, optional=FALSE); attributes(y); }");
         assertEval("{ x<-matrix(c(1,2,3,4), nrow=2); y<-as.data.frame(x, row.names=\"r1\", optional=FALSE); attributes(y); }");
         assertEval("{ x<-1; class(x)<-\"foo\"; y<-as.data.frame(x) }");
-- 
GitLab


From ad11297f7b95c9e5fefacff135a4d90e66708cc5 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 22 Feb 2017 16:36:09 +0100
Subject: [PATCH 063/402] .External2 calls get "op" argument

---
 .../foreign/CallAndExternalFunctions.java     | 26 +++++++++++++++----
 .../truffle/r/runtime/data/RFunction.java     |  3 +++
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 2a9fe3ee00..037a66f6f7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -15,6 +15,8 @@ import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
@@ -819,13 +821,29 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".External2", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotExternal2 extends CallRFFIAdapter {
         private static final Object CALL = "call";
-        private static final Object OP = "op";
         private static final Object RHO = "rho";
+        /**
+         * This argument for the native function should be SPECIALSXP reprenting the .External2
+         * builtin. In GnuR SPECIALSXP is index into the table of builtins. External2 and External
+         * are in fact one native function with two entries in this table, the "op" argument is used
+         * to determine whether the call was made to .External or .External2. The actual code of the
+         * native function that is eventually invoked will always get SPECIALSXP reprenting the
+         * .External2, becuase functions exported as .External do not take the "op" argument.
+         */
+        @CompilationFinal private static Object op = null;
 
         static {
             Casts.noCasts(DotExternal2.class);
         }
 
+        private static Object getOp() {
+            if (op == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                op = RContext.lookupBuiltin(".External2");
+            }
+            return op;
+        }
+
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
@@ -866,8 +884,7 @@ public class CallAndExternalFunctions {
                         @Cached("symbol") RList cached,
                         @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) {
             Object list = encodeArgumentPairList(args, nativeCallInfo.name);
-            // TODO: provide proper values for the CALL, OP and RHO parameters
-            return callRFFINode.execute(nativeCallInfo, new Object[]{CALL, OP, list, RHO});
+            return callRFFINode.execute(nativeCallInfo, new Object[]{CALL, getOp(), list, RHO});
         }
 
         @Specialization
@@ -886,8 +903,7 @@ public class CallAndExternalFunctions {
                 throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "External2", packageName);
             }
             Object list = encodeArgumentPairList(args, symbol);
-            // TODO: provide proper values for the CALL, OP and RHO parameters
-            return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), new Object[]{CALL, OP, list, RHO});
+            return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), new Object[]{CALL, getOp(), list, RHO});
         }
 
         @Fallback
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
index d85a2c5f4f..463191fceb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
@@ -68,6 +68,9 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV
 
     @Override
     public RType getRType() {
+        // Note: GnuR distinguishes "builtins" and "specials" (BUILTINSXP vs SPECIALSXP). The later
+        // has non-evaluated args. FastR and GnuR built-ins differ in whether they have evaluated
+        // args, so we cannot correcly choose RType.Special here.
         return isBuiltin() ? RType.Builtin : RType.Closure;
     }
 
-- 
GitLab


From d64edadf9cf02658f0d3148b9371b3b7d269558c Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 17 Feb 2017 16:04:21 +0100
Subject: [PATCH 064/402] First changes from refactoring of connections
 implementation.

---
 SocketTest/src/Server.java                    |  35 +++
 .../r/runtime/conn/CompressedConnections.java |   1 -
 .../r/runtime/conn/ConnectionSupport.java     | 219 +++++-------------
 .../r/runtime/conn/FileConnections.java       |   1 -
 .../r/runtime/conn/RawConnections.java        |   1 -
 .../r/runtime/conn/ReadWriteHelper.java       | 170 ++++++++++++++
 .../r/runtime/conn/SocketConnections.java     |   1 -
 .../r/runtime/conn/URLConnections.java        |   1 -
 8 files changed, 265 insertions(+), 164 deletions(-)
 create mode 100644 SocketTest/src/Server.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java

diff --git a/SocketTest/src/Server.java b/SocketTest/src/Server.java
new file mode 100644
index 0000000000..8747a63dc1
--- /dev/null
+++ b/SocketTest/src/Server.java
@@ -0,0 +1,35 @@
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.charset.Charset;
+
+public class Server {
+
+	public static void main(String[] args) {
+
+		try (ServerSocket serverSocket = new ServerSocket(5678)) {
+			System.out.println("server started");
+			while (true) {
+				System.out.println("waiting for client");
+				Socket client = serverSocket.accept();
+				System.out.println("Client connected");
+				getLine();
+				PrintWriter pw = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
+				pw.println("hello");
+				pw.flush();
+				client.close();
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private static void getLine() throws IOException {
+		new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())).readLine();
+	}
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
index 7bf6d1af13..2b91e55502 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
@@ -48,7 +48,6 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class CompressedConnections {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 3eb19bd3cc..9ad58ba085 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.conn;
 
-import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -30,6 +29,7 @@ import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -41,6 +41,8 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.sun.istack.internal.NotNull;
+import com.sun.media.jfxmedia.locator.ConnectionHolder;
 
 /**
  * Basic support classes and methods for the connection implementations.
@@ -798,157 +800,7 @@ public class ConnectionSupport {
         }
     }
 
-    interface ReadWriteHelper {
-
-        /**
-         * {@code readLines} from an {@link InputStream}. It would be convenient to use a
-         * {@link BufferedReader} but mixing binary and text operations, which is a requirement,
-         * would then be difficult.
-         *
-         * @param warn TODO
-         * @param skipNul TODO
-         */
-        default String[] readLinesHelper(InputStream in, int n, boolean warn, boolean skipNul) throws IOException {
-            ArrayList<String> lines = new ArrayList<>();
-            int totalRead = 0;
-            byte[] buffer = new byte[64];
-            int pushBack = 0;
-            while (true) {
-                int ch;
-                if (pushBack != 0) {
-                    ch = pushBack;
-                    pushBack = 0;
-                } else {
-                    ch = in.read();
-                }
-                boolean lineEnd = false;
-                if (ch < 0) {
-                    if (totalRead > 0) {
-                        /*
-                         * TODO GnuR says keep data and output a warning if blocking, otherwise
-                         * silently push back. FastR doesn't support non-blocking yet, so we keep
-                         * the data. Some refactoring is needed to be able to reliably access the
-                         * "name" for the warning.
-                         */
-                        lines.add(new String(buffer, 0, totalRead));
-                        if (warn) {
-                            RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, "TODO: connection path");
-                        }
-                    }
-                    break;
-                }
-                if (ch == '\n') {
-                    lineEnd = true;
-                } else if (ch == '\r') {
-                    lineEnd = true;
-                    ch = in.read();
-                    if (ch == '\n') {
-                        // swallow the trailing lf
-                    } else {
-                        pushBack = ch;
-                    }
-                }
-                if (lineEnd) {
-                    lines.add(new String(buffer, 0, totalRead));
-                    if (n > 0 && lines.size() == n) {
-                        break;
-                    }
-                    totalRead = 0;
-                } else {
-                    buffer = checkBuffer(buffer, totalRead);
-                    buffer[totalRead++] = (byte) (ch & 0xFF);
-                }
-            }
-            String[] result = new String[lines.size()];
-            lines.toArray(result);
-            return result;
-        }
-
-        default void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep) throws IOException {
-            for (int i = 0; i < lines.getLength(); i++) {
-                out.write(lines.getDataAt(i).getBytes());
-                out.write(sep.getBytes());
-            }
-        }
-
-        default void writeStringHelper(OutputStream out, String s, boolean nl) throws IOException {
-            out.write(s.getBytes());
-            if (nl) {
-                out.write('\n');
-            }
-        }
-
-        default void writeCharHelper(OutputStream out, String s, int pad, String eos) throws IOException {
-            out.write(s.getBytes());
-            if (pad > 0) {
-                for (int i = 0; i < pad; i++) {
-                    out.write(0);
-                }
-            }
-            if (eos != null) {
-                if (eos.length() > 0) {
-                    out.write(eos.getBytes());
-                }
-                // function writeChar is defined to append the null character if eos != null
-                out.write(0);
-            }
-        }
-
-        default void writeBinHelper(ByteBuffer buffer, OutputStream outputStream) throws IOException {
-            int n = buffer.remaining();
-            byte[] b = new byte[n];
-            buffer.get(b);
-            outputStream.write(b);
-        }
-
-        /**
-         * Reads null-terminated character strings from an {@link InputStream}.
-         */
-        default byte[] readBinCharsHelper(InputStream in) throws IOException {
-            int ch = in.read();
-            if (ch < 0) {
-                return null;
-            }
-            int totalRead = 0;
-            byte[] buffer = new byte[64];
-            while (true) {
-                buffer = checkBuffer(buffer, totalRead);
-                buffer[totalRead++] = (byte) (ch & 0xFF);
-                if (ch == 0) {
-                    break;
-                }
-                ch = in.read();
-            }
-            return buffer;
-        }
-
-        default int readBinHelper(ByteBuffer buffer, InputStream inputStream) throws IOException {
-            int bytesToRead = buffer.remaining();
-            byte[] b = new byte[bytesToRead];
-            int totalRead = 0;
-            int thisRead = 0;
-            while ((totalRead < bytesToRead) && ((thisRead = inputStream.read(b, totalRead, bytesToRead - totalRead)) > 0)) {
-                totalRead += thisRead;
-            }
-            buffer.put(b, 0, totalRead);
-            return totalRead;
-        }
-
-        default String readCharHelper(int nchars, InputStream in, @SuppressWarnings("unused") boolean useBytes) throws IOException {
-            byte[] bytes = new byte[nchars];
-            in.read(bytes);
-            int j = 0;
-            for (; j < bytes.length; j++) {
-                // strings end at 0
-                if (bytes[j] == 0) {
-                    break;
-                }
-            }
-            return new String(bytes, 0, j);
-        }
-    }
-
-    private static byte[] checkBuffer(byte[] buffer, int n) {
+    static byte[] checkBuffer(byte[] buffer, int n) {
         if (n > buffer.length - 1) {
             byte[] newBuffer = new byte[buffer.length + buffer.length / 2];
             System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
@@ -960,8 +812,9 @@ public class ConnectionSupport {
 
     abstract static class DelegateRConnection extends RConnection {
         protected BaseRConnection base;
+        protected ByteChannel channel;
 
-        DelegateRConnection(BaseRConnection base) {
+        DelegateRConnection(@NotNull BaseRConnection base, @NotNull ByteChannel channel) {
             this.base = base;
         }
 
@@ -997,8 +850,8 @@ public class ConnectionSupport {
     }
 
     abstract static class DelegateReadRConnection extends DelegateRConnection {
-        protected DelegateReadRConnection(BaseRConnection base) {
-            super(base);
+        protected DelegateReadRConnection(BaseRConnection base, ByteChannel channel) {
+            super(base, channel);
         }
 
         @Override
@@ -1048,8 +901,8 @@ public class ConnectionSupport {
     }
 
     abstract static class DelegateWriteRConnection extends DelegateRConnection {
-        protected DelegateWriteRConnection(BaseRConnection base) {
-            super(base);
+        protected DelegateWriteRConnection(BaseRConnection base, ByteChannel channel) {
+            super(base, channel);
         }
 
         @Override
@@ -1091,11 +944,59 @@ public class ConnectionSupport {
         public boolean canWrite() {
             return true;
         }
+
+        @Override
+        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+            // TODO
+            writeCharHelper(channel, s, pad, eos);
+        }
+
+        @Override
+        public void writeBin(ByteBuffer buffer) throws IOException {
+            channel.write(buffer);
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            // TODO do we still need the output stream ?
+            throw RInternalError.shouldNotReachHere();
+        }
+
+        @Override
+        public void closeAndDestroy() throws IOException {
+            base.closed = true;
+            close();
+        }
+
+        @Override
+        public void close() throws IOException {
+            flush();
+            channel.close();
+        }
+
+        @Override
+        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+            for (int i = 0; i < lines.getLength(); i++) {
+                String line = lines.getDataAt(i);
+                outputStream.write(line.getBytes());
+                outputStream.write(sep.getBytes());
+            }
+        }
+
+        @Override
+        public void writeString(String s, boolean nl) throws IOException {
+            writeStringHelper(outputStream, s, nl);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            outputStream.flush();
+        }
     }
 
     abstract static class DelegateReadWriteRConnection extends DelegateRConnection {
-        protected DelegateReadWriteRConnection(BaseRConnection base) {
-            super(base);
+        protected DelegateReadWriteRConnection(BaseRConnection base, ByteChannel channel) {
+            super(base, channel);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 77c0e2875e..66c8c8ab72 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -48,7 +48,6 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnecti
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.OpenMode;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class FileConnections {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 02d6e0dd6c..ac220dafd9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class RawConnections {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
new file mode 100644
index 0000000000..ebeca0685c
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
@@ -0,0 +1,170 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.util.ArrayList;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+public class ReadWriteHelper {
+
+    /**
+     * {@code readLines} from an {@link InputStream}. It would be convenient to use a
+     * {@link BufferedReader} but mixing binary and text operations, which is a requirement, would
+     * then be difficult.
+     *
+     * @param warn TODO
+     * @param skipNul TODO
+     */
+    public static String[] readLinesHelper(InputStream in, int n, boolean warn, boolean skipNul) throws IOException {
+        ArrayList<String> lines = new ArrayList<>();
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        int pushBack = 0;
+        while (true) {
+            int ch;
+            if (pushBack != 0) {
+                ch = pushBack;
+                pushBack = 0;
+            } else {
+                ch = in.read();
+            }
+            boolean lineEnd = false;
+            if (ch < 0) {
+                if (totalRead > 0) {
+                    /*
+                     * TODO GnuR says keep data and output a warning if blocking, otherwise silently
+                     * push back. FastR doesn't support non-blocking yet, so we keep the data. Some
+                     * refactoring is needed to be able to reliably access the "name" for the
+                     * warning.
+                     */
+                    lines.add(new String(buffer, 0, totalRead));
+                    if (warn) {
+                        RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, "TODO: connection path");
+                    }
+                }
+                break;
+            }
+            if (ch == '\n') {
+                lineEnd = true;
+            } else if (ch == '\r') {
+                lineEnd = true;
+                ch = in.read();
+                if (ch == '\n') {
+                    // swallow the trailing lf
+                } else {
+                    pushBack = ch;
+                }
+            }
+            if (lineEnd) {
+                lines.add(new String(buffer, 0, totalRead));
+                if (n > 0 && lines.size() == n) {
+                    break;
+                }
+                totalRead = 0;
+            } else {
+                buffer = ConnectionSupport.checkBuffer(buffer, totalRead);
+                buffer[totalRead++] = (byte) (ch & 0xFF);
+            }
+        }
+        String[] result = new String[lines.size()];
+        lines.toArray(result);
+        return result;
+    }
+
+    public static void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep) throws IOException {
+        for (int i = 0; i < lines.getLength(); i++) {
+            out.write(lines.getDataAt(i).getBytes());
+            out.write(sep.getBytes());
+        }
+    }
+
+    public static void writeStringHelper(ByteChannel out, String s, boolean nl) throws IOException {
+        ByteBuffer buf = ByteBuffer.allocate(s.length() + 1);
+        buf.put(s.getBytes());
+        if (nl) {
+            buf.putChar('\n');
+        }
+        buf.rewind();
+        out.write(buf);
+    }
+
+    public static void writeCharHelper(ByteChannel channel, String s, int pad, String eos) throws IOException {
+
+        ByteBuffer buf = ByteBuffer.allocate(s.length() + pad + eos.length() + 1);
+        buf.put(s.getBytes());
+        if (pad > 0) {
+            for (int i = 0; i < pad; i++) {
+                buf.put((byte) 0);
+            }
+        }
+        if (eos != null) {
+            if (eos.length() > 0) {
+                buf.put(eos.getBytes());
+            }
+            // function writeChar is defined to append the null character if eos != null
+            buf.put((byte) 0);
+        }
+        buf.rewind();
+        channel.write(buf);
+    }
+
+    @Deprecated
+    public static void writeBinHelper(ByteBuffer buffer, OutputStream outputStream) throws IOException {
+        int n = buffer.remaining();
+        byte[] b = new byte[n];
+        buffer.get(b);
+        outputStream.write(b);
+    }
+
+    /**
+     * Reads null-terminated character strings from an {@link InputStream}.
+     */
+    public static byte[] readBinCharsHelper(InputStream in) throws IOException {
+        int ch = in.read();
+        if (ch < 0) {
+            return null;
+        }
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        while (true) {
+            buffer = ConnectionSupport.checkBuffer(buffer, totalRead);
+            buffer[totalRead++] = (byte) (ch & 0xFF);
+            if (ch == 0) {
+                break;
+            }
+            ch = in.read();
+        }
+        return buffer;
+    }
+
+    public static int readBinHelper(ByteBuffer buffer, InputStream inputStream) throws IOException {
+        int bytesToRead = buffer.remaining();
+        byte[] b = new byte[bytesToRead];
+        int totalRead = 0;
+        int thisRead = 0;
+        while ((totalRead < bytesToRead) && ((thisRead = inputStream.read(b, totalRead, bytesToRead - totalRead)) > 0)) {
+            totalRead += thisRead;
+        }
+        buffer.put(b, 0, totalRead);
+        return totalRead;
+    }
+
+    public static String readCharHelper(int nchars, InputStream in, @SuppressWarnings("unused") boolean useBytes) throws IOException {
+        byte[] bytes = new byte[nchars];
+        in.read(bytes);
+        int j = 0;
+        for (; j < bytes.length; j++) {
+            // strings end at 0
+            if (bytes[j] == 0) {
+                break;
+            }
+        }
+        return new String(bytes, 0, j);
+    }
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index e7da9ceca6..815792173f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class SocketConnections {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index 7aad2be8e1..add7bb79e5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ReadWriteHelper;
 
 public class URLConnections {
     public static class URLRConnection extends BaseRConnection {
-- 
GitLab


From b431f0ce371dae1fb25f0512cef7ff980c3dab89 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 21 Feb 2017 17:52:04 +0100
Subject: [PATCH 065/402] Continued refactoring of connection implementation. -
 Moved DelegateRConnection and subclasses into separate files (for better
 overview). - Increased code sharing of readLines, readChar, readBin (same for
 write) by providing standard implementation in the delegate classes. Hence,
 implementation of, for example, named pipes (FIFOs) is almost trivial. -
 Fixed some bug in SeekableMemoryByteChannel and changed behavior if a byte
 array is provided in the constructor. - Implemented push back reset when
 seeking.

Added initial test class for FIFOs and added tests to file and text connections.
Implemented function "fifo" for working with named pipes.
---
 .../r/nodes/builtin/base/BasePackage.java     |   1 +
 .../builtin/base/ConnectionFunctions.java     |  37 +-
 .../com/oracle/truffle/r/runtime/RError.java  |   5 +-
 .../r/runtime/conn/CompressedConnections.java | 231 +-------
 .../r/runtime/conn/ConnectionSupport.java     | 221 +-------
 .../r/runtime/conn/DelegateRConnection.java   |  45 ++
 .../runtime/conn/DelegateReadRConnection.java | 107 ++++
 .../conn/DelegateReadWriteRConnection.java    | 106 ++++
 .../conn/DelegateWriteRConnection.java        | 106 ++++
 .../r/runtime/conn/FifoConnections.java       | 201 +++++++
 .../r/runtime/conn/FileConnections.java       | 497 ++++++++++++------
 .../truffle/r/runtime/conn/RConnection.java   |  18 +-
 .../r/runtime/conn/RawConnections.java        | 172 +-----
 .../r/runtime/conn/ReadWriteHelper.java       |  85 ++-
 .../conn/SeekableMemoryByteChannel.java       |  23 +-
 .../r/runtime/conn/SocketConnections.java     |  73 +--
 .../r/runtime/conn/TextConnections.java       |  57 +-
 .../r/runtime/conn/URLConnections.java        |  37 +-
 .../truffle/r/test/ExpectedTestOutput.test    |  47 ++
 .../builtins/TestBuiltin_fifoConnection.java  |  74 +++
 .../builtins/TestBuiltin_fileConnection.java  |  71 +++
 .../builtins/TestBuiltin_textConnection.java  |  54 ++
 22 files changed, 1388 insertions(+), 880 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index c09506f646..144dd28313 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -267,6 +267,7 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.SocketConnection.class, ConnectionFunctionsFactory.SocketConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnection.class, ConnectionFunctionsFactory.RawConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnectionValue.class, ConnectionFunctionsFactory.RawConnectionValueNodeGen::create);
+        add(ConnectionFunctions.Fifo.class, ConnectionFunctionsFactory.FifoNodeGen::create);
         add(ConnectionFunctions.Stderr.class, ConnectionFunctionsFactory.StderrNodeGen::create);
         add(ConnectionFunctions.Stdin.class, ConnectionFunctionsFactory.StdinNodeGen::create);
         add(ConnectionFunctions.Stdout.class, ConnectionFunctionsFactory.StdoutNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index c5c88dd46d..baf8368617 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -69,8 +69,9 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.conn.CompressedConnections.CompressedRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.FifoConnections.FifoRConnection;
+import com.oracle.truffle.r.runtime.conn.FileConnections.CompressedRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.FileRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.conn.RawConnections.RawRConnection;
@@ -310,8 +311,7 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(TextConnection.class);
             CastsHelper.description(casts);
             // TODO how to have either a RNull or a String/RStringVector and have the latter coerced
-            // to a
-            // RAbstractStringVector to avoid the explicit handling in the specialization
+            // to a RAbstractStringVector to avoid the explicit handling in the specialization
             casts.arg("text").allowNull().mustBe(stringValue());
             CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
             casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
@@ -748,10 +748,10 @@ public abstract class ConnectionFunctions {
         @TruffleBoundary
         private RNull writeCharGeneric(RAbstractStringVector object, int con, RAbstractIntVector nchars, RAbstractStringVector sep, boolean useBytes) {
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("wb")) {
-                int length = object.getLength();
+                final int length = object.getLength();
+                final int ncharsLen = nchars.getLength();
                 for (int i = 0; i < length; i++) {
-                    // FIXME: 'i % length' is probably wrong
-                    int nc = nchars.getDataAt(i % length);
+                    int nc = nchars.getDataAt(i % ncharsLen);
                     String s = object.getDataAt(i);
                     final int writeLen = Math.min(s.length(), nc);
                     int pad = nc - s.length();
@@ -1203,4 +1203,29 @@ public abstract class ConnectionFunctions {
             }
         }
     }
+
+    @RBuiltin(name = "fifo", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding"}, behavior = IO)
+    public abstract static class Fifo extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(Fifo.class);
+            CastsHelper.description(casts);
+            CastsHelper.open(casts);
+            CastsHelper.blocking(casts);
+            CastsHelper.encoding(casts);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected RAbstractIntVector fifo(String path, String openArg, boolean blocking, String encoding) {
+
+            String open = openArg;
+            try {
+                return new FifoRConnection(path, open, blocking, encoding).asVector();
+            } catch (IOException ex) {
+                RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
+                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+            }
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index ad5120700f..20cb51447e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -831,7 +831,10 @@ public final class RError extends RuntimeException {
         NOT_AN_OUTPUT_RAW_CONNECTION("'con' is not an output rawConnection"),
         NOT_A_RAW_CONNECTION("'con' is not a rawConnection"),
         SEEK_OUTSITE_RAW_CONNECTION("attempt to seek outside the range of the raw connection"),
-        VECTOR_IS_TOO_LARGE("vector is too large");
+        VECTOR_IS_TOO_LARGE("vector is too large"),
+        SEEK_NOT_RELEVANT_FOR_TEXT_CON("seek is not relevant for text connection"),
+        SEEK_NOT_ENABLED("'seek' not enabled for this connection"),
+        CANNOT_OPEN_FIFO("cannot open fifo '%s'");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
index 2b91e55502..3786c9d900 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
@@ -30,6 +30,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
@@ -45,235 +48,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class CompressedConnections {
-    public static final int GZIP_BUFFER_SIZE = (2 << 20);
-
-    /**
-     * Base class for all modes of gzfile/bzfile/xzfile connections. N.B. In GNU R these can read
-     * gzip, bzip, lzma and uncompressed files, and this has to be implemented by reading the first
-     * few bytes of the file and detecting the type of the file.
-     */
-    public static class CompressedRConnection extends BasePathRConnection {
-        private final RCompression.Type cType;
-        @SuppressWarnings("unused") private final String encoding; // TODO
-        @SuppressWarnings("unused") private final int compression; // TODO
-
-        public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException {
-            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary);
-            this.cType = cType;
-            this.encoding = encoding;
-            this.compression = compression;
-            openNonLazyConnection();
-        }
-
-        private static ConnectionClass mapConnectionClass(RCompression.Type cType) {
-            switch (cType) {
-                case NONE:
-                    return ConnectionClass.File;
-                case GZIP:
-                    return ConnectionClass.GZFile;
-                case BZIP2:
-                    return ConnectionClass.BZFile;
-                case XZ:
-                    return ConnectionClass.XZFile;
-                default:
-                    throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        protected void createDelegateConnection() throws IOException {
-            DelegateRConnection delegate = null;
-            AbstractOpenMode openMode = getOpenMode().abstractOpenMode;
-            switch (openMode) {
-                case Read:
-                case ReadBinary:
-                    /*
-                     * For input, we check the actual compression type as GNU R is permissive about
-                     * the claimed type.
-                     */
-                    RCompression.Type cTypeActual = RCompression.getCompressionType(path);
-                    if (cTypeActual != cType) {
-                        updateConnectionClass(mapConnectionClass(cTypeActual));
-                    }
-                    switch (cTypeActual) {
-                        case NONE:
-                            if (openMode == AbstractOpenMode.ReadBinary) {
-                                delegate = new FileConnections.FileReadBinaryRConnection(this);
-                            } else {
-                                delegate = new FileConnections.FileReadTextRConnection(this);
-                            }
-                            break;
-                        case GZIP:
-                            delegate = new CompressedInputRConnection(this, new GZIPInputStream(new FileInputStream(path), GZIP_BUFFER_SIZE));
-                            break;
-                        case XZ:
-                            delegate = new CompressedInputRConnection(this, new XZInputStream(new FileInputStream(path)));
-                            break;
-                        case BZIP2:
-                            // no in Java support, so go via byte array
-                            byte[] bzipUdata = RCompression.bzipUncompressFromFile(path);
-                            delegate = new ByteStreamCompressedInputRConnection(this, new ByteArrayInputStream(bzipUdata));
-                    }
-                    break;
-
-                case Append:
-                case AppendBinary:
-                case Write:
-                case WriteBinary: {
-                    boolean append = openMode == AbstractOpenMode.Append || openMode == AbstractOpenMode.AppendBinary;
-                    switch (cType) {
-                        case GZIP:
-                            delegate = new CompressedOutputRConnection(this, new GZIPOutputStream(new FileOutputStream(path, append), GZIP_BUFFER_SIZE));
-                            break;
-                        case BZIP2:
-                            delegate = new BZip2OutputRConnection(this, new ByteArrayOutputStream(), append);
-                            break;
-                        case XZ:
-                            delegate = new CompressedOutputRConnection(this, new XZOutputStream(new FileOutputStream(path, append), new LZMA2Options(), XZ.CHECK_CRC32));
-                            break;
-                    }
-                    break;
-                }
-                default:
-                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
-            }
-            setDelegate(delegate);
-        }
-
-        // @Override
-        /**
-         * GnuR behavior for lazy connections is odd, e.g. gzfile returns "text", even though the
-         * default mode is "rb".
-         */
-        // public boolean isTextMode() {
-        // }
-    }
-
-    private static class CompressedInputRConnection extends DelegateReadRConnection implements ReadWriteHelper {
-        private final InputStream inputStream;
-
-        protected CompressedInputRConnection(CompressedRConnection base, InputStream is) {
-            super(base);
-            this.inputStream = is;
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, inputStream, useBytes);
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            return readBinHelper(buffer, inputStream);
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            return readBinCharsHelper(inputStream);
-        }
-
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(inputStream, n, warn, skipNul);
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
-            return inputStream;
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
-
-        @Override
-        public void close() throws IOException {
-            inputStream.close();
-        }
-    }
-
-    private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection {
-        ByteStreamCompressedInputRConnection(CompressedRConnection base, ByteArrayInputStream is) {
-            super(base, is);
-        }
-    }
-
-    private static class CompressedOutputRConnection extends DelegateWriteRConnection implements ReadWriteHelper {
-        protected OutputStream outputStream;
-
-        protected CompressedOutputRConnection(CompressedRConnection base, OutputStream os) {
-            super(base);
-            this.outputStream = os;
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return outputStream;
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
-
-        @Override
-        public void close() throws IOException {
-            flush();
-            outputStream.close();
-        }
-
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            writeLinesHelper(outputStream, lines, sep);
-        }
-
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(outputStream, s, pad, eos);
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            writeBinHelper(buffer, outputStream);
-        }
-
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(outputStream, s, nl);
-        }
-
-        @Override
-        public void flush() throws IOException {
-            outputStream.flush();
-        }
-    }
-
-    private static class BZip2OutputRConnection extends CompressedOutputRConnection {
-        private final ByteArrayOutputStream bos;
-        private final boolean append;
-
-        BZip2OutputRConnection(CompressedRConnection base, ByteArrayOutputStream os, boolean append) {
-            super(base, os);
-            this.bos = os;
-            this.append = append;
-        }
-
-        @Override
-        public void close() throws IOException {
-            flush();
-            outputStream.close();
-            // Now actually do the compression using sub-process
-            byte[] data = bos.toByteArray();
-            RCompression.bzipCompressToFile(data, ((BasePathRConnection) base).path, append);
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 9ad58ba085..57d17adc6f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -29,7 +29,6 @@ import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -41,8 +40,6 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.sun.istack.internal.NotNull;
-import com.sun.media.jfxmedia.locator.ConnectionHolder;
 
 /**
  * Basic support classes and methods for the connection implementations.
@@ -321,7 +318,9 @@ public class ConnectionSupport {
         Text("textConnection"),
         URL("url"),
         RAW("rawConnection"),
-        Internal("internal");
+        Internal("internal"),
+        PIPE("pipe"),
+        FIFO("fifo");
 
         private final String printName;
 
@@ -466,6 +465,11 @@ public class ConnectionSupport {
         public boolean isOpen() {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
+
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
+        }
     }
 
     /**
@@ -745,9 +749,9 @@ public class ConnectionSupport {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             checkOpen();
-            return theConnection.seek(offset, seekMode, seekRWMode);
+            return theConnection.seekInternal(offset, seekMode, seekRWMode);
         }
 
         @Override
@@ -810,211 +814,6 @@ public class ConnectionSupport {
         }
     }
 
-    abstract static class DelegateRConnection extends RConnection {
-        protected BaseRConnection base;
-        protected ByteChannel channel;
-
-        DelegateRConnection(@NotNull BaseRConnection base, @NotNull ByteChannel channel) {
-            this.base = base;
-        }
-
-        @Override
-        public int getDescriptor() {
-            return base.getDescriptor();
-        }
-
-        @Override
-        public boolean isTextMode() {
-            return base.isTextMode();
-        }
-
-        @Override
-        public boolean isOpen() {
-            return base.isOpen();
-        }
-
-        @Override
-        public RConnection forceOpen(String modeString) throws IOException {
-            return base.forceOpen(modeString);
-        }
-
-        @Override
-        public boolean isSeekable() {
-            return false;
-        }
-
-        @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.UNSEEKABLE_CONNECTION);
-        }
-    }
-
-    abstract static class DelegateReadRConnection extends DelegateRConnection {
-        protected DelegateReadRConnection(BaseRConnection base, ByteChannel channel) {
-            super(base, channel);
-        }
-
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-        }
-
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-        }
-
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-        }
-
-        @Override
-        public int getc() throws IOException {
-            return getInputStream().read();
-        }
-
-        @Override
-        public void flush() {
-            // nothing to do
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public boolean canRead() {
-            return true;
-        }
-
-        @Override
-        public boolean canWrite() {
-            return false;
-        }
-    }
-
-    abstract static class DelegateWriteRConnection extends DelegateRConnection {
-        protected DelegateWriteRConnection(BaseRConnection base, ByteChannel channel) {
-            super(base, channel);
-        }
-
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-        }
-
-        @Override
-        public int getc() throws IOException {
-            throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public boolean canRead() {
-            return false;
-        }
-
-        @Override
-        public boolean canWrite() {
-            return true;
-        }
-
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            // TODO
-            writeCharHelper(channel, s, pad, eos);
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            channel.write(buffer);
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            // TODO do we still need the output stream ?
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
-
-        @Override
-        public void close() throws IOException {
-            flush();
-            channel.close();
-        }
-
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            for (int i = 0; i < lines.getLength(); i++) {
-                String line = lines.getDataAt(i);
-                outputStream.write(line.getBytes());
-                outputStream.write(sep.getBytes());
-            }
-        }
-
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(outputStream, s, nl);
-        }
-
-        @Override
-        public void flush() throws IOException {
-            outputStream.flush();
-        }
-    }
-
-    abstract static class DelegateReadWriteRConnection extends DelegateRConnection {
-        protected DelegateReadWriteRConnection(BaseRConnection base, ByteChannel channel) {
-            super(base, channel);
-        }
-
-        @Override
-        public boolean canRead() {
-            return true;
-        }
-
-        @Override
-        public boolean canWrite() {
-            return true;
-        }
-
-        @Override
-        public int getc() throws IOException {
-            return getInputStream().read();
-        }
-    }
-
     abstract static class BasePathRConnection extends BaseRConnection {
         protected final String path;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
new file mode 100644
index 0000000000..6b33ed255c
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -0,0 +1,45 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.nio.channels.Channel;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.sun.istack.internal.NotNull;
+
+abstract class DelegateRConnection extends RConnection {
+    protected BaseRConnection base;
+
+    DelegateRConnection(@NotNull BaseRConnection base) {
+        this.base = base;
+    }
+
+    @Override
+    public int getDescriptor() {
+        return base.getDescriptor();
+    }
+
+    @Override
+    public boolean isTextMode() {
+        return base.isTextMode();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return base.isOpen();
+    }
+
+    @Override
+    public RConnection forceOpen(String modeString) throws IOException {
+        return base.forceOpen(modeString);
+    }
+
+    @Override
+    protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        assert !isSeekable();
+        throw RError.error(RError.SHOW_CALLER2, RError.Message.UNSEEKABLE_CONNECTION);
+    }
+
+    public abstract Channel getChannel();
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
new file mode 100644
index 0000000000..ae12d89797
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -0,0 +1,107 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+public abstract class DelegateReadRConnection extends DelegateRConnection {
+
+    protected DelegateReadRConnection(BaseRConnection base) {
+        super(base);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public int getc() throws IOException {
+        return getInputStream().read();
+    }
+
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        return ReadWriteHelper.readCharHelper(nchars, getChannel(), useBytes);
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        return getChannel().read(buffer);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+    }
+
+    @TruffleBoundary
+    @Override
+    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul);
+    }
+
+    @Override
+    public void flush() {
+        // nothing to do when reading
+    }
+
+    @Override
+    public OutputStream getOutputStream() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return false;
+    }
+
+    @Override
+    public abstract ReadableByteChannel getChannel();
+
+    @Override
+    public InputStream getInputStream() {
+        return Channels.newInputStream(getChannel());
+    }
+
+    @Override
+    public void close() throws IOException {
+        getChannel().close();
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
new file mode 100644
index 0000000000..0b34b4ee82
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -0,0 +1,106 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.Channels;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+abstract class DelegateReadWriteRConnection extends DelegateRConnection {
+
+    protected DelegateReadWriteRConnection(BaseRConnection base) {
+        super(base);
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    public int getc() throws IOException {
+        return getInputStream().read();
+    }
+
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        return ReadWriteHelper.readCharHelper(nchars, getChannel(), useBytes);
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        return getChannel().read(buffer);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+    }
+
+    @TruffleBoundary
+    @Override
+    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul);
+    }
+
+    @Override
+    public void flush() {
+        // nothing to do for channels
+    }
+
+    @Override
+    public OutputStream getOutputStream() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public abstract ByteChannel getChannel();
+
+    @Override
+    public InputStream getInputStream() {
+        return Channels.newInputStream(getChannel());
+    }
+
+    @Override
+    public void close() throws IOException {
+        getChannel().close();
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        getChannel().write(buffer);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep);
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        ReadWriteHelper.writeStringHelper(getChannel(), s, nl);
+    }
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
new file mode 100644
index 0000000000..c3c38def14
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -0,0 +1,106 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+abstract class DelegateWriteRConnection extends DelegateRConnection {
+
+    protected DelegateWriteRConnection(BaseRConnection base) {
+        super(base);
+    }
+
+    @Override
+    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public int getc() throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public InputStream getInputStream() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public boolean canRead() {
+        return false;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
+
+    @Override
+    public void flush() throws IOException {
+        // channels don't need any flushing
+    }
+
+    @Override
+    public void close() throws IOException {
+        flush();
+        getChannel().close();
+    }
+
+    @Override
+    public abstract WritableByteChannel getChannel();
+
+    @Override
+    public OutputStream getOutputStream() throws IOException {
+        return Channels.newOutputStream(getChannel());
+    }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        getChannel().write(buffer);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep);
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        ReadWriteHelper.writeStringHelper(getChannel(), s, nl);
+    }
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
new file mode 100644
index 0000000000..475a550117
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.lang.ProcessBuilder.Redirect;
+import java.nio.channels.SeekableByteChannel;
+import java.util.Arrays;
+
+import com.oracle.truffle.r.runtime.ProcessOutputManager;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
+
+public class FifoConnections {
+
+    public static class FifoRConnection extends BaseRConnection {
+
+        private final String path;
+
+        public FifoRConnection(String path, String open, boolean blocking, String encoding) throws IOException {
+            super(ConnectionClass.FIFO, open, AbstractOpenMode.Read);
+            this.path = path;
+            openNonLazyConnection();
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            DelegateRConnection delegate = null;
+            switch (getOpenMode().abstractOpenMode) {
+                case Read:
+                case ReadBinary:
+                    delegate = new FifoReadRConnection(this, path);
+                    break;
+                case Write:
+                case WriteBinary:
+                    delegate = new FifoWriteConnection(this, path);
+                    delegate = new FifoWriteConnection(this, path);
+                    break;
+                case ReadAppend:
+                case ReadWrite:
+                case ReadWriteBinary:
+                case ReadWriteTrunc:
+                case ReadWriteTruncBinary:
+                    delegate = new FifoReadWriteConnection(this, path);
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
+            }
+            setDelegate(delegate);
+        }
+
+        @Override
+        public String getSummaryDescription() {
+            return path;
+        }
+    }
+
+    static class FifoReadRConnection extends DelegateReadRConnection {
+        private final RandomAccessFile raf;
+
+        protected FifoReadRConnection(BaseRConnection base, String path) throws FileNotFoundException {
+            super(base);
+            raf = new RandomAccessFile(path, "r");
+        }
+
+        @Override
+        public SeekableByteChannel getChannel() {
+            return raf.getChannel();
+        }
+
+        @Override
+        public void close() throws IOException {
+            raf.close();
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private static class FifoWriteConnection extends DelegateWriteRConnection {
+        private final RandomAccessFile raf;
+
+        FifoWriteConnection(BaseRConnection base, String path) throws IOException {
+            super(base);
+            this.raf = createAndOpenFifo(path, "rw");
+        }
+
+        @Override
+        public SeekableByteChannel getChannel() {
+            return raf.getChannel();
+        }
+
+        @Override
+        public void close() throws IOException {
+            raf.close();
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private static class FifoReadWriteConnection extends DelegateReadWriteRConnection {
+
+        private final RandomAccessFile raf;
+
+        protected FifoReadWriteConnection(BaseRConnection base, String path) throws IOException {
+            super(base);
+            this.raf = createAndOpenFifo(path, "w");
+        }
+
+        @Override
+        public SeekableByteChannel getChannel() {
+            return raf.getChannel();
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+
+    }
+
+    private static final String MKFIFO_ERROR_FILE_EXISTS = "File exists";
+
+    private static RandomAccessFile createAndOpenFifo(String path, String mode) throws IOException {
+        RandomAccessFile pipeFile = null;
+        try {
+            pipeFile = new RandomAccessFile(path, mode);
+        } catch (FileNotFoundException e) {
+            // try to create fifo on demand
+            createNamedPipe(path);
+
+            // re-try opening
+            pipeFile = new RandomAccessFile(path, mode);
+        }
+        return pipeFile;
+    }
+
+    /**
+     * Creates a named pipe (FIFO) by invoking {@code mkfifo} in a shell.
+     *
+     * <b>NOTE:</b> This is a Linux-specific operation and won't work on other OSes.
+     *
+     * @param path The path to the named pipe.
+     * @throws IOException
+     */
+    private static void createNamedPipe(String path) throws IOException {
+
+        String[] command = new String[]{"mkfifo", path};
+        ProcessBuilder pb = new ProcessBuilder(command);
+        pb.redirectError(Redirect.INHERIT);
+        Process p = pb.start();
+        InputStream is = p.getInputStream();
+        ProcessOutputManager.OutputThreadVariable readThread = new ProcessOutputManager.OutputThreadVariable(command[0], is);
+        readThread.start();
+        try {
+            int rc = p.waitFor();
+            if (rc == 0) {
+                readThread.join();
+                String msg = new String(Arrays.copyOf(readThread.getData(), readThread.getTotalRead()));
+
+                // ignore if file already exists
+                if (!msg.endsWith(MKFIFO_ERROR_FILE_EXISTS)) {
+                    throw new IOException(msg);
+                }
+            }
+        } catch (InterruptedException ex) {
+            // fall through
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 66c8c8ab72..f9b97b4b1e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -22,9 +22,8 @@
  */
 package com.oracle.truffle.r.runtime.conn;
 
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -32,25 +31,40 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
 
+import org.tukaani.xz.LZMA2Options;
+import org.tukaani.xz.XZ;
 import org.tukaani.xz.XZInputStream;
+import org.tukaani.xz.XZOutputStream;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RCompression;
+import com.oracle.truffle.r.runtime.RCompression.Type;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.TempPathName;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.OpenMode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class FileConnections {
+    public static final int GZIP_BUFFER_SIZE = (2 << 20);
+
     /**
      * Base class for all modes of file connections.
      *
@@ -72,10 +86,13 @@ public class FileConnections {
 
         @Override
         protected void createDelegateConnection() throws IOException {
+
+            // TODO (non-)blocking
+
             DelegateRConnection delegate = null;
             switch (getOpenMode().abstractOpenMode) {
                 case Read:
-                    delegate = new FileReadTextRConnection(this);
+                    delegate = new FileReadTextRConnection(this, true);
                     break;
                 case Write:
                     delegate = new FileWriteTextRConnection(this, false);
@@ -87,7 +104,7 @@ public class FileConnections {
                     delegate = new FileReadBinaryRConnection(this);
                     break;
                 case WriteBinary:
-                    delegate = new FileWriteBinaryConnection(this, false);
+                    delegate = new FileWriteBinaryConnection(this, false, true);
                     break;
                 case ReadWriteTrunc:
                 case ReadWriteTruncBinary:
@@ -100,27 +117,62 @@ public class FileConnections {
         }
     }
 
-    static class FileReadTextRConnection extends DelegateReadRConnection implements ReadWriteHelper {
-        private InputStream inputStream;
+    private DelegateRConnection createDelegateConnection(BasePathRConnection base, OpenMode m) throws IOException {
+
+        // TODO (non-)blocking
+
+        DelegateRConnection delegate = null;
+        switch (m.abstractOpenMode) {
+            case Read:
+                delegate = new FileReadTextRConnection(base, true);
+                break;
+            case Write:
+                delegate = new FileWriteTextRConnection(base, false);
+                break;
+            case Append:
+                delegate = new FileWriteTextRConnection(base, true);
+                break;
+            case ReadBinary:
+                delegate = new FileReadBinaryRConnection(base);
+                break;
+            case WriteBinary:
+                delegate = new FileWriteBinaryConnection(base, false, true);
+                break;
+            case ReadWriteTrunc:
+            case ReadWriteTruncBinary:
+                delegate = new FileReadWriteConnection(base);
+                break;
+            default:
+                throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + m);
+        }
+        return delegate;
+    }
+
+    static class FileReadTextRConnection extends DelegateReadRConnection {
+
+        private final ReadableByteChannel channel;
 
-        FileReadTextRConnection(BasePathRConnection base) throws IOException {
+        FileReadTextRConnection(BasePathRConnection base, boolean blocking) throws IOException {
             super(base);
+
+            // FIXME: since streams are used to open the file, this is BLOCKING by default !
+
             // can be compressed - check for it
             RCompression.Type cType = RCompression.getCompressionType(base.path);
             switch (cType) {
                 case NONE:
-                    inputStream = new BufferedInputStream(new FileInputStream(base.path));
+                    channel = Files.newByteChannel(Paths.get(base.path), StandardOpenOption.READ);
                     break;
                 case GZIP:
-                    inputStream = new GZIPInputStream(new FileInputStream(base.path), CompressedConnections.GZIP_BUFFER_SIZE);
+                    channel = Channels.newChannel(new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE));
                     break;
                 case BZIP2:
                     // no in Java support, so go via byte array
                     byte[] bzipUdata = RCompression.bzipUncompressFromFile(base.path);
-                    inputStream = new ByteArrayInputStream(bzipUdata);
+                    channel = new SeekableMemoryByteChannel(bzipUdata);
                     break;
                 case XZ:
-                    inputStream = new XZInputStream(new FileInputStream(base.path));
+                    channel = Channels.newChannel(new XZInputStream(new FileInputStream(base.path)));
                     break;
                 default:
                     throw RError.nyi(RError.SHOW_CALLER2, "compression type: " + cType.name());
@@ -137,45 +189,48 @@ public class FileConnections {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
         }
 
-        @TruffleBoundary
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(inputStream, n, warn, skipNul);
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, inputStream, useBytes);
-        }
-
         @Override
-        public InputStream getInputStream() throws IOException {
-            return inputStream;
+        public ReadableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
+        public boolean isSeekable() {
+            // TODO Auto-generated method stub
+            return false;
         }
 
-        @Override
-        public void close() throws IOException {
-            inputStream.close();
-        }
     }
 
-    private static class FileWriteTextRConnection extends DelegateWriteRConnection implements ReadWriteHelper {
-        private final BufferedOutputStream outputStream;
+    private static class FileWriteTextRConnection extends DelegateWriteRConnection {
 
-        FileWriteTextRConnection(FileRConnection base, boolean append) throws IOException {
+        private final SeekableByteChannel channel;
+
+        /**
+         * Opens a file for writing.
+         *
+         * @param base The base connection.
+         * @param append If {@code true}, the file cursor is positioned at the end and write
+         *            operations append to the file. If {@code false}, the file will be truncated.
+         * @throws IOException
+         */
+        FileWriteTextRConnection(BasePathRConnection base, boolean append) throws IOException {
             super(base);
-            outputStream = new BufferedOutputStream(new FileOutputStream(base.path, append));
+            List<OpenOption> opts = new ArrayList<>();
+            opts.add(StandardOpenOption.WRITE);
+            opts.add(StandardOpenOption.CREATE);
+            if (append) {
+                opts.add(StandardOpenOption.APPEND);
+            } else {
+                opts.add(StandardOpenOption.TRUNCATE_EXISTING);
+            }
+
+            channel = Files.newByteChannel(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
         }
 
         @Override
         public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(outputStream, s, pad, eos);
+            ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
         }
 
         @Override
@@ -183,40 +238,24 @@ public class FileConnections {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
         }
 
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            writeLinesHelper(outputStream, lines, sep);
-            flush();
-        }
-
         @Override
         public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(outputStream, s, nl);
+            ReadWriteHelper.writeStringHelper(getChannel(), s, nl);
         }
 
         @Override
-        public OutputStream getOutputStream() throws IOException {
-            return outputStream;
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
+        public SeekableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
-        public void close() throws IOException {
-            outputStream.close();
+        public boolean isSeekable() {
+            return false;
         }
 
-        @Override
-        public void flush() throws IOException {
-            outputStream.flush();
-        }
     }
 
-    static class FileReadBinaryRConnection extends DelegateReadRConnection implements ReadWriteHelper {
+    static class FileReadBinaryRConnection extends DelegateReadRConnection {
         private final FileInputStream inputStream;
 
         FileReadBinaryRConnection(BasePathRConnection base) throws IOException {
@@ -225,28 +264,7 @@ public class FileConnections {
         }
 
         @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, inputStream, useBytes);
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            return inputStream.getChannel().read(buffer);
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            return readBinCharsHelper(inputStream);
-        }
-
-        @TruffleBoundary
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(inputStream, n, warn, skipNul);
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
+        public InputStream getInputStream() {
             return inputStream;
         }
 
@@ -267,7 +285,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             long position = inputStream.getChannel().position();
             switch (seekMode) {
                 case ENQUIRE:
@@ -286,64 +304,45 @@ public class FileConnections {
             }
             return position;
         }
-    }
-
-    private static class FileWriteBinaryConnection extends DelegateWriteRConnection implements ReadWriteHelper {
-        private final FileOutputStream outputStream;
-
-        FileWriteBinaryConnection(FileRConnection base, boolean append) throws IOException {
-            super(base);
-            outputStream = new FileOutputStream(base.path, append);
-        }
 
         @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(outputStream, s, pad, eos);
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            outputStream.getChannel().write(buffer);
+        public ReadableByteChannel getChannel() {
+            return inputStream.getChannel();
         }
+    }
 
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return outputStream;
-        }
+    private static class FileWriteBinaryConnection extends DelegateWriteRConnection {
 
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
+        private final SeekableByteChannel channel;
 
-        @Override
-        public void close() throws IOException {
-            flush();
-            outputStream.close();
-        }
+        FileWriteBinaryConnection(BasePathRConnection base, boolean append, boolean blocking) throws IOException {
+            super(base);
 
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            for (int i = 0; i < lines.getLength(); i++) {
-                String line = lines.getDataAt(i);
-                outputStream.write(line.getBytes());
-                outputStream.write(sep.getBytes());
+            List<OpenOption> args = new LinkedList<>();
+            args.add(StandardOpenOption.WRITE);
+            args.add(StandardOpenOption.CREATE);
+            if (append) {
+                args.add(StandardOpenOption.APPEND);
+            } else {
+                args.add(StandardOpenOption.TRUNCATE_EXISTING);
             }
+
+            channel = Files.newByteChannel(Paths.get(base.path), args.toArray(new OpenOption[args.size()]));
         }
 
         @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(outputStream, s, nl);
+        public WritableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
-        public void flush() throws IOException {
-            outputStream.flush();
+        public boolean isSeekable() {
+            return true;
         }
+
     }
 
-    private static class FileReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper {
+    private static class FileReadWriteConnection extends DelegateReadWriteRConnection {
         /*
          * This is a minimal implementation to support one specific use in package installation.
          *
@@ -368,7 +367,7 @@ public class FileConnections {
             }
         }
 
-        FileReadWriteConnection(FileRConnection base) throws IOException {
+        FileReadWriteConnection(BasePathRConnection base) throws IOException {
             super(base);
             OpenMode openMode = base.getOpenMode();
             String rafMode = null;
@@ -431,23 +430,7 @@ public class FileConnections {
         @Override
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
             raf.seek(readOffset);
-            return readLinesHelper(inputStream, n, warn, skipNul);
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
-            return inputStream;
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
+            return ReadWriteHelper.readLinesHelper(inputStream, n, warn, skipNul);
         }
 
         @Override
@@ -468,10 +451,6 @@ public class FileConnections {
             lastMode = SeekRWMode.WRITE;
         }
 
-        @Override
-        public void flush() throws IOException {
-        }
-
         @Override
         public void writeString(String s, boolean nl) throws IOException {
             raf.write(s.getBytes());
@@ -504,5 +483,225 @@ public class FileConnections {
         public byte[] readBinChars() throws IOException {
             throw RInternalError.unimplemented();
         }
+
+        @Override
+        public ByteChannel getChannel() {
+            return raf.getChannel();
+        }
+    }
+
+    /**
+     * Base class for all modes of gzfile/bzfile/xzfile connections. N.B. In GNU R these can read
+     * gzip, bzip, lzma and uncompressed files, and this has to be implemented by reading the first
+     * few bytes of the file and detecting the type of the file.
+     */
+    public static class CompressedRConnection extends BasePathRConnection {
+        private final RCompression.Type cType;
+        @SuppressWarnings("unused") private final String encoding; // TODO
+        @SuppressWarnings("unused") private final int compression; // TODO
+
+        public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException {
+            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary);
+            this.cType = cType;
+            this.encoding = encoding;
+            this.compression = compression;
+            openNonLazyConnection();
+        }
+
+        private static ConnectionClass mapConnectionClass(RCompression.Type cType) {
+            switch (cType) {
+                case NONE:
+                    return ConnectionClass.File;
+                case GZIP:
+                    return ConnectionClass.GZFile;
+                case BZIP2:
+                    return ConnectionClass.BZFile;
+                case XZ:
+                    return ConnectionClass.XZFile;
+                default:
+                    throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            DelegateRConnection delegate = null;
+            AbstractOpenMode openMode = getOpenMode().abstractOpenMode;
+            switch (openMode) {
+                case Read:
+                case ReadBinary:
+                    /*
+                     * For input, we check the actual compression type as GNU R is permissive about
+                     * the claimed type.
+                     */
+                    RCompression.Type cTypeActual = RCompression.getCompressionType(path);
+                    if (cTypeActual != cType) {
+                        updateConnectionClass(mapConnectionClass(cTypeActual));
+                    }
+                    switch (cTypeActual) {
+                        case NONE:
+                            if (openMode == AbstractOpenMode.ReadBinary) {
+                                delegate = new FileConnections.FileReadBinaryRConnection(this);
+                            } else {
+                                delegate = new FileConnections.FileReadTextRConnection(this, true);
+                            }
+                            break;
+                        case GZIP:
+                            delegate = new CompressedInputRConnection(this, new GZIPInputStream(new FileInputStream(path), GZIP_BUFFER_SIZE), true);
+                            break;
+                        case XZ:
+                            delegate = new CompressedInputRConnection(this, new XZInputStream(new FileInputStream(path)), false);
+                            break;
+                        case BZIP2:
+                            // no in Java support, so go via byte array
+                            byte[] bzipUdata = RCompression.bzipUncompressFromFile(path);
+                            delegate = new ByteStreamCompressedInputRConnection(this, new ByteArrayInputStream(bzipUdata), false);
+                    }
+                    break;
+
+                case Append:
+                case AppendBinary:
+                case Write:
+                case WriteBinary: {
+                    boolean append = openMode == AbstractOpenMode.Append || openMode == AbstractOpenMode.AppendBinary;
+                    switch (cType) {
+                        case GZIP:
+                            delegate = new CompressedOutputRConnection(this, new GZIPOutputStream(new FileOutputStream(path, append), GZIP_BUFFER_SIZE), true);
+                            break;
+                        case BZIP2:
+                            delegate = new BZip2OutputRConnection(this, new ByteArrayOutputStream(), append);
+                            break;
+                        case XZ:
+                            delegate = new CompressedOutputRConnection(this, new XZOutputStream(new FileOutputStream(path, append), new LZMA2Options(), XZ.CHECK_CRC32), false);
+                            break;
+                    }
+                    break;
+                }
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
+            }
+            setDelegate(delegate);
+        }
+
+        // @Override
+        /**
+         * GnuR behavior for lazy connections is odd, e.g. gzfile returns "text", even though the
+         * default mode is "rb".
+         */
+        // public boolean isTextMode() {
+        // }
+    }
+
+    private static class CompressedInputRConnection extends DelegateReadRConnection {
+        private final InputStream inputStream;
+        private final boolean seekable;
+
+        protected CompressedInputRConnection(CompressedRConnection base, InputStream is, boolean seekable) {
+            super(base);
+            this.inputStream = is;
+            this.seekable = seekable;
+        }
+
+        @Override
+        public ReadableByteChannel getChannel() {
+            return Channels.newChannel(inputStream);
+        }
+
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            if (seekable) {
+                // TODO
+            }
+            return super.seekInternal(offset, seekMode, seekRWMode);
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return seekable;
+        }
+    }
+
+    private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection {
+        ByteStreamCompressedInputRConnection(CompressedRConnection base, ByteArrayInputStream is, boolean seekable) {
+            super(base, is, seekable);
+        }
+    }
+
+    private static class CompressedOutputRConnection extends DelegateWriteRConnection {
+        protected OutputStream outputStream;
+        private final WritableByteChannel channel;
+        private final boolean seekable;
+        private long seekPosition = 0L;
+
+        protected CompressedOutputRConnection(CompressedRConnection base, OutputStream os, boolean seekable) {
+            super(base);
+            this.outputStream = os;
+            this.channel = Channels.newChannel(os);
+            this.seekable = seekable;
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            return outputStream;
+        }
+
+        @Override
+        public void closeAndDestroy() throws IOException {
+            base.closed = true;
+            close();
+        }
+
+        @Override
+        public void close() throws IOException {
+            flush();
+            outputStream.close();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            outputStream.flush();
+        }
+
+        @Override
+        public WritableByteChannel getChannel() {
+            return channel;
+        }
+
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            if (seekable) {
+                // TODO GZIP is basically seekable; however, the output stream does not allow any
+                // seeking
+                long oldPos = seekPosition;
+                seekPosition = offset;
+                return oldPos;
+            }
+            return super.seekInternal(offset, seekMode, seekRWMode);
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return seekable;
+        }
+    }
+
+    private static class BZip2OutputRConnection extends CompressedOutputRConnection {
+        private final ByteArrayOutputStream bos;
+        private final boolean append;
+
+        BZip2OutputRConnection(CompressedRConnection base, ByteArrayOutputStream os, boolean append) {
+            super(base, os, false);
+            this.bos = os;
+            this.append = append;
+        }
+
+        @Override
+        public void close() throws IOException {
+            flush();
+            outputStream.close();
+            // Now actually do the compression using sub-process
+            byte[] data = bos.toByteArray();
+            RCompression.bzipCompressToFile(data, ((BasePathRConnection) base).path, append);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index b699372cca..7c9d9847ea 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -30,6 +30,7 @@ import java.util.LinkedList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
@@ -259,9 +260,22 @@ public abstract class RConnection implements AutoCloseable {
     public abstract boolean isSeekable();
 
     /**
-     * Support for {@code seek} Internal.
+     * Support for {@code seek} Internal. Also clears push back lines.
      */
-    public abstract long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException;
+    public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        if (isSeekable()) {
+            // discard any push back strings
+            pushBackClear();
+
+            return seekInternal(offset, seekMode, seekRWMode);
+        }
+        throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_ENABLED);
+    }
+
+    /**
+     * Allows to seek in the connection.
+     */
+    protected abstract long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException;
 
     /**
      * Internal support for reading one character at a time.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index ac220dafd9..dc2310798b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -23,22 +23,16 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.channels.SeekableByteChannel;
 import java.util.Objects;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class RawConnections {
 
@@ -98,7 +92,7 @@ public class RawConnections {
             return channel.getBuffer();
         }
 
-        public static long seek(SeekableMemoryByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
+        private static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
             final long origPos = channel.position();
             final long newPos;
             switch (seekMode) {
@@ -121,7 +115,7 @@ public class RawConnections {
 
     }
 
-    static class RawReadRConnection extends DelegateReadRConnection implements ReadWriteHelper {
+    static class RawReadRConnection extends DelegateReadRConnection {
         private SeekableMemoryByteChannel channel;
 
         RawReadRConnection(BaseRConnection base, SeekableMemoryByteChannel channel) {
@@ -138,11 +132,6 @@ public class RawConnections {
             super(base);
         }
 
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            return channel.read(buffer);
-        }
-
         @Override
         public byte[] readBinChars() throws IOException {
             // acquire copy from buffer without advancing the cursor
@@ -159,45 +148,23 @@ public class RawConnections {
             return new byte[0];
         }
 
-        @TruffleBoundary
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(channel.getInputStream(), n, warn, skipNul);
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, channel.getInputStream(), useBytes);
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
-            return channel.getInputStream();
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
-
         @Override
-        public void close() throws IOException {
-            channel.close();
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
         @Override
-        public OutputStream getOutputStream() {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_AN_OUTPUT_RAW_CONNECTION);
+        public SeekableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
+        public boolean isSeekable() {
+            return true;
         }
     }
 
-    private static class RawWriteBinaryConnection extends DelegateWriteRConnection implements ReadWriteHelper {
+    private static class RawWriteBinaryConnection extends DelegateWriteRConnection {
         private final SeekableMemoryByteChannel channel;
 
         RawWriteBinaryConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
@@ -212,11 +179,6 @@ public class RawConnections {
             }
         }
 
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(channel.getOutputStream(), s, pad, eos);
-        }
-
         @Override
         public void writeBin(ByteBuffer buffer) throws IOException {
             channel.write(buffer);
@@ -228,52 +190,31 @@ public class RawConnections {
         }
 
         @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
-
-        @Override
-        public void close() throws IOException {
-            flush();
-            channel.close();
-        }
-
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            for (int i = 0; i < lines.getLength(); i++) {
-                String line = lines.getDataAt(i);
-                channel.write(line.getBytes());
-                channel.write(sep.getBytes());
-            }
-        }
-
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(channel.getOutputStream(), s, nl);
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
         @Override
-        public void flush() throws IOException {
-            // nothing to do
+        public SeekableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
+        public boolean isSeekable() {
+            return true;
         }
     }
 
-    private static class RawReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper {
+    private static class RawReadWriteConnection extends DelegateReadWriteRConnection {
 
         private final SeekableMemoryByteChannel channel;
 
         protected RawReadWriteConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
             super(base);
-            this.channel = Objects.requireNonNull(channel);
-            if (!append) {
+            this.channel = channel;
+            if (append) {
                 try {
-                    channel.position(0);
+                    channel.position(channel.size());
                 } catch (IOException e) {
                     RInternalError.shouldNotReachHere();
                 }
@@ -281,79 +222,18 @@ public class RawConnections {
         }
 
         @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
-            return channel.getInputStream();
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return channel.getOutputStream();
-        }
-
-        @Override
-        public void closeAndDestroy() throws IOException {
-            close();
-        }
-
-        @Override
-        public void close() throws IOException {
-            channel.close();
-        }
-
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            for (int i = 0; i < lines.getLength(); i++) {
-                channel.write(lines.getDataAt(i).getBytes());
-                channel.write(sep.getBytes());
-            }
-        }
-
-        @Override
-        public void flush() throws IOException {
-            // nothing to do
-        }
-
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            channel.write(s.getBytes());
-            if (nl) {
-                channel.write(System.lineSeparator().getBytes());
-            }
-        }
-
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(channel.getOutputStream(), s, pad, eos);
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, channel.getInputStream(), useBytes);
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            channel.write(buffer);
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            return channel.read(buffer);
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
         @Override
-        public byte[] readBinChars() throws IOException {
-            throw RInternalError.unimplemented();
+        public SeekableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
+        public boolean isSeekable() {
+            return true;
         }
 
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
index ebeca0685c..1d0b0c52f3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
@@ -5,11 +5,17 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.RConnection.SeekMode;
+import com.oracle.truffle.r.runtime.conn.RConnection.SeekRWMode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.sun.istack.internal.NotNull;
 
 public class ReadWriteHelper {
 
@@ -77,27 +83,46 @@ public class ReadWriteHelper {
         return result;
     }
 
-    public static void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep) throws IOException {
+    public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep) throws IOException {
         for (int i = 0; i < lines.getLength(); i++) {
-            out.write(lines.getDataAt(i).getBytes());
-            out.write(sep.getBytes());
+            final String line = lines.getDataAt(i);
+            writeStringHelper(out, line, false);
+            writeStringHelper(out, sep, false);
         }
     }
 
-    public static void writeStringHelper(ByteChannel out, String s, boolean nl) throws IOException {
-        ByteBuffer buf = ByteBuffer.allocate(s.length() + 1);
-        buf.put(s.getBytes());
+    public static void writeStringHelper(WritableByteChannel out, String s, boolean nl) throws IOException {
+        final byte[] bytes = s.getBytes();
+        final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes() : null;
+
+        ByteBuffer buf = ByteBuffer.allocate(bytes.length + (nl ? lineSepBytes.length : 0));
+        buf.put(bytes);
         if (nl) {
-            buf.putChar('\n');
+            buf.put(lineSepBytes);
         }
+
         buf.rewind();
         out.write(buf);
     }
 
-    public static void writeCharHelper(ByteChannel channel, String s, int pad, String eos) throws IOException {
+    /**
+     * Writes characters in binary mode (without any re-encoding) to the provided channel.
+     *
+     * @param channel The writable byte channel to write to (must not be {@code null}).
+     * @param s The character string to write (must not be {@code null}).
+     * @param pad The number of null characters to append to the characters.
+     * @param eos The end-of-string terminator (may be {@code null}).
+     * @throws IOException
+     */
+    public static void writeCharHelper(@NotNull WritableByteChannel channel, @NotNull String s, int pad, String eos) throws IOException {
 
-        ByteBuffer buf = ByteBuffer.allocate(s.length() + pad + eos.length() + 1);
-        buf.put(s.getBytes());
+        final byte[] bytes = s.getBytes();
+        final byte[] eosBytes = eos != null ? eos.getBytes() : null;
+
+        final int bufLen = bytes.length + (pad > 0 ? pad : 0) + (eos != null ? eosBytes.length + 1 : 0);
+        assert bufLen >= s.length();
+        ByteBuffer buf = ByteBuffer.allocate(bufLen);
+        buf.put(bytes);
         if (pad > 0) {
             for (int i = 0; i < pad; i++) {
                 buf.put((byte) 0);
@@ -123,7 +148,7 @@ public class ReadWriteHelper {
     }
 
     /**
-     * Reads null-terminated character strings from an {@link InputStream}.
+     * Reads null-terminated character strings from a {@link InputStream}.
      */
     public static byte[] readBinCharsHelper(InputStream in) throws IOException {
         int ch = in.read();
@@ -155,16 +180,40 @@ public class ReadWriteHelper {
         return totalRead;
     }
 
-    public static String readCharHelper(int nchars, InputStream in, @SuppressWarnings("unused") boolean useBytes) throws IOException {
-        byte[] bytes = new byte[nchars];
-        in.read(bytes);
+    public static String readCharHelper(int nchars, ReadableByteChannel channel, @SuppressWarnings("unused") boolean useBytes) throws IOException {
+        ByteBuffer buf = ByteBuffer.allocate(nchars);
+        channel.read(buf);
         int j = 0;
-        for (; j < bytes.length; j++) {
+        for (; j < buf.position(); j++) {
             // strings end at 0
-            if (bytes[j] == 0) {
+            if (buf.get(j) == 0) {
                 break;
             }
         }
-        return new String(bytes, 0, j);
+
+        return new String(buf.array(), 0, j);
+    }
+
+    /**
+     * TODO probably, this method belongs to {@link ConnectionSupport}
+     */
+    public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        long position = channel.position();
+        switch (seekMode) {
+            case ENQUIRE:
+                break;
+            case CURRENT:
+                if (offset != 0) {
+                    channel.position(position + offset);
+                }
+                break;
+            case START:
+                channel.position(offset);
+                break;
+            case END:
+                throw RInternalError.unimplemented();
+
+        }
+        return position;
     }
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
index 79dd7dfe9e..c625c855a3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -89,7 +89,7 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
         this(clp2(Objects.requireNonNull(initialBuffer).length));
         assert buf.length >= initialBuffer.length;
         endPos = initialBuffer.length;
-        position = initialBuffer.length;
+        position = 0L;
         System.arraycopy(initialBuffer, 0, buf, 0, initialBuffer.length);
     }
 
@@ -105,9 +105,10 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
         }
         Objects.requireNonNull(dst);
         RInternalError.guarantee(dst.remaining() <= Integer.MAX_VALUE);
-        final int nCanRead = (int) Math.min(dst.remaining(), size());
+        final int nCanRead = (int) Math.min(dst.remaining(), remaining());
         dst.put(buf, (int) (position - offset), nCanRead);
         position += nCanRead;
+        assert position <= endPos;
         return nCanRead;
     }
 
@@ -181,11 +182,18 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
         return endPos - offset;
     }
 
+    private long remaining() {
+        return endPos - position;
+    }
+
     @Override
     public SeekableByteChannel position(long newPosition) throws IOException {
         if (newPosition < 0) {
             throw new IllegalArgumentException("newPosition must not be negative");
         }
+        if (newPosition + offset > endPos) {
+            throw new IllegalArgumentException("setting position outside data range is currently not supported");
+        }
         position = newPosition + offset;
         return this;
     }
@@ -224,10 +232,13 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
     }
 
     public int read() throws IOException {
-        final ByteBuffer bf = ByteBuffer.allocate(1);
-        read(bf);
-        bf.rewind();
-        return bf.get();
+        if (position < endPos) {
+            final ByteBuffer bf = ByteBuffer.allocate(1);
+            read(bf);
+            bf.rewind();
+            return bf.get();
+        }
+        return -1;
     }
 
     private class SyncOS extends OutputStream {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index 815792173f..becf859cb1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -28,15 +28,13 @@ import java.io.OutputStream;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
-import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
 import java.nio.channels.SocketChannel;
 
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadWriteRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class SocketConnections {
     /**
@@ -74,7 +72,7 @@ public class SocketConnections {
         }
     }
 
-    private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection implements ReadWriteHelper {
+    private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection {
         private Socket socket;
         private SocketChannel socketChannel;
         protected InputStream inputStream;
@@ -105,68 +103,33 @@ public class SocketConnections {
 
         @Override
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(inputStream, n, warn, skipNul);
+            return ReadWriteHelper.readLinesHelper(inputStream, n, warn, skipNul);
         }
 
         @Override
-        public InputStream getInputStream() throws IOException {
-            return inputStream;
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return outputStream;
-        }
-
-        @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            writeLinesHelper(outputStream, lines, sep);
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            writeBinHelper(buffer, outputStream);
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            return readBinHelper(buffer, inputStream);
-        }
-
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            writeCharHelper(outputStream, s, pad, eos);
-        }
-
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            writeStringHelper(outputStream, s, nl);
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, inputStream, useBytes);
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            return readBinCharsHelper(inputStream);
+        public void flush() {
+            // TODO add "throws"
+            try {
+                outputStream.flush();
+            } catch (IOException e) {
+                RInternalError.shouldNotReachHere();
+            }
         }
 
         @Override
-        public void flush() throws IOException {
-            outputStream.flush();
+        public void close() throws IOException {
+            // TODO(fa) I'm not sure if socket.close() is the same as channel.close()
+            socket.close();
         }
 
         @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
+        public ByteChannel getChannel() {
+            return socketChannel;
         }
 
         @Override
-        public void close() throws IOException {
-            socket.close();
+        public boolean isSeekable() {
+            return false;
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index 9434f758c4..aad53cdb61 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -23,9 +23,10 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -33,9 +34,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateWriteRConnection;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -115,44 +113,25 @@ public class TextConnections {
             return result;
         }
 
-        @SuppressWarnings("hiding")
         @Override
-        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
+        public String[] getValue() {
+            // TODO refactor
             throw RInternalError.shouldNotReachHere();
         }
 
         @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-        }
-
-        @Override
-        public void close() {
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            throw RError.nyi(null, "readBin on text connection");
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            throw RError.nyi(null, "readBinChars on text connection");
+        public void close() throws IOException {
+            // nothing to do
         }
 
         @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            throw RError.nyi(null, "readChar on text connection");
+        public ReadableByteChannel getChannel() {
+            throw RInternalError.shouldNotReachHere();
         }
 
         @Override
-        public String[] getValue() {
-            throw RError.nyi(null, "textConnectionValue");
+        public boolean isSeekable() {
+            return false;
         }
     }
 
@@ -315,6 +294,22 @@ public class TextConnections {
                 throw RInternalError.unimplemented();
             }
         }
+
+        @Override
+        public WritableByteChannel getChannel() {
+            // no channel available for a text connection
+            return null;
+        }
+
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_RELEVANT_FOR_TEXT_CON);
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
     }
 
     /**
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index add7bb79e5..1b76ab39b5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -27,14 +27,13 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.DelegateReadRConnection;
 
 public class URLConnections {
     public static class URLRConnection extends BaseRConnection {
@@ -64,7 +63,7 @@ public class URLConnections {
         }
     }
 
-    private static class URLReadRConnection extends DelegateReadRConnection implements ReadWriteHelper {
+    private static class URLReadRConnection extends DelegateReadRConnection {
 
         private final BufferedInputStream inputStream;
 
@@ -75,39 +74,23 @@ public class URLConnections {
         }
 
         @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            throw RError.nyi(null, "readBin on URL");
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            throw RError.nyi(null, "readBinChars on URL");
-        }
-
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return readLinesHelper(inputStream, n, warn, skipNul);
-        }
-
-        @Override
-        public InputStream getInputStream() throws IOException {
+        public InputStream getInputStream() {
             return inputStream;
         }
 
         @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
+        public void close() throws IOException {
+            inputStream.close();
         }
 
         @Override
-        public void close() throws IOException {
-            inputStream.close();
+        public ReadableByteChannel getChannel() {
+            return Channels.newChannel(inputStream);
         }
 
         @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            return readCharHelper(nchars, inputStream, useBytes);
+        public boolean isSeekable() {
+            return false;
         }
     }
 }
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 4e3506d9a4..5e57f9ebb8 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
@@ -21071,6 +21071,44 @@ Levels: c f h k m n p x
 [1000] 1
 Levels: 0 1
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenInexisting#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+#{ zz <- fifo("/tmp/pipe3408688236", "r"); close(zz); }
+Error in fifo("/tmp/pipe3408688236", "r") : cannot open the connection
+In addition: Warning message:
+In fifo("/tmp/pipe3408688236", "r") :
+  cannot open fifo '/tmp/pipe3408688236'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenNonBlocking#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+#{ zz <- fifo("/tmp/pipe3408688236", "r"); close(zz); }
+Error in fifo("/tmp/pipe3408688236", "r") : cannot open the connection
+In addition: Warning message:
+In fifo("/tmp/pipe3408688236", "r") :
+  cannot open fifo '/tmp/pipe3408688236'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fileConnection.testFileSummary#
+#{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res }
+$description
+[1] "/tmp/gzipped_____5137528280012599068___.gz"
+
+$class
+[1] "gzfile"
+
+$mode
+[1] "r"
+
+$text
+[1] "text"
+
+$opened
+[1] "opened"
+
+$`can read`
+[1] "yes"
+
+$`can write`
+[1] "no"
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_fileaccess.testfileaccess1#
 #argv <- list(character(0), 0); .Internal(file.access(argv[[1]], argv[[2]]))
 integer(0)
@@ -65505,6 +65543,15 @@ Error in tempfile(character()) : no 'pattern'
 #{ tempfile(integer()) }
 Error in tempfile(integer()) : invalid filename pattern
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_textConnection.testSeek#
+#{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res }
+[1] FALSE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_textConnection.testSeek#
+#{ zz <- textConnection("Hello, World!"); res <- seek(zz, 5); close(zz); res }
+Error in seek.connection(zz, 5) :
+  seek is not relevant for text connection
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_times_difftime.testtimes_difftime1#
 #argv <- structure(list(e1 = 2, e2 = structure(c(3.33333333333333,     683.25), units = 'mins', class = 'difftime')), .Names = c('e1',     'e2'));do.call('*.difftime', argv)
 Time differences in mins
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
new file mode 100644
index 0000000000..1a359a3dc5
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+public class TestBuiltin_fifoConnection extends TestBase {
+
+    private static List<Path> TEMP_FIFOS = new ArrayList<>();
+
+    @BeforeClass
+    public static void setup() {
+        Path path = Paths.get(System.getProperty("java.io.tmpdir"));
+        TEMP_FIFOS.add(path.resolve("pipe3408688236"));
+        TEMP_FIFOS.add(path.resolve("pipe4039819292"));
+    }
+
+    @Test
+    public void testFifoOpenInexisting() {
+        Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
+        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
+    }
+
+    @Test(timeout = 100)
+    public void testFifoOpenNonBlocking() {
+        Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
+        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
+    }
+
+    @AfterClass
+    public static void cleanup() {
+        for (Path p : TEMP_FIFOS) {
+            try {
+                Files.delete(p);
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java
new file mode 100644
index 0000000000..a9aa9409bb
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.zip.GZIPOutputStream;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+/**
+ * Class tests basic file connection functionality.
+ */
+// Checkstyle: stop line length check
+public class TestBuiltin_fileConnection extends TestBase {
+
+    private static Path TEMP_FILE_GZIP;
+
+    @BeforeClass
+    public static void setup() throws IOException {
+        Path path = Paths.get(System.getProperty("java.io.tmpdir"));
+
+        // create a gzipped file
+        TEMP_FILE_GZIP = path.resolve("gzipped_____5137528280012599068___.gz");
+        OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(TEMP_FILE_GZIP, StandardOpenOption.WRITE, StandardOpenOption.CREATE));
+        gzos.write("Hello, World!".getBytes());
+        gzos.close();
+    }
+
+    @Test
+    public void testFileSummary() {
+
+        Assert.assertTrue("Could not create required temp file for test.", Files.exists(TEMP_FILE_GZIP));
+        assertEval("{ zz <- file(\"" + TEMP_FILE_GZIP + "\", \"r\"); res <- summary(zz); close(zz); res }");
+    }
+
+    @AfterClass
+    public static void cleanup() throws IOException {
+        Files.delete(TEMP_FILE_GZIP);
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java
new file mode 100644
index 0000000000..27ab9b5144
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+public class TestBuiltin_textConnection extends TestBase {
+
+    @Test
+    public void testReadAppendText() {
+    }
+
+    @Test
+    public void testReadWriteText() {
+    }
+
+    @Test
+    public void testWriteText() {
+    }
+
+    @Test
+    public void testWriteBinary() {
+    }
+
+    @Test
+    public void testSeek() {
+        assertEval("{ zz <- textConnection(\"Hello, World!\"); res <- isSeekable(zz); close(zz); res }");
+        assertEval("{ zz <- textConnection(\"Hello, World!\"); res <- seek(zz, 5); close(zz); res }");
+    }
+
+}
-- 
GitLab


From 7b2387501dd7a7796906cbb4d18d1e07298f6b62 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 22 Feb 2017 18:02:51 +0100
Subject: [PATCH 066/402] Implemented FIFOs and tried to get them non-blocking
 on opening. This seems not to be easily possible from Java. Added more tests
 and implemented some small missing functionality. Refactored file and
 compressed file connection implementation. Added encoding support for files.
 Made some cleanup.

---
 .../r/nodes/builtin/base/BasePackage.java     |   1 +
 .../r/nodes/builtin/base/Capabilities.java    |   2 +-
 .../builtin/base/ConnectionFunctions.java     |  32 ++-
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../r/runtime/conn/CompressedConnections.java |  54 ----
 .../r/runtime/conn/ConnectionSupport.java     |  96 ++++++-
 .../runtime/conn/DelegateReadRConnection.java |   2 +-
 .../conn/DelegateReadWriteRConnection.java    |   6 +-
 .../conn/DelegateWriteRConnection.java        |   4 +-
 .../r/runtime/conn/FifoConnections.java       | 126 +++++++++-
 .../r/runtime/conn/FileConnections.java       | 235 ++++++++++--------
 .../truffle/r/runtime/conn/RConnection.java   |  13 +
 .../r/runtime/conn/RawConnections.java        |   2 +-
 .../r/runtime/conn/ReadWriteHelper.java       |  23 +-
 .../r/runtime/conn/SocketConnections.java     |  14 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 122 ++++++---
 .../builtins/TestBuiltin_fifoConnection.java  |   2 +
 .../builtins/TestBuiltin_fileConnection.java  |  71 ------
 .../builtins/TestBuiltin_textConnection.java  |  54 ----
 .../builtins/connection/R/fifo_GnuR_example.R |   9 +
 .../connection/R/readLines_GnuR_example.R     |  15 ++
 .../builtins/connection/R/textConnection.R    |  30 +++
 .../r/test/library/base/TestConnections.java  | 104 +++++++-
 23 files changed, 643 insertions(+), 377 deletions(-)
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 144dd28313..97135250de 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -278,6 +278,7 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.WriteBin.class, ConnectionFunctionsFactory.WriteBinNodeGen::create);
         add(ConnectionFunctions.WriteChar.class, ConnectionFunctionsFactory.WriteCharNodeGen::create);
         add(ConnectionFunctions.WriteLines.class, ConnectionFunctionsFactory.WriteLinesNodeGen::create);
+        add(ConnectionFunctions.IsIncomplete.class, ConnectionFunctionsFactory.IsIncompleteNodeGen::create);
         add(Contributors.class, ContributorsNodeGen::create);
         add(CopyDFAttr.class, CopyDFAttrNodeGen::create);
         add(Crossprod.class, CrossprodNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
index 109ddc233b..b63bb9fb4e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
@@ -46,7 +46,7 @@ public abstract class Capabilities extends RBuiltinNode {
         http_fttp(true, "http/ftp"),
         sockets(true, null),
         libxml(false, null),
-        fifo(false, null),
+        fifo(true, null),
         cledit(false, null),
         iconv(false, null),
         nls(false, "NLS"),
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index baf8368617..fb1e07a5bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -53,6 +53,8 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.DoubleBuffer;
 import java.nio.IntBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -69,6 +71,7 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.FifoConnections.FifoRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.CompressedRConnection;
@@ -209,8 +212,7 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        @SuppressWarnings("unused")
-        protected RAbstractIntVector file(String description, String openArg, boolean blocking, String encoding, String method, boolean raw) {
+        protected RAbstractIntVector file(String description, String openArg, @SuppressWarnings("unused") boolean blocking, String encoding, @SuppressWarnings("unused") String method, boolean raw) {
             String open = openArg;
             // TODO handle http/ftp prefixes and redirect and method
             String path = removeFileURLPrefix(description);
@@ -226,10 +228,13 @@ public abstract class ConnectionFunctions {
                 }
             }
             try {
-                return new FileRConnection(path, open).asVector();
+                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
+                return new FileRConnection(path, open, charset).asVector();
             } catch (IOException ex) {
                 warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
+            } catch (IllegalCharsetNameException ex) {
+                throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -259,9 +264,12 @@ public abstract class ConnectionFunctions {
         @TruffleBoundary
         protected RAbstractIntVector zzFile(RAbstractStringVector description, String open, String encoding, int compression) {
             try {
-                return new CompressedRConnection(description.getDataAt(0), open, cType, encoding, compression).asVector();
+                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
+                return new CompressedRConnection(description.getDataAt(0), open, cType, charset, compression).asVector();
             } catch (IOException ex) {
                 throw reportError(description.getDataAt(0), ex);
+            } catch (IllegalCharsetNameException ex) {
+                throw RError.error(this, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
 
@@ -1228,4 +1236,20 @@ public abstract class ConnectionFunctions {
             }
         }
     }
+
+    @RBuiltin(name = "isIncomplete", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
+    public abstract static class IsIncomplete extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(IsIncomplete.class);
+            CastsHelper.connection(casts);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected boolean isIncomplete(int con) {
+
+            return RConnection.fromIndex(con).isIncomplete();
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 20cb51447e..287dc010fb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -834,7 +834,8 @@ public final class RError extends RuntimeException {
         VECTOR_IS_TOO_LARGE("vector is too large"),
         SEEK_NOT_RELEVANT_FOR_TEXT_CON("seek is not relevant for text connection"),
         SEEK_NOT_ENABLED("'seek' not enabled for this connection"),
-        CANNOT_OPEN_FIFO("cannot open fifo '%s'");
+        CANNOT_OPEN_FIFO("cannot open fifo '%s'"),
+        UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
deleted file mode 100644
index 3786c9d900..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/CompressedConnections.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.conn;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-
-import org.tukaani.xz.LZMA2Options;
-import org.tukaani.xz.XZ;
-import org.tukaani.xz.XZInputStream;
-import org.tukaani.xz.XZOutputStream;
-
-import com.oracle.truffle.r.runtime.RCompression;
-import com.oracle.truffle.r.runtime.RCompression.Type;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-public class CompressedConnections {
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 57d17adc6f..d90cb05986 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -29,6 +29,7 @@ import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -491,6 +492,18 @@ public class ConnectionSupport {
      * it subsequently will throw an error. The latter will open/close the connection (internally)
      * and this can be repeated indefinitely.
      */
+    /**
+     * @author fa
+     *
+     */
+    /**
+     * @author fa
+     *
+     */
+    /**
+     * @author fa
+     *
+     */
     public abstract static class BaseRConnection extends RConnection {
 
         /**
@@ -525,6 +538,13 @@ public class ConnectionSupport {
          */
         private int descriptor;
 
+        private boolean blocking = true;
+
+        /**
+         * The encoding to use to read or to write to the connection.
+         */
+        private Charset encoding;
+
         private ConnectionClass conClass;
 
         /**
@@ -533,13 +553,55 @@ public class ConnectionSupport {
          * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File}
          * @param modeString the mode in which the connection should be opened, "" for lazy opening
          * @param defaultModeForLazy the mode to use when this connection is opened implicitly
+         * @param blocking Indicates if this connection has been openend in blocking mode.
+         * @param encoding The encoding used to read from or to write to the connection.
          *
          */
-        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy) throws IOException {
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, boolean blocking, Charset encoding) throws IOException {
             this(conClass, new OpenMode(modeString, defaultModeForLazy));
             if (conClass != ConnectionClass.Internal) {
                 this.descriptor = getContextStateImpl().setConnection(this);
             }
+            this.blocking = blocking;
+            this.encoding = encoding;
+        }
+
+        /**
+         * The constructor for every connection class except {@link StdConnections}.
+         *
+         * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File}
+         * @param modeString the mode in which the connection should be opened, "" for lazy opening
+         * @param defaultModeForLazy the mode to use when this connection is opened implicitly
+         * @param blocking Indicates if this connection has been openend in blocking mode.
+         *
+         */
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, boolean blocking) throws IOException {
+            this(conClass, modeString, defaultModeForLazy, blocking, null);
+        }
+
+        /**
+         * The constructor for every connection class except {@link StdConnections}.
+         *
+         * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File}
+         * @param modeString the mode in which the connection should be opened, "" for lazy opening
+         * @param defaultModeForLazy the mode to use when this connection is opened implicitly
+         * @param encoding The encoding used to read from or to write to the connection.
+         *
+         */
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, Charset encoding) throws IOException {
+            this(conClass, modeString, defaultModeForLazy, true, encoding);
+        }
+
+        /**
+         * The constructor for every connection class except {@link StdConnections}.
+         *
+         * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File}
+         * @param modeString the mode in which the connection should be opened, "" for lazy opening
+         * @param defaultModeForLazy the mode to use when this connection is opened implicitly
+         *
+         */
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy) throws IOException {
+            this(conClass, modeString, defaultModeForLazy, true, Charset.defaultCharset());
         }
 
         /**
@@ -617,6 +679,17 @@ public class ConnectionSupport {
             return getOpenMode().isText();
         }
 
+        public boolean isBlocking() {
+            return blocking;
+        }
+
+        /**
+         * Returns the original encoding string.
+         */
+        public Charset getEncoding() {
+            return encoding;
+        }
+
         @Override
         public RConnection forceOpen(String modeString) throws IOException {
             if (closed) {
@@ -817,12 +890,12 @@ public class ConnectionSupport {
     abstract static class BasePathRConnection extends BaseRConnection {
         protected final String path;
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString) throws IOException {
-            this(path, connectionClass, modeString, AbstractOpenMode.Read);
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, Charset encoding) throws IOException {
+            this(path, connectionClass, modeString, AbstractOpenMode.Read, encoding);
         }
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode) throws IOException {
-            super(connectionClass, modeString, defaultLazyOpenMode);
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, Charset encoding) throws IOException {
+            super(connectionClass, modeString, defaultLazyOpenMode, encoding);
             this.path = Utils.tildeExpand(path);
         }
 
@@ -831,4 +904,17 @@ public class ConnectionSupport {
             return path;
         }
     }
+
+    /**
+     * Converts between character set names of iconv and Java.
+     *
+     * @param encoding The iconv name of the character set to use.
+     * @return The Java name of the character set to use.
+     */
+    public static String convertEncodingName(String encoding) {
+        if (encoding == null || encoding.isEmpty() || "native.enc".equals(encoding)) {
+            return Charset.defaultCharset().name();
+        }
+        return encoding;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index ae12d89797..96b1ef006d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -62,7 +62,7 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul);
+        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul, base.getSummaryDescription(), base.getEncoding());
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 0b34b4ee82..ce50eff302 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -51,7 +51,7 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul);
+        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul, base.getSummaryDescription(), base.getEncoding());
     }
 
     @Override
@@ -95,12 +95,12 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep);
+        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getChannel(), s, nl);
+        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index c3c38def14..25028a9ef1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -95,12 +95,12 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep);
+        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getChannel(), s, nl);
+        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index 475a550117..43a27a0faf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -27,7 +27,12 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
 import java.lang.ProcessBuilder.Redirect;
+import java.nio.channels.FileChannel;
 import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.OpenOption;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
 import java.util.Arrays;
 
 import com.oracle.truffle.r.runtime.ProcessOutputManager;
@@ -43,13 +48,24 @@ public class FifoConnections {
         private final String path;
 
         public FifoRConnection(String path, String open, boolean blocking, String encoding) throws IOException {
-            super(ConnectionClass.FIFO, open, AbstractOpenMode.Read);
+            super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, blocking);
             this.path = path;
             openNonLazyConnection();
         }
 
         @Override
         protected void createDelegateConnection() throws IOException {
+            final DelegateRConnection delegate;
+            if (isBlocking()) {
+                delegate = createBlockingDelegate();
+            } else {
+
+                delegate = createNonBlockingDelegate();
+            }
+            setDelegate(delegate);
+        }
+
+        private DelegateRConnection createBlockingDelegate() throws IOException {
             DelegateRConnection delegate = null;
             switch (getOpenMode().abstractOpenMode) {
                 case Read:
@@ -58,7 +74,6 @@ public class FifoConnections {
                     break;
                 case Write:
                 case WriteBinary:
-                    delegate = new FifoWriteConnection(this, path);
                     delegate = new FifoWriteConnection(this, path);
                     break;
                 case ReadAppend:
@@ -71,7 +86,31 @@ public class FifoConnections {
                 default:
                     throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
             }
-            setDelegate(delegate);
+            return delegate;
+        }
+
+        private DelegateRConnection createNonBlockingDelegate() throws IOException {
+            DelegateRConnection delegate = null;
+            switch (getOpenMode().abstractOpenMode) {
+                case Read:
+                case ReadBinary:
+                    delegate = new FifoReadNonBlockingRConnection(this, path);
+                    break;
+                case Write:
+                case WriteBinary:
+                    delegate = new FifoWriteNonBlockingRConnection(this, path);
+                    break;
+                case ReadAppend:
+                case ReadWrite:
+                case ReadWriteBinary:
+                case ReadWriteTrunc:
+                case ReadWriteTruncBinary:
+                    delegate = new FifoReadWriteNonBlockingRConnection(this, path);
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
+            }
+            return delegate;
         }
 
         @Override
@@ -134,7 +173,7 @@ public class FifoConnections {
 
         protected FifoReadWriteConnection(BaseRConnection base, String path) throws IOException {
             super(base);
-            this.raf = createAndOpenFifo(path, "w");
+            this.raf = createAndOpenFifo(path, "rw");
         }
 
         @Override
@@ -149,20 +188,80 @@ public class FifoConnections {
 
     }
 
+    static class FifoReadNonBlockingRConnection extends DelegateReadRConnection {
+        private final FileChannel channel;
+
+        protected FifoReadNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
+            super(base);
+            channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ);
+        }
+
+        @Override
+        public SeekableByteChannel getChannel() {
+            return channel;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private static class FifoWriteNonBlockingRConnection extends DelegateWriteRConnection {
+        private final FileChannel channel;
+
+        FifoWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
+            super(base);
+            channel = createAndOpenNonBlockingFifo(path, StandardOpenOption.READ, StandardOpenOption.WRITE);
+        }
+
+        @Override
+        public SeekableByteChannel getChannel() {
+            return channel;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private static class FifoReadWriteNonBlockingRConnection extends DelegateReadWriteRConnection {
+        private final FileChannel channel;
+
+        FifoReadWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
+            super(base);
+            channel = createAndOpenNonBlockingFifo(path, StandardOpenOption.WRITE, StandardOpenOption.READ);
+        }
+
+        @Override
+        public SeekableByteChannel getChannel() {
+            return channel;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+
+    }
+
     private static final String MKFIFO_ERROR_FILE_EXISTS = "File exists";
 
     private static RandomAccessFile createAndOpenFifo(String path, String mode) throws IOException {
-        RandomAccessFile pipeFile = null;
-        try {
-            pipeFile = new RandomAccessFile(path, mode);
-        } catch (FileNotFoundException e) {
+        if (!Files.exists(Paths.get(path))) {
             // try to create fifo on demand
             createNamedPipe(path);
+        }
+        return new RandomAccessFile(path, mode);
+    }
 
-            // re-try opening
-            pipeFile = new RandomAccessFile(path, mode);
+    private static FileChannel createAndOpenNonBlockingFifo(String path, OpenOption... openOptions) throws IOException {
+        if (!Files.exists(Paths.get(path))) {
+            // try to create fifo on demand
+            createNamedPipe(path);
         }
-        return pipeFile;
+        return FileChannel.open(Paths.get(path), openOptions);
     }
 
     /**
@@ -188,8 +287,9 @@ public class FifoConnections {
                 readThread.join();
                 String msg = new String(Arrays.copyOf(readThread.getData(), readThread.getTotalRead()));
 
-                // ignore if file already exists
-                if (!msg.endsWith(MKFIFO_ERROR_FILE_EXISTS)) {
+                // if the message is not empty and it is not the "file exists" error, then throw
+                // error
+                if (!msg.isEmpty() && !msg.endsWith(MKFIFO_ERROR_FILE_EXISTS)) {
                     throw new IOException(msg);
                 }
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index f9b97b4b1e..f6de8632eb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -36,6 +36,7 @@ import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.OpenOption;
 import java.nio.file.Paths;
@@ -71,8 +72,8 @@ public class FileConnections {
      */
     public static class FileRConnection extends BasePathRConnection {
 
-        public FileRConnection(String path, String modeString) throws IOException {
-            super(checkTemp(path), ConnectionClass.File, modeString);
+        public FileRConnection(String path, String modeString, Charset encoding) throws IOException {
+            super(checkTemp(path), ConnectionClass.File, modeString, encoding);
             openNonLazyConnection();
         }
 
@@ -89,40 +90,18 @@ public class FileConnections {
 
             // TODO (non-)blocking
 
-            DelegateRConnection delegate = null;
-            switch (getOpenMode().abstractOpenMode) {
-                case Read:
-                    delegate = new FileReadTextRConnection(this, true);
-                    break;
-                case Write:
-                    delegate = new FileWriteTextRConnection(this, false);
-                    break;
-                case Append:
-                    delegate = new FileWriteTextRConnection(this, true);
-                    break;
-                case ReadBinary:
-                    delegate = new FileReadBinaryRConnection(this);
-                    break;
-                case WriteBinary:
-                    delegate = new FileWriteBinaryConnection(this, false, true);
-                    break;
-                case ReadWriteTrunc:
-                case ReadWriteTruncBinary:
-                    delegate = new FileReadWriteConnection(this);
-                    break;
-                default:
-                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
-            }
+            DelegateRConnection delegate = FileConnections.createDelegateConnection(this, RCompression.Type.NONE);
             setDelegate(delegate);
         }
     }
 
-    private DelegateRConnection createDelegateConnection(BasePathRConnection base, OpenMode m) throws IOException {
+    private static DelegateRConnection createUncompressedDelegateConnection(BasePathRConnection base)
+                    throws IOException {
 
         // TODO (non-)blocking
 
         DelegateRConnection delegate = null;
-        switch (m.abstractOpenMode) {
+        switch (base.getOpenMode().abstractOpenMode) {
             case Read:
                 delegate = new FileReadTextRConnection(base, true);
                 break;
@@ -143,11 +122,120 @@ public class FileConnections {
                 delegate = new FileReadWriteConnection(base);
                 break;
             default:
-                throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + m);
+                throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
         }
         return delegate;
     }
 
+    private static DelegateRConnection createGZIPDelegateConnection(BasePathRConnection base) throws IOException {
+
+        // TODO (non-)blocking
+
+        boolean append = false;
+        switch (base.getOpenMode().abstractOpenMode) {
+            case Read:
+            case ReadBinary:
+                return new CompressedInputRConnection(base, new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE), true);
+            case Append:
+            case AppendBinary:
+                append = true;
+                // intentionally fall through !
+            case Write:
+            case WriteBinary:
+                return new CompressedOutputRConnection(base, new GZIPOutputStream(new FileOutputStream(base.path, append), GZIP_BUFFER_SIZE), true);
+            default:
+                throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
+        }
+    }
+
+    private static DelegateRConnection createXZDelegateConnection(BasePathRConnection base) throws IOException {
+
+        // TODO (non-)blocking
+
+        boolean append = false;
+        switch (base.getOpenMode().abstractOpenMode) {
+            case Read:
+            case ReadBinary:
+                return new CompressedInputRConnection(base, new XZInputStream(new FileInputStream(base.path)), false);
+            case Append:
+            case AppendBinary:
+                append = true;
+                // intentionally fall through !
+            case Write:
+            case WriteBinary:
+                return new CompressedOutputRConnection(base, new XZOutputStream(new FileOutputStream(base.path, append), new LZMA2Options(), XZ.CHECK_CRC32), false);
+            default:
+                throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
+        }
+    }
+
+    private static DelegateRConnection createBZIP2DelegateConnection(BasePathRConnection base) throws IOException {
+
+        // TODO (non-)blocking
+
+        boolean append = false;
+        switch (base.getOpenMode().abstractOpenMode) {
+            case Read:
+            case ReadBinary:
+                byte[] bzipUdata = RCompression.bzipUncompressFromFile(base.path);
+                return new ByteStreamCompressedInputRConnection(base, new ByteArrayInputStream(bzipUdata), false);
+            case Append:
+            case AppendBinary:
+                append = true;
+                // intentionally fall through !
+            case Write:
+            case WriteBinary:
+                return new BZip2OutputRConnection(base, new ByteArrayOutputStream(), append);
+            default:
+                throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
+        }
+    }
+
+    private static DelegateRConnection createDelegateConnection(BasePathRConnection base, RCompression.Type cType) throws IOException {
+        AbstractOpenMode openMode = base.getOpenMode().abstractOpenMode;
+
+        /*
+         * For input, we check the actual compression type as GNU R is permissive about the claimed
+         * type.
+         */
+        final RCompression.Type cTypeActual;
+        if (openMode == AbstractOpenMode.Read || openMode == AbstractOpenMode.ReadBinary) {
+            cTypeActual = RCompression.getCompressionType(base.path);
+            if (cTypeActual != cType) {
+                base.updateConnectionClass(mapConnectionClass(cTypeActual));
+            }
+        } else {
+            cTypeActual = cType;
+        }
+
+        switch (cTypeActual) {
+            case NONE:
+                return createUncompressedDelegateConnection(base);
+            case GZIP:
+                return createGZIPDelegateConnection(base);
+            case XZ:
+                return createXZDelegateConnection(base);
+            case BZIP2:
+                return createBZIP2DelegateConnection(base);
+        }
+        throw RInternalError.shouldNotReachHere("unsupported compression type");
+    }
+
+    private static ConnectionClass mapConnectionClass(RCompression.Type cType) {
+        switch (cType) {
+            case NONE:
+                return ConnectionClass.File;
+            case GZIP:
+                return ConnectionClass.GZFile;
+            case BZIP2:
+                return ConnectionClass.BZFile;
+            case XZ:
+                return ConnectionClass.XZFile;
+            default:
+                throw RInternalError.shouldNotReachHere();
+        }
+    }
+
     static class FileReadTextRConnection extends DelegateReadRConnection {
 
         private final ReadableByteChannel channel;
@@ -240,7 +328,7 @@ public class FileConnections {
 
         @Override
         public void writeString(String s, boolean nl) throws IOException {
-            ReadWriteHelper.writeStringHelper(getChannel(), s, nl);
+            ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
         }
 
         @Override
@@ -430,7 +518,7 @@ public class FileConnections {
         @Override
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
             raf.seek(readOffset);
-            return ReadWriteHelper.readLinesHelper(inputStream, n, warn, skipNul);
+            return super.readLines(n, warn, skipNul);
         }
 
         @Override
@@ -497,90 +585,19 @@ public class FileConnections {
      */
     public static class CompressedRConnection extends BasePathRConnection {
         private final RCompression.Type cType;
-        @SuppressWarnings("unused") private final String encoding; // TODO
         @SuppressWarnings("unused") private final int compression; // TODO
 
-        public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException {
-            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary);
+        public CompressedRConnection(String path, String modeString, Type cType, Charset encoding, int compression) throws IOException {
+            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary, encoding);
             this.cType = cType;
-            this.encoding = encoding;
             this.compression = compression;
             openNonLazyConnection();
         }
 
-        private static ConnectionClass mapConnectionClass(RCompression.Type cType) {
-            switch (cType) {
-                case NONE:
-                    return ConnectionClass.File;
-                case GZIP:
-                    return ConnectionClass.GZFile;
-                case BZIP2:
-                    return ConnectionClass.BZFile;
-                case XZ:
-                    return ConnectionClass.XZFile;
-                default:
-                    throw RInternalError.shouldNotReachHere();
-            }
-        }
-
         @Override
         protected void createDelegateConnection() throws IOException {
-            DelegateRConnection delegate = null;
-            AbstractOpenMode openMode = getOpenMode().abstractOpenMode;
-            switch (openMode) {
-                case Read:
-                case ReadBinary:
-                    /*
-                     * For input, we check the actual compression type as GNU R is permissive about
-                     * the claimed type.
-                     */
-                    RCompression.Type cTypeActual = RCompression.getCompressionType(path);
-                    if (cTypeActual != cType) {
-                        updateConnectionClass(mapConnectionClass(cTypeActual));
-                    }
-                    switch (cTypeActual) {
-                        case NONE:
-                            if (openMode == AbstractOpenMode.ReadBinary) {
-                                delegate = new FileConnections.FileReadBinaryRConnection(this);
-                            } else {
-                                delegate = new FileConnections.FileReadTextRConnection(this, true);
-                            }
-                            break;
-                        case GZIP:
-                            delegate = new CompressedInputRConnection(this, new GZIPInputStream(new FileInputStream(path), GZIP_BUFFER_SIZE), true);
-                            break;
-                        case XZ:
-                            delegate = new CompressedInputRConnection(this, new XZInputStream(new FileInputStream(path)), false);
-                            break;
-                        case BZIP2:
-                            // no in Java support, so go via byte array
-                            byte[] bzipUdata = RCompression.bzipUncompressFromFile(path);
-                            delegate = new ByteStreamCompressedInputRConnection(this, new ByteArrayInputStream(bzipUdata), false);
-                    }
-                    break;
+            setDelegate(FileConnections.createDelegateConnection(this, cType));
 
-                case Append:
-                case AppendBinary:
-                case Write:
-                case WriteBinary: {
-                    boolean append = openMode == AbstractOpenMode.Append || openMode == AbstractOpenMode.AppendBinary;
-                    switch (cType) {
-                        case GZIP:
-                            delegate = new CompressedOutputRConnection(this, new GZIPOutputStream(new FileOutputStream(path, append), GZIP_BUFFER_SIZE), true);
-                            break;
-                        case BZIP2:
-                            delegate = new BZip2OutputRConnection(this, new ByteArrayOutputStream(), append);
-                            break;
-                        case XZ:
-                            delegate = new CompressedOutputRConnection(this, new XZOutputStream(new FileOutputStream(path, append), new LZMA2Options(), XZ.CHECK_CRC32), false);
-                            break;
-                    }
-                    break;
-                }
-                default:
-                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
-            }
-            setDelegate(delegate);
         }
 
         // @Override
@@ -596,7 +613,7 @@ public class FileConnections {
         private final InputStream inputStream;
         private final boolean seekable;
 
-        protected CompressedInputRConnection(CompressedRConnection base, InputStream is, boolean seekable) {
+        protected CompressedInputRConnection(BasePathRConnection base, InputStream is, boolean seekable) {
             super(base);
             this.inputStream = is;
             this.seekable = seekable;
@@ -622,7 +639,7 @@ public class FileConnections {
     }
 
     private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection {
-        ByteStreamCompressedInputRConnection(CompressedRConnection base, ByteArrayInputStream is, boolean seekable) {
+        ByteStreamCompressedInputRConnection(BasePathRConnection base, ByteArrayInputStream is, boolean seekable) {
             super(base, is, seekable);
         }
     }
@@ -633,7 +650,7 @@ public class FileConnections {
         private final boolean seekable;
         private long seekPosition = 0L;
 
-        protected CompressedOutputRConnection(CompressedRConnection base, OutputStream os, boolean seekable) {
+        protected CompressedOutputRConnection(BasePathRConnection base, OutputStream os, boolean seekable) {
             super(base);
             this.outputStream = os;
             this.channel = Channels.newChannel(os);
@@ -689,7 +706,7 @@ public class FileConnections {
         private final ByteArrayOutputStream bos;
         private final boolean append;
 
-        BZip2OutputRConnection(CompressedRConnection base, ByteArrayOutputStream os, boolean append) {
+        BZip2OutputRConnection(BasePathRConnection base, ByteArrayOutputStream os, boolean append) {
             super(base, os, false);
             this.bos = os;
             this.append = append;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 7c9d9847ea..3e7a760d9c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -67,6 +67,12 @@ public abstract class RConnection implements AutoCloseable {
 
     private LinkedList<String> pushBack;
 
+    /**
+     * Indicates that the last line read operation was incomplete.<br>
+     * This is only relevant for connections in text and non-blocking mode.
+     */
+    private boolean incomplete = false;
+
     public abstract String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException;
 
     private String readOneLineWithPushBack(String[] res, int ind, @SuppressWarnings("unused") boolean warn, @SuppressWarnings("unused") boolean skipNul) {
@@ -350,4 +356,11 @@ public abstract class RConnection implements AutoCloseable {
      */
     public abstract boolean isOpen();
 
+    /**
+     * Returns {@code true} iff the last read operation was blocked or there is unflushed output.
+     */
+    public boolean isIncomplete() {
+        return incomplete;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index dc2310798b..fec3a53929 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -134,7 +134,7 @@ public class RawConnections {
 
         @Override
         public byte[] readBinChars() throws IOException {
-            // acquire copy from buffer without advancing the cursor
+            // acquire copy from buffer without advancing the cursorskipNul
             final byte[] buffer = channel.getBufferFromCursor();
             int i = 0;
             while (i < buffer.length && buffer[i] != (byte) 0) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
index 1d0b0c52f3..8aa5483305 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
@@ -8,6 +8,7 @@ import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -27,7 +28,7 @@ public class ReadWriteHelper {
      * @param warn TODO
      * @param skipNul TODO
      */
-    public static String[] readLinesHelper(InputStream in, int n, boolean warn, boolean skipNul) throws IOException {
+    public static String[] readLinesHelper(InputStream in, int n, boolean warn, boolean skipNul, String description, Charset encoding) throws IOException {
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
         byte[] buffer = new byte[64];
@@ -49,9 +50,9 @@ public class ReadWriteHelper {
                      * refactoring is needed to be able to reliably access the "name" for the
                      * warning.
                      */
-                    lines.add(new String(buffer, 0, totalRead));
+                    lines.add(new String(buffer, 0, totalRead, encoding));
                     if (warn) {
-                        RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, "TODO: connection path");
+                        RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, description);
                     }
                 }
                 break;
@@ -68,7 +69,7 @@ public class ReadWriteHelper {
                 }
             }
             if (lineEnd) {
-                lines.add(new String(buffer, 0, totalRead));
+                lines.add(new String(buffer, 0, totalRead, encoding));
                 if (n > 0 && lines.size() == n) {
                     break;
                 }
@@ -83,17 +84,17 @@ public class ReadWriteHelper {
         return result;
     }
 
-    public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep) throws IOException {
+    public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
         for (int i = 0; i < lines.getLength(); i++) {
             final String line = lines.getDataAt(i);
-            writeStringHelper(out, line, false);
-            writeStringHelper(out, sep, false);
+            writeStringHelper(out, line, false, encoding);
+            writeStringHelper(out, sep, false, encoding);
         }
     }
 
-    public static void writeStringHelper(WritableByteChannel out, String s, boolean nl) throws IOException {
-        final byte[] bytes = s.getBytes();
-        final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes() : null;
+    public static void writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
+        final byte[] bytes = s.getBytes(encoding);
+        final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes(encoding) : null;
 
         ByteBuffer buf = ByteBuffer.allocate(bytes.length + (nl ? lineSepBytes.length : 0));
         buf.put(bytes);
@@ -197,7 +198,7 @@ public class ReadWriteHelper {
     /**
      * TODO probably, this method belongs to {@link ConnectionSupport}
      */
-    public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+    public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
         long position = channel.position();
         switch (seekMode) {
             case ENQUIRE:
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index becf859cb1..c635f00f86 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
@@ -47,15 +46,13 @@ public class SocketConnections {
         protected final boolean server;
         protected final String host;
         protected final int port;
-        protected final boolean blocking;
         protected final int timeout;
 
         public RSocketConnection(String modeString, boolean server, String host, int port, boolean blocking, int timeout) throws IOException {
-            super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read);
+            super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read, blocking);
             this.server = server;
             this.host = host;
             this.port = port;
-            this.blocking = blocking;
             this.timeout = timeout;
             openNonLazyConnection();
         }
@@ -75,7 +72,6 @@ public class SocketConnections {
     private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection {
         private Socket socket;
         private SocketChannel socketChannel;
-        protected InputStream inputStream;
         protected OutputStream outputStream;
         protected final RSocketConnection thisBase;
 
@@ -87,7 +83,7 @@ public class SocketConnections {
         protected void openStreams(Socket socketArg) throws IOException {
             this.socket = socketArg;
             this.socketChannel = socket.getChannel();
-            if (thisBase.blocking) {
+            if (thisBase.isBlocking()) {
                 // Java (int) timeouts do not meet the POSIX standard of 31 days
                 long millisTimeout = ((long) thisBase.timeout) * 1000;
                 if (millisTimeout > Integer.MAX_VALUE) {
@@ -97,15 +93,9 @@ public class SocketConnections {
             } else {
                 socketChannel.configureBlocking(false);
             }
-            inputStream = socket.getInputStream();
             outputStream = socket.getOutputStream();
         }
 
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            return ReadWriteHelper.readLinesHelper(inputStream, n, warn, skipNul);
-        }
-
         @Override
         public void flush() {
             // TODO add "throws"
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 5e57f9ebb8..914d4ea03d 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
@@ -21071,6 +21071,11 @@ Levels: c f h k m n p x
 [1000] 1
 Levels: 0 1
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenInexisting#
+#capabilities("fifo")
+fifo
+TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenInexisting#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
 #{ zz <- fifo("/tmp/pipe3408688236", "r"); close(zz); }
 Error in fifo("/tmp/pipe3408688236", "r") : cannot open the connection
@@ -21085,30 +21090,6 @@ In addition: Warning message:
 In fifo("/tmp/pipe3408688236", "r") :
   cannot open fifo '/tmp/pipe3408688236'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fileConnection.testFileSummary#
-#{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res }
-$description
-[1] "/tmp/gzipped_____5137528280012599068___.gz"
-
-$class
-[1] "gzfile"
-
-$mode
-[1] "r"
-
-$text
-[1] "text"
-
-$opened
-[1] "opened"
-
-$`can read`
-[1] "yes"
-
-$`can write`
-[1] "no"
-
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_fileaccess.testfileaccess1#
 #argv <- list(character(0), 0); .Internal(file.access(argv[[1]], argv[[2]]))
 integer(0)
@@ -42215,6 +42196,10 @@ numeric(0)
 #argv <- structure(list(length = 0), .Names = 'length');do.call('raw', argv)
 raw(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#Ignored.Unknown#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R") }
+[1] "abc"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R") }
 
@@ -42227,6 +42212,19 @@ raw(0)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") }
+Warning message:
+In readLines("test1") : incomplete final line found on 'test1'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R") }
+Read 4 items
+Read 4 items
+
+Summary of Residuals:
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
 #{ rc <- rawConnection(raw(0), "a+"); close(rc); write(charToRaw("A"), rc) }
 Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
@@ -65543,15 +65541,6 @@ Error in tempfile(character()) : no 'pattern'
 #{ tempfile(integer()) }
 Error in tempfile(integer()) : invalid filename pattern
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_textConnection.testSeek#
-#{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res }
-[1] FALSE
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_textConnection.testSeek#
-#{ zz <- textConnection("Hello, World!"); res <- seek(zz, 5); close(zz); res }
-Error in seek.connection(zz, 5) :
-  seek is not relevant for text connection
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_times_difftime.testtimes_difftime1#
 #argv <- structure(list(e1 = 2, e2 = structure(c(3.33333333333333,     683.25), units = 'mins', class = 'difftime')), .Names = c('e1',     'e2'));do.call('*.difftime', argv)
 Time differences in mins
@@ -73509,6 +73498,64 @@ NULL
 #withRestarts({cat("<start>");invokeRestart("foo", 123L, 456L);789L},<<<NEWLINE>>> foo=list(description="my handler", handler=function(a,b) c(a,b)))
 <start>[1] 123 456
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
+#fin <- file("/tmp/file3408688236", "r", encoding = "UTF-8"); lines <- readLines(fin, 1); close(fin); lines
+[1] "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß."
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Output.IgnoreErrorContext#
+#fin <- file("/tmp/file3408688236", "r", encoding = "___inexistingCharSet___")
+Error in file("/tmp/file3408688236", "r", encoding = "___inexistingCharSet___") :
+  unsupported conversion from '___inexistingCharSet___' to ''
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
+#fin <- file("/tmp/file3408688236", "r", encoding = "latin1"); lines <- readLines(fin, 1); close(fin); lines
+[1] "This is a sentence using german Umlauts like ö, ä, ü, Ã\u0096, Ã\u0084, Ã\u009c but also Ã\u009f."
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.Unknown#
+#fin <- file("/tmp/file4039819292", "r"); lines <- readLines(fin, 1, encoding = "UTF-8"); close(fin); lines
+[1] "This is a sentence using german Umlauts like \xf6, \xe4, \xfc, \xd6, \xc4, \xdc but also \xdf."
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
+#fin <- file("/tmp/file4039819292", "r", encoding = "UTF-8"); lines <- readLines(fin, 1); close(fin); lines
+Warning messages:
+1: In readLines(fin, 1) :
+  invalid input found on input connection '/tmp/file4039819292'
+2: In readLines(fin, 1) :
+  incomplete final line found on '/tmp/file4039819292'
+[1] "This is a sentence using german Umlauts like "
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
+#fin <- file("/tmp/file4039819292", "r", encoding = "latin1"); lines <- readLines(fin, 1); close(fin); lines
+[1] "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß."
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
+#{ wline <- "Hellö"; fin <- file("/tmp/file9823674682", "w+", encoding = "UTF-8"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }
+[1] "Hellö" "Hellö" "TRUE"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary#
+#{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res }
+$description
+[1] "/tmp/gzipped_____5137528280012599068___.gz"
+
+$class
+[1] "gzfile"
+
+$mode
+[1] "r"
+
+$text
+[1] "text"
+
+$opened
+[1] "opened"
+
+$`can read`
+[1] "yes"
+
+$`can write`
+[1] "no"
+
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin#
 #{ readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", "rb"), 3) }
 numeric(0)
@@ -73613,6 +73660,15 @@ numeric(0)
 #{ con<-textConnection(c("a","b","c","d")); pushBackLength(con) }
 [1] 0
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#
+#{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#Output.IgnoreErrorMessage#
+#{ zz <- textConnection("Hello, World!"); res <- seek(zz, 5); close(zz); res }
+Error in seek.connection(zz, 5) :
+  seek is not relevant for text connection
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testTextReadConnection#
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con) }
 [1] "1" "2" "3" "4"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
index 1a359a3dc5..def25b3376 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
@@ -50,6 +50,8 @@ public class TestBuiltin_fifoConnection extends TestBase {
 
     @Test
     public void testFifoOpenInexisting() {
+        assertEval("capabilities(\"fifo\")");
+
         Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
         assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java
deleted file mode 100644
index a9aa9409bb..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileConnection.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.builtins;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.zip.GZIPOutputStream;
-
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-/**
- * Class tests basic file connection functionality.
- */
-// Checkstyle: stop line length check
-public class TestBuiltin_fileConnection extends TestBase {
-
-    private static Path TEMP_FILE_GZIP;
-
-    @BeforeClass
-    public static void setup() throws IOException {
-        Path path = Paths.get(System.getProperty("java.io.tmpdir"));
-
-        // create a gzipped file
-        TEMP_FILE_GZIP = path.resolve("gzipped_____5137528280012599068___.gz");
-        OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(TEMP_FILE_GZIP, StandardOpenOption.WRITE, StandardOpenOption.CREATE));
-        gzos.write("Hello, World!".getBytes());
-        gzos.close();
-    }
-
-    @Test
-    public void testFileSummary() {
-
-        Assert.assertTrue("Could not create required temp file for test.", Files.exists(TEMP_FILE_GZIP));
-        assertEval("{ zz <- file(\"" + TEMP_FILE_GZIP + "\", \"r\"); res <- summary(zz); close(zz); res }");
-    }
-
-    @AfterClass
-    public static void cleanup() throws IOException {
-        Files.delete(TEMP_FILE_GZIP);
-    }
-
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java
deleted file mode 100644
index 27ab9b5144..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_textConnection.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.builtins;
-
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-// Checkstyle: stop line length check
-public class TestBuiltin_textConnection extends TestBase {
-
-    @Test
-    public void testReadAppendText() {
-    }
-
-    @Test
-    public void testReadWriteText() {
-    }
-
-    @Test
-    public void testWriteText() {
-    }
-
-    @Test
-    public void testWriteBinary() {
-    }
-
-    @Test
-    public void testSeek() {
-        assertEval("{ zz <- textConnection(\"Hello, World!\"); res <- isSeekable(zz); close(zz); res }");
-        assertEval("{ zz <- textConnection(\"Hello, World!\"); res <- seek(zz, 5); close(zz); res }");
-    }
-
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R
new file mode 100644
index 0000000000..9ffda2392b
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R
@@ -0,0 +1,9 @@
+# Ignored
+# This test does currently not work on Java because there is simply no way in Java for opening a UNIX named pipe non-blocking.
+if(capabilities("fifo")) {
+  zz <- fifo("foo-fifo", "w+")
+  writeLines("abc", zz)
+  print(readLines(zz))
+  close(zz)
+  unlink("foo-fifo")
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
new file mode 100644
index 0000000000..79e5aea04c
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
@@ -0,0 +1,15 @@
+cat("TITLE extra line", "2 3 5 7", "", "11 13 17", file = "ex.data", sep = "\n")
+readLines("ex.data", n = -1)
+unlink("ex.data") # tidy up
+
+## difference in blocking
+cat("123\nabc", file = "test1")
+readLines("test1") # line with a warning
+
+con <- file("test1", "r", blocking = FALSE)
+readLines(con) # empty
+cat(" def\n", file = "test1", append = TRUE)
+readLines(con) # gets both
+close(con)
+
+unlink("test1") # tidy up
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R
new file mode 100644
index 0000000000..7785051d50
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R
@@ -0,0 +1,30 @@
+zz <- textConnection(LETTERS)
+readLines(zz, 2)
+scan(zz, "", 4)
+pushBack(c("aa", "bb"), zz)
+scan(zz, "", 4)
+close(zz)
+
+zz <- textConnection("foo", "w")
+writeLines(c("testit1", "testit2"), zz)
+cat("testit3 ", file = zz)
+isIncomplete(zz)
+cat("testit4\n", file = zz)
+# removed this call since we haven't implemented it yet
+# isIncomplete(zz)
+close(zz)
+foo
+
+# capture R output: use part of example from help(lm)
+zz <- textConnection("foo", "w")
+ctl <- c(4.17, 5.58, 5.18, 6.11, 4.5, 4.61, 5.17, 4.53, 5.33, 5.14)
+trt <- c(4.81, 4.17, 4.41, 3.59, 5.87, 3.83, 6.03, 4.89, 4.32, 4.69)
+group <- gl(2, 10, 20, labels = c("Ctl", "Trt"))
+weight <- c(ctl, trt)
+sink(zz)
+anova(lm.D9 <- lm(weight ~ group))
+cat("\nSummary of Residuals:\n\n")
+summary(resid(lm.D9))
+sink()
+close(zz)
+cat(foo, sep = "\n")
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index b67b54e5a1..ae88d43b42 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -22,9 +22,28 @@
  */
 package com.oracle.truffle.r.test.library.base;
 
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.GZIPOutputStream;
 
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -44,17 +63,44 @@ public class TestConnections extends TestBase {
     }
 
     private static TestDir testDir;
+    private static Path TEMP_FILE_GZIP;
+    private static List<Path> TEMP_FILES = new ArrayList<>();
 
     @BeforeClass
-    public static void setupTestDir() {
+    public static void setup() throws IOException {
         testDir = new TestDir();
+
+        Path path = Paths.get(System.getProperty("java.io.tmpdir"));
+
+        // create a gzipped file
+        TEMP_FILE_GZIP = path.resolve("gzipped_____5137528280012599068___.gz");
+        OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(TEMP_FILE_GZIP, StandardOpenOption.WRITE, StandardOpenOption.CREATE));
+        gzos.write("Hello, World!".getBytes());
+        gzos.close();
+
+        TEMP_FILES.add(path.resolve("file3408688236"));
+        TEMP_FILES.add(path.resolve("file4039819292"));
+        TEMP_FILES.add(path.resolve("file9823674682"));
+        TEMP_FILES.add(path.resolve("file3762346723"));
     }
 
     @AfterClass
-    public static void teardownTestDir() {
+    public static void teardown() {
         if (!deleteDir(testDir.testDirPath)) {
             System.err.println("WARNING: error deleting : " + testDir.testDirPath);
         }
+        deleteFile(TEMP_FILE_GZIP);
+        for (Path p : TEMP_FILES) {
+            deleteFile(p);
+        }
+    }
+
+    private static void deleteFile(Path p) {
+        try {
+            Files.delete(p);
+        } catch (IOException e) {
+            // ignore
+        }
     }
 
     @Test
@@ -123,4 +169,58 @@ public class TestConnections extends TestBase {
 
         assertEval("{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection(\"buf\", open=\"w\", local=T); write.table(d, c); buf }");
     }
+
+    @Test
+    public void testSeekTextConnection() {
+        assertEval("{ zz <- textConnection(\"Hello, World!\"); res <- isSeekable(zz); close(zz); res }");
+        assertEval(Output.IgnoreErrorMessage, "{ zz <- textConnection(\"Hello, World!\"); res <- seek(zz, 5); close(zz); res }");
+    }
+
+    @Test
+    public void testFileSummary() {
+
+        Assert.assertTrue("Could not create required temp file for test.", Files.exists(TEMP_FILE_GZIP));
+        assertEval("{ zz <- file(\"" + TEMP_FILE_GZIP + "\", \"r\"); res <- summary(zz); close(zz); res }");
+    }
+
+    @Test
+    public void testEncoding() throws IOException {
+
+        // read from UTF-8 file
+        final Path utf8File = TEMP_FILES.get(0);
+        writeEncodedString(utf8File, "utf8", "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß.\n");
+        assertEval(Ignored.ImplementationError, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
+        assertEval("fin <- file(\"" + utf8File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
+
+        // read from ISO-8859-1 (aka Latin1) file
+        final Path latin1File = TEMP_FILES.get(1);
+        writeEncodedString(latin1File, "ISO-8859-1", "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß.\n");
+        assertEval(Ignored.Unknown, "fin <- file(\"" + latin1File + "\", \"r\"); lines <- readLines(fin, 1, encoding = \"UTF-8\"); close(fin); lines");
+        assertEval("fin <- file(\"" + latin1File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
+        assertEval(Ignored.ImplementationError, "fin <- file(\"" + latin1File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
+
+        // use inexisting charset
+        assertEval(Output.IgnoreErrorContext, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"___inexistingCharSet___\")");
+
+        // write UTF-8 file
+        final Path utf8File1 = TEMP_FILES.get(2);
+        assertEval("{ wline <- \"Hellö\"; fin <- file(\"" + utf8File1 +
+                        "\", \"w+\", encoding = \"UTF-8\"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }");
+    }
+
+    private static String determineFileEncoding(final Path utf8File1) throws FileNotFoundException {
+        InputStreamReader r = new InputStreamReader(new FileInputStream(utf8File1.toFile()));
+        return r.getEncoding().toLowerCase();
+    }
+
+    /**
+     * Writes a string using the specified charset to the provided file. The file is created and
+     * truncated.
+     */
+    private static void writeEncodedString(Path p, String enc, String s) throws IOException {
+        ByteBuffer encode = Charset.forName(enc).encode(s);
+        FileChannel open = FileChannel.open(p, CREATE, WRITE, TRUNCATE_EXISTING);
+        open.write(encode);
+        open.close();
+    }
 }
-- 
GitLab


From d419d60b211c7fa6981b6872aeba3c7d24515284 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 23 Feb 2017 14:25:18 +0100
Subject: [PATCH 067/402] Implemented pipe command. Implemented proper
 dispatching if an URL is used in function "file".

---
 .../builtin/base/ConnectionFunctions.java     |  60 ++++-
 .../r/runtime/conn/PipeConnections.java       | 224 ++++++++++++++++++
 2 files changed, 278 insertions(+), 6 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index fb1e07a5bc..30ff269062 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -49,6 +49,7 @@ import static com.oracle.truffle.r.runtime.conn.StdConnections.getStdout;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.net.URL;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.DoubleBuffer;
@@ -76,6 +77,7 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.FifoConnections.FifoRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.CompressedRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.FileRConnection;
+import com.oracle.truffle.r.runtime.conn.PipeConnections.PipeRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.conn.RawConnections.RawRConnection;
 import com.oracle.truffle.r.runtime.conn.SocketConnections.RSocketConnection;
@@ -195,6 +197,10 @@ public abstract class ConnectionFunctions {
         private static void method(Casts casts) {
             casts.arg("method").asStringVector().findFirst();
         }
+
+        static void blockingNotSupported(Casts casts) {
+            casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean());
+        }
     }
 
     @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method", "raw"}, behavior = IO)
@@ -214,8 +220,23 @@ public abstract class ConnectionFunctions {
         @TruffleBoundary
         protected RAbstractIntVector file(String description, String openArg, @SuppressWarnings("unused") boolean blocking, String encoding, @SuppressWarnings("unused") String method, boolean raw) {
             String open = openArg;
-            // TODO handle http/ftp prefixes and redirect and method
-            String path = removeFileURLPrefix(description);
+
+            // check if the description is an URL and dispatch if necessary
+            String path = description;
+            try {
+                URL url = new URL(description);
+                if (!"file".equals(url.getProtocol())) {
+                    return new URLRConnection(description, open).asVector();
+                } else {
+                    path = removeFileURLPrefix(description);
+                }
+            } catch (MalformedURLException e) {
+                // ignore and try to open file
+            } catch (IOException e) {
+                RError.warning(this, RError.Message.UNABLE_TO_RESOLVE, e.getMessage());
+                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+            }
+
             if (path.length() == 0) {
                 // special case, temp file opened in "w+" or "w+b" only
                 if (open.length() == 0) {
@@ -537,7 +558,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected RLogicalVector isOpen(int con, int rw) {
-            BaseRConnection baseCon = getBaseConnection(RConnection.fromIndex(con));
+            RConnection baseCon = getBaseConnection(RConnection.fromIndex(con));
             boolean result = baseCon.isOpen();
             switch (rw) {
                 case 0:
@@ -567,7 +588,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected Object close(int con, @SuppressWarnings("unused") String type) {
-            BaseRConnection connection = RConnection.fromIndex(con);
+            RConnection connection = RConnection.fromIndex(con);
             try {
                 connection.closeAndDestroy();
             } catch (IOException ex) {
@@ -1143,7 +1164,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector getConnection(int what) {
-            BaseRConnection con = RContext.getInstance().stateRConnection.getConnection(what, false);
+            RConnection con = RContext.getInstance().stateRConnection.getConnection(what, false);
             if (con == null) {
                 throw error(RError.Message.NO_SUCH_CONNECTION, what);
             } else {
@@ -1219,7 +1240,9 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(Fifo.class);
             CastsHelper.description(casts);
             CastsHelper.open(casts);
-            CastsHelper.blocking(casts);
+            // We cannot support non-blocking because Java does simply not allow to open a file or
+            // named pipe in non-blocking mode.
+            CastsHelper.blockingNotSupported(casts);
             CastsHelper.encoding(casts);
         }
 
@@ -1237,6 +1260,31 @@ public abstract class ConnectionFunctions {
         }
     }
 
+    @RBuiltin(name = "pipe", kind = INTERNAL, parameterNames = {"description", "open", "encoding"}, behavior = IO)
+    public abstract static class Pipe extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(Pipe.class);
+            CastsHelper.description(casts);
+            CastsHelper.open(casts);
+            CastsHelper.encoding(casts);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected RAbstractIntVector pipe(String path, String openArg, String encoding) {
+
+            String open = openArg;
+            try {
+                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
+                return new PipeRConnection(path, open, charset).asVector();
+            } catch (IOException ex) {
+                RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
+                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+            }
+        }
+    }
+
     @RBuiltin(name = "isIncomplete", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
     public abstract static class IsIncomplete extends RBuiltinNode {
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
new file mode 100644
index 0000000000..a9f9f839d2
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.ProcessBuilder.Redirect;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
+
+public class PipeConnections {
+
+    private static Process executeAndJoin(String command) throws IOException {
+        ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-c", command);
+        pb.redirectError(Redirect.INHERIT);
+        Process p = pb.start();
+        try {
+            p.waitFor();
+        } catch (InterruptedException e) {
+            // TODO not sure how to handle an interrupted exception at this point
+        }
+        return p;
+    }
+
+    public static class PipeRConnection extends BaseRConnection {
+
+        private final String command;
+
+        public PipeRConnection(String command, String open, Charset encoding) throws IOException {
+            super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, encoding);
+            this.command = command;
+            openNonLazyConnection();
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            final DelegateRConnection delegate;
+            switch (getOpenMode().abstractOpenMode) {
+                case Read:
+                case ReadBinary:
+                    delegate = new PipeReadRConnection(this, command);
+                    break;
+                case Write:
+                case WriteBinary:
+                    delegate = new PipeWriteConnection(this, command);
+                    break;
+                case ReadAppend:
+                case ReadWrite:
+                case ReadWriteBinary:
+                case ReadWriteTrunc:
+                case ReadWriteTruncBinary:
+                    delegate = new PipeReadWriteConnection(this, command);
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode());
+            }
+            setDelegate(delegate);
+        }
+
+        @Override
+        public String getSummaryDescription() {
+            return command;
+        }
+    }
+
+    static class PipeReadRConnection extends DelegateReadRConnection {
+        private final InputStream in;
+
+        protected PipeReadRConnection(BaseRConnection base, String command) throws IOException {
+            super(base);
+            Process p = PipeConnections.executeAndJoin(command);
+            in = p.getInputStream();
+        }
+
+        @Override
+        public ReadableByteChannel getChannel() {
+            return Channels.newChannel(in);
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            return in;
+        }
+
+        @Override
+        public void close() throws IOException {
+            in.close();
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private static class PipeWriteConnection extends DelegateWriteRConnection {
+        private final OutputStream out;
+
+        PipeWriteConnection(BaseRConnection base, String command) throws IOException {
+            super(base);
+            Process p = PipeConnections.executeAndJoin(command);
+            out = p.getOutputStream();
+        }
+
+        @Override
+        public WritableByteChannel getChannel() {
+            return Channels.newChannel(out);
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            return out;
+        }
+
+        @Override
+        public void close() throws IOException {
+            out.close();
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private static class PipeReadWriteConnection extends DelegateReadWriteRConnection {
+
+        private final InputStream in;
+        private final OutputStream out;
+
+        protected PipeReadWriteConnection(BaseRConnection base, String command) throws IOException {
+            super(base);
+            Process p = PipeConnections.executeAndJoin(command);
+            in = p.getInputStream();
+            out = p.getOutputStream();
+        }
+
+        @Override
+        public ByteChannel getChannel() {
+            return new ReadableWriteableChannel(Channels.newChannel(in), Channels.newChannel(out));
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            return in;
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            return out;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+
+    }
+
+    private static class ReadableWriteableChannel implements ByteChannel {
+
+        private final ReadableByteChannel rb;
+        private final WritableByteChannel wb;
+
+        public ReadableWriteableChannel(ReadableByteChannel rb, WritableByteChannel wb) {
+            super();
+            this.rb = rb;
+            this.wb = wb;
+        }
+
+        @Override
+        public int read(ByteBuffer dst) throws IOException {
+            return rb.read(dst);
+        }
+
+        @Override
+        public boolean isOpen() {
+            return rb.isOpen() && wb.isOpen();
+        }
+
+        @Override
+        public void close() throws IOException {
+            rb.close();
+            wb.close();
+        }
+
+        @Override
+        public int write(ByteBuffer src) throws IOException {
+            return wb.write(src);
+        }
+
+    }
+
+}
-- 
GitLab


From ffd4fa5b1a0af078663594983639fde8c033b908 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 23 Feb 2017 18:26:00 +0100
Subject: [PATCH 068/402] Splitted delegate connection classes into blocking
 and non-blocking implementations (at least prepared for non-blocking). This
 was necessary because we cannot simply wrap channels into input streams on
 non-blocking sockets.

---
 .../r/nodes/builtin/base/BasePackage.java     |   1 +
 .../builtin/base/ConnectionFunctions.java     |   5 +-
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../r/runtime/conn/ConnectionSupport.java     |  17 +-
 .../r/runtime/conn/DelegateRConnection.java   |  10 +-
 .../conn/DelegateReadNonBlockRConnection.java | 112 +++++++
 .../runtime/conn/DelegateReadRConnection.java |  26 +-
 .../DelegateReadWriteNonBlockRConnection.java | 112 +++++++
 .../conn/DelegateReadWriteRConnection.java    |  40 +--
 .../DelegateWriteNonBlockRConnection.java     | 106 +++++++
 .../conn/DelegateWriteRConnection.java        |  21 +-
 .../r/runtime/conn/FifoConnections.java       |  35 ++-
 .../r/runtime/conn/FileConnections.java       | 273 +++---------------
 .../r/runtime/conn/PipeConnections.java       |  54 ----
 .../truffle/r/runtime/conn/RConnection.java   |  13 +-
 .../r/runtime/conn/RawConnections.java        |  17 +-
 .../r/runtime/conn/ReadWriteHelper.java       | 171 ++++++++++-
 .../r/runtime/conn/SocketConnections.java     |  59 +++-
 .../r/runtime/conn/StdConnections.java        |   2 +-
 .../r/runtime/conn/TextConnections.java       |  17 +-
 .../r/runtime/conn/URLConnections.java        |  12 -
 .../truffle/r/test/ExpectedTestOutput.test    |  26 +-
 .../builtins/TestBuiltin_fifoConnection.java  |   4 +-
 .../r/test/library/base/TestConnections.java  |   8 -
 24 files changed, 702 insertions(+), 442 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 97135250de..f3119ba912 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -268,6 +268,7 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.RawConnection.class, ConnectionFunctionsFactory.RawConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnectionValue.class, ConnectionFunctionsFactory.RawConnectionValueNodeGen::create);
         add(ConnectionFunctions.Fifo.class, ConnectionFunctionsFactory.FifoNodeGen::create);
+        add(ConnectionFunctions.Pipe.class, ConnectionFunctionsFactory.PipeNodeGen::create);
         add(ConnectionFunctions.Stderr.class, ConnectionFunctionsFactory.StderrNodeGen::create);
         add(ConnectionFunctions.Stdin.class, ConnectionFunctionsFactory.StdinNodeGen::create);
         add(ConnectionFunctions.Stdout.class, ConnectionFunctionsFactory.StdoutNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 30ff269062..ac5525187e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -210,7 +210,7 @@ public abstract class ConnectionFunctions {
             Casts casts = new Casts(File.class);
             CastsHelper.description(casts);
             CastsHelper.open(casts);
-            casts.arg("blocking").asLogicalVector().findFirst().mustBe(logicalTrue(), RError.Message.NYI, "non-blocking mode not supported").map(toBoolean());
+            CastsHelper.blocking(casts);
             CastsHelper.encoding(casts);
             CastsHelper.method(casts);
             CastsHelper.raw(casts);
@@ -1252,7 +1252,8 @@ public abstract class ConnectionFunctions {
 
             String open = openArg;
             try {
-                return new FifoRConnection(path, open, blocking, encoding).asVector();
+                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
+                return new FifoRConnection(path, open, blocking, charset).asVector();
             } catch (IOException ex) {
                 RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
                 throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 287dc010fb..c80be71b26 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -835,7 +835,8 @@ public final class RError extends RuntimeException {
         SEEK_NOT_RELEVANT_FOR_TEXT_CON("seek is not relevant for text connection"),
         SEEK_NOT_ENABLED("'seek' not enabled for this connection"),
         CANNOT_OPEN_FIFO("cannot open fifo '%s'"),
-        UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'");
+        UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'"),
+        UNABLE_TO_RESOLVE("unable to resolve '%s'");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index d90cb05986..41b5362c0a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -107,7 +107,7 @@ public class ConnectionSupport {
             for (int i = 0; i <= hwm; i++) {
                 WeakReference<BaseRConnection> ref = allConnections.get(i);
                 if (ref != null) {
-                    BaseRConnection con = ref.get();
+                    RConnection con = ref.get();
                     if (con != null) {
                         list.add(i);
                     }
@@ -402,11 +402,6 @@ public class ConnectionSupport {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
-        @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
-        }
-
         @Override
         public int getc() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
@@ -877,16 +872,6 @@ public class ConnectionSupport {
         }
     }
 
-    static byte[] checkBuffer(byte[] buffer, int n) {
-        if (n > buffer.length - 1) {
-            byte[] newBuffer = new byte[buffer.length + buffer.length / 2];
-            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
-            return newBuffer;
-        } else {
-            return buffer;
-        }
-    }
-
     abstract static class BasePathRConnection extends BaseRConnection {
         protected final String path;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 6b33ed255c..ed1d60ea4d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -1,9 +1,9 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.nio.channels.Channel;
 
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.sun.istack.internal.NotNull;
 
@@ -36,10 +36,10 @@ abstract class DelegateRConnection extends RConnection {
 
     @Override
     protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-        assert !isSeekable();
-        throw RError.error(RError.SHOW_CALLER2, RError.Message.UNSEEKABLE_CONNECTION);
+        if (!isSeekable()) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_ENABLED);
+        }
+        throw RInternalError.shouldNotReachHere("seek has not been implemented for this connection");
     }
 
-    public abstract Channel getChannel();
-
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
new file mode 100644
index 0000000000..682c8b4bb3
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
@@ -0,0 +1,112 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+public abstract class DelegateReadNonBlockRConnection extends DelegateRConnection {
+
+    private final ByteBuffer tmp = ByteBuffer.allocate(1);
+
+    protected DelegateReadNonBlockRConnection(BaseRConnection base) {
+        super(base);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
+    }
+
+    @Override
+    public int getc() throws IOException {
+        // TODO a character may consist of multiple bytes
+        tmp.clear();
+        getChannel().read(tmp);
+        return tmp.get();
+    }
+
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        return ReadWriteHelper.readCharHelper(nchars, getChannel(), useBytes);
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        return getChannel().read(buffer);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+    }
+
+    @TruffleBoundary
+    @Override
+    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        return ReadWriteHelper.readLinesNonBlockHelper(base, getChannel(), n, warn, skipNul, base.getSummaryDescription(), base.getEncoding());
+    }
+
+    @Override
+    public void flush() {
+        // nothing to do when reading
+    }
+
+    @Override
+    public OutputStream getOutputStream() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return false;
+    }
+
+    public abstract ReadableByteChannel getChannel();
+
+    @Override
+    @Deprecated
+    public InputStream getInputStream() throws IOException {
+        return Channels.newInputStream(getChannel());
+    }
+
+    @Override
+    public void close() throws IOException {
+        getChannel().close();
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index 96b1ef006d..6484175a5a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -2,10 +2,9 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
@@ -13,6 +12,9 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
+/**
+ * A blocking connection for reading.
+ */
 public abstract class DelegateReadRConnection extends DelegateRConnection {
 
     protected DelegateReadRConnection(BaseRConnection base) {
@@ -46,12 +48,17 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
-        return ReadWriteHelper.readCharHelper(nchars, getChannel(), useBytes);
+        if (useBytes) {
+            return ReadWriteHelper.readCharHelper(nchars, getInputStream());
+        } else {
+            final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
+            return ReadWriteHelper.readCharHelper(nchars, isr);
+        }
     }
 
     @Override
     public int readBin(ByteBuffer buffer) throws IOException {
-        return getChannel().read(buffer);
+        return getInputStream().read(buffer.array());
     }
 
     @Override
@@ -62,7 +69,7 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul, base.getSummaryDescription(), base.getEncoding());
+        return ReadWriteHelper.readLinesHelper(base, getInputStream(), n, warn, skipNul);
     }
 
     @Override
@@ -86,16 +93,11 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
     }
 
     @Override
-    public abstract ReadableByteChannel getChannel();
-
-    @Override
-    public InputStream getInputStream() {
-        return Channels.newInputStream(getChannel());
-    }
+    public abstract InputStream getInputStream();
 
     @Override
     public void close() throws IOException {
-        getChannel().close();
+        getInputStream().close();
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
new file mode 100644
index 0000000000..efd4f493cf
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
@@ -0,0 +1,112 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.Channels;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection {
+
+    protected DelegateReadWriteNonBlockRConnection(BaseRConnection base) {
+        super(base);
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    public int getc() throws IOException {
+        return getInputStream().read();
+    }
+
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        if (useBytes) {
+            return ReadWriteHelper.readCharHelper(nchars, getInputStream());
+        } else {
+            final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
+            return ReadWriteHelper.readCharHelper(nchars, isr);
+        }
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        return getChannel().read(buffer);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+    }
+
+    @TruffleBoundary
+    @Override
+    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        return ReadWriteHelper.readLinesHelper(base, getInputStream(), n, warn, skipNul);
+    }
+
+    @Override
+    public void flush() {
+        // nothing to do for channels
+    }
+
+    @Override
+    public OutputStream getOutputStream() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    public abstract ByteChannel getChannel();
+
+    @Override
+    @Deprecated
+    public InputStream getInputStream() {
+        return Channels.newInputStream(getChannel());
+    }
+
+    @Override
+    public void close() throws IOException {
+        getChannel().close();
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        getChannel().write(buffer);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+    }
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index ce50eff302..09ac19ae6f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -2,16 +2,17 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
-import java.nio.channels.Channels;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
+/**
+ * A blocking connection for reading and writing.
+ */
 abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     protected DelegateReadWriteRConnection(BaseRConnection base) {
@@ -35,12 +36,17 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
-        return ReadWriteHelper.readCharHelper(nchars, getChannel(), useBytes);
+        if (useBytes) {
+            return ReadWriteHelper.readCharHelper(nchars, getInputStream());
+        } else {
+            final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
+            return ReadWriteHelper.readCharHelper(nchars, isr);
+        }
     }
 
     @Override
     public int readBin(ByteBuffer buffer) throws IOException {
-        return getChannel().read(buffer);
+        return getInputStream().read(buffer.array());
     }
 
     @Override
@@ -51,7 +57,7 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(getInputStream(), n, warn, skipNul, base.getSummaryDescription(), base.getEncoding());
+        return ReadWriteHelper.readLinesHelper(base, getInputStream(), n, warn, skipNul);
     }
 
     @Override
@@ -60,21 +66,15 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     }
 
     @Override
-    public OutputStream getOutputStream() {
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    @Override
-    public abstract ByteChannel getChannel();
+    public abstract OutputStream getOutputStream();
 
     @Override
-    public InputStream getInputStream() {
-        return Channels.newInputStream(getChannel());
-    }
+    public abstract InputStream getInputStream();
 
     @Override
     public void close() throws IOException {
-        getChannel().close();
+        getInputStream().close();
+        getOutputStream().close();
     }
 
     @Override
@@ -85,22 +85,22 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeBin(ByteBuffer buffer) throws IOException {
-        getChannel().write(buffer);
+        getOutputStream().write(buffer.array());
     }
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+        ReadWriteHelper.writeCharHelper(getOutputStream(), s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        ReadWriteHelper.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+        ReadWriteHelper.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
new file mode 100644
index 0000000000..41119a8f36
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
@@ -0,0 +1,106 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+abstract class DelegateWriteNonBlockRConnection extends DelegateRConnection {
+
+    protected DelegateWriteNonBlockRConnection(BaseRConnection base) {
+        super(base);
+    }
+
+    @Override
+    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public int getc() throws IOException {
+        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
+    }
+
+    @Override
+    public InputStream getInputStream() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public boolean canRead() {
+        return false;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
+
+    @Override
+    public void flush() throws IOException {
+        // channels don't need any flushing
+    }
+
+    @Override
+    public void close() throws IOException {
+        flush();
+        getChannel().close();
+    }
+
+    public abstract WritableByteChannel getChannel();
+
+    @Override
+    @Deprecated
+    public OutputStream getOutputStream() throws IOException {
+        return Channels.newOutputStream(getChannel());
+    }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        getChannel().write(buffer);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+    }
+
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 25028a9ef1..97ec636bdc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -4,8 +4,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.WritableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -66,41 +64,36 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
 
     @Override
     public void flush() throws IOException {
-        // channels don't need any flushing
+        getOutputStream().flush();
     }
 
     @Override
     public void close() throws IOException {
         flush();
-        getChannel().close();
+        getOutputStream().close();
     }
 
     @Override
-    public abstract WritableByteChannel getChannel();
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        return Channels.newOutputStream(getChannel());
-    }
+    public abstract OutputStream getOutputStream() throws IOException;
 
     @Override
     public void writeBin(ByteBuffer buffer) throws IOException {
-        getChannel().write(buffer);
+        getOutputStream().write(buffer.array());
     }
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+        ReadWriteHelper.writeCharHelper(getOutputStream(), s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        ReadWriteHelper.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+        ReadWriteHelper.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index 43a27a0faf..72327193e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -27,8 +27,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
 import java.lang.ProcessBuilder.Redirect;
+import java.nio.channels.ByteChannel;
 import java.nio.channels.FileChannel;
 import java.nio.channels.SeekableByteChannel;
+import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.OpenOption;
 import java.nio.file.Paths;
@@ -47,8 +49,8 @@ public class FifoConnections {
 
         private final String path;
 
-        public FifoRConnection(String path, String open, boolean blocking, String encoding) throws IOException {
-            super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, blocking);
+        public FifoRConnection(String path, String open, boolean blocking, Charset encoding) throws IOException {
+            super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, blocking, encoding);
             this.path = path;
             openNonLazyConnection();
         }
@@ -127,11 +129,6 @@ public class FifoConnections {
             raf = new RandomAccessFile(path, "r");
         }
 
-        @Override
-        public SeekableByteChannel getChannel() {
-            return raf.getChannel();
-        }
-
         @Override
         public void close() throws IOException {
             raf.close();
@@ -141,9 +138,15 @@ public class FifoConnections {
         public boolean isSeekable() {
             return false;
         }
+
+        @Override
+        public InputStream getInputStream() {
+            // TODO Auto-generated method stub
+            return null;
+        }
     }
 
-    private static class FifoWriteConnection extends DelegateWriteRConnection {
+    private static class FifoWriteConnection extends DelegateWriteNonBlockRConnection {
         private final RandomAccessFile raf;
 
         FifoWriteConnection(BaseRConnection base, String path) throws IOException {
@@ -167,7 +170,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoReadWriteConnection extends DelegateReadWriteRConnection {
+    private static class FifoReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
 
         private final RandomAccessFile raf;
 
@@ -177,18 +180,18 @@ public class FifoConnections {
         }
 
         @Override
-        public SeekableByteChannel getChannel() {
-            return raf.getChannel();
+        public boolean isSeekable() {
+            return false;
         }
 
         @Override
-        public boolean isSeekable() {
-            return false;
+        public ByteChannel getChannel() {
+            return raf.getChannel();
         }
 
     }
 
-    static class FifoReadNonBlockingRConnection extends DelegateReadRConnection {
+    static class FifoReadNonBlockingRConnection extends DelegateReadNonBlockRConnection {
         private final FileChannel channel;
 
         protected FifoReadNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
@@ -207,7 +210,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoWriteNonBlockingRConnection extends DelegateWriteRConnection {
+    private static class FifoWriteNonBlockingRConnection extends DelegateWriteNonBlockRConnection {
         private final FileChannel channel;
 
         FifoWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
@@ -226,7 +229,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoReadWriteNonBlockingRConnection extends DelegateReadWriteRConnection {
+    private static class FifoReadWriteNonBlockingRConnection extends DelegateReadWriteNonBlockRConnection {
         private final FileChannel channel;
 
         FifoReadWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index f6de8632eb..ffdb0d239d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -32,18 +32,7 @@ import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.SeekableByteChannel;
-import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.OpenOption;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
@@ -88,8 +77,6 @@ public class FileConnections {
         @Override
         protected void createDelegateConnection() throws IOException {
 
-            // TODO (non-)blocking
-
             DelegateRConnection delegate = FileConnections.createDelegateConnection(this, RCompression.Type.NONE);
             setDelegate(delegate);
         }
@@ -98,12 +85,13 @@ public class FileConnections {
     private static DelegateRConnection createUncompressedDelegateConnection(BasePathRConnection base)
                     throws IOException {
 
-        // TODO (non-)blocking
-
         DelegateRConnection delegate = null;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
-                delegate = new FileReadTextRConnection(base, true);
+                delegate = new FileReadTextRConnection(base);
+                break;
+            case ReadBinary:
+                delegate = new FileReadBinaryRConnection(base);
                 break;
             case Write:
                 delegate = new FileWriteTextRConnection(base, false);
@@ -111,11 +99,8 @@ public class FileConnections {
             case Append:
                 delegate = new FileWriteTextRConnection(base, true);
                 break;
-            case ReadBinary:
-                delegate = new FileReadBinaryRConnection(base);
-                break;
             case WriteBinary:
-                delegate = new FileWriteBinaryConnection(base, false, true);
+                delegate = new FileWriteBinaryConnection(base, false);
                 break;
             case ReadWriteTrunc:
             case ReadWriteTruncBinary:
@@ -129,8 +114,6 @@ public class FileConnections {
 
     private static DelegateRConnection createGZIPDelegateConnection(BasePathRConnection base) throws IOException {
 
-        // TODO (non-)blocking
-
         boolean append = false;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
@@ -150,8 +133,6 @@ public class FileConnections {
 
     private static DelegateRConnection createXZDelegateConnection(BasePathRConnection base) throws IOException {
 
-        // TODO (non-)blocking
-
         boolean append = false;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
@@ -171,8 +152,6 @@ public class FileConnections {
 
     private static DelegateRConnection createBZIP2DelegateConnection(BasePathRConnection base) throws IOException {
 
-        // TODO (non-)blocking
-
         boolean append = false;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
@@ -236,135 +215,68 @@ public class FileConnections {
         }
     }
 
-    static class FileReadTextRConnection extends DelegateReadRConnection {
+    static class FileReadBinaryRConnection extends DelegateReadRConnection {
 
-        private final ReadableByteChannel channel;
+        private final FileInputStream inputStream;
 
-        FileReadTextRConnection(BasePathRConnection base, boolean blocking) throws IOException {
+        FileReadBinaryRConnection(BasePathRConnection base) throws IOException {
             super(base);
-
-            // FIXME: since streams are used to open the file, this is BLOCKING by default !
-
-            // can be compressed - check for it
-            RCompression.Type cType = RCompression.getCompressionType(base.path);
-            switch (cType) {
-                case NONE:
-                    channel = Files.newByteChannel(Paths.get(base.path), StandardOpenOption.READ);
-                    break;
-                case GZIP:
-                    channel = Channels.newChannel(new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE));
-                    break;
-                case BZIP2:
-                    // no in Java support, so go via byte array
-                    byte[] bzipUdata = RCompression.bzipUncompressFromFile(base.path);
-                    channel = new SeekableMemoryByteChannel(bzipUdata);
-                    break;
-                case XZ:
-                    channel = Channels.newChannel(new XZInputStream(new FileInputStream(base.path)));
-                    break;
-                default:
-                    throw RError.nyi(RError.SHOW_CALLER2, "compression type: " + cType.name());
-            }
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
+            inputStream = new FileInputStream(base.path);
         }
 
         @Override
-        public byte[] readBinChars() throws IOException {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
+        public boolean isSeekable() {
+            return true;
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
-            return channel;
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return ReadWriteHelper.seek(inputStream.getChannel(), offset, seekMode, seekRWMode);
         }
 
         @Override
-        public boolean isSeekable() {
-            // TODO Auto-generated method stub
-            return false;
+        public InputStream getInputStream() {
+            return inputStream;
         }
 
     }
 
-    private static class FileWriteTextRConnection extends DelegateWriteRConnection {
-
-        private final SeekableByteChannel channel;
+    static class FileReadTextRConnection extends FileReadBinaryRConnection {
 
-        /**
-         * Opens a file for writing.
-         *
-         * @param base The base connection.
-         * @param append If {@code true}, the file cursor is positioned at the end and write
-         *            operations append to the file. If {@code false}, the file will be truncated.
-         * @throws IOException
-         */
-        FileWriteTextRConnection(BasePathRConnection base, boolean append) throws IOException {
+        FileReadTextRConnection(BasePathRConnection base) throws IOException {
             super(base);
-            List<OpenOption> opts = new ArrayList<>();
-            opts.add(StandardOpenOption.WRITE);
-            opts.add(StandardOpenOption.CREATE);
-            if (append) {
-                opts.add(StandardOpenOption.APPEND);
-            } else {
-                opts.add(StandardOpenOption.TRUNCATE_EXISTING);
-            }
-
-            channel = Files.newByteChannel(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
         }
 
         @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+        public int readBin(ByteBuffer buffer) throws IOException {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
         }
 
         @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
+        public byte[] readBinChars() throws IOException {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_READ_BINARY_CONNECTION);
         }
+    }
 
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
-        }
+    private static class FileWriteTextRConnection extends FileWriteBinaryConnection {
 
-        @Override
-        public SeekableByteChannel getChannel() {
-            return channel;
+        FileWriteTextRConnection(BasePathRConnection base, boolean append) throws IOException {
+            super(base, append);
         }
 
         @Override
-        public boolean isSeekable() {
-            return false;
+        public void writeBin(ByteBuffer buffer) throws IOException {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
         }
-
     }
 
-    static class FileReadBinaryRConnection extends DelegateReadRConnection {
-        private final FileInputStream inputStream;
-
-        FileReadBinaryRConnection(BasePathRConnection base) throws IOException {
-            super(base);
-            inputStream = new FileInputStream(base.path);
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            return inputStream;
-        }
+    private static class FileWriteBinaryConnection extends DelegateWriteRConnection {
 
-        @Override
-        public void closeAndDestroy() throws IOException {
-            base.closed = true;
-            close();
-        }
+        private final FileOutputStream out;
 
-        @Override
-        public void close() throws IOException {
-            inputStream.close();
+        FileWriteBinaryConnection(BasePathRConnection base, boolean append) throws IOException {
+            super(base);
+            out = new FileOutputStream(base.path, append);
         }
 
         @Override
@@ -374,63 +286,17 @@ public class FileConnections {
 
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            long position = inputStream.getChannel().position();
-            switch (seekMode) {
-                case ENQUIRE:
-                    break;
-                case CURRENT:
-                    if (offset != 0) {
-                        inputStream.getChannel().position(position + offset);
-                    }
-                    break;
-                case START:
-                    inputStream.getChannel().position(offset);
-                    break;
-                case END:
-                    throw RInternalError.unimplemented();
-
-            }
-            return position;
+            return ReadWriteHelper.seek(out.getChannel(), offset, seekMode, seekRWMode);
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
-            return inputStream.getChannel();
-        }
-    }
-
-    private static class FileWriteBinaryConnection extends DelegateWriteRConnection {
-
-        private final SeekableByteChannel channel;
-
-        FileWriteBinaryConnection(BasePathRConnection base, boolean append, boolean blocking) throws IOException {
-            super(base);
-
-            List<OpenOption> args = new LinkedList<>();
-            args.add(StandardOpenOption.WRITE);
-            args.add(StandardOpenOption.CREATE);
-            if (append) {
-                args.add(StandardOpenOption.APPEND);
-            } else {
-                args.add(StandardOpenOption.TRUNCATE_EXISTING);
-            }
-
-            channel = Files.newByteChannel(Paths.get(base.path), args.toArray(new OpenOption[args.size()]));
-        }
-
-        @Override
-        public WritableByteChannel getChannel() {
-            return channel;
-        }
-
-        @Override
-        public boolean isSeekable() {
-            return true;
+        public OutputStream getOutputStream() throws IOException {
+            return out;
         }
 
     }
 
-    private static class FileReadWriteConnection extends DelegateReadWriteRConnection {
+    private static class FileReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
         /*
          * This is a minimal implementation to support one specific use in package installation.
          *
@@ -442,18 +308,6 @@ public class FileConnections {
         private long readOffset;
         private long writeOffset;
         private SeekRWMode lastMode = SeekRWMode.READ;
-        private final RAFInputStream inputStream;
-
-        /**
-         * Allows an {@link RandomAccessFile} to appear to be an {@link InputStream}.
-         *
-         */
-        private class RAFInputStream extends InputStream {
-            @Override
-            public int read() throws IOException {
-                return FileReadWriteConnection.this.getc();
-            }
-        }
 
         FileReadWriteConnection(BasePathRConnection base) throws IOException {
             super(base);
@@ -468,7 +322,6 @@ public class FileConnections {
                     throw RInternalError.shouldNotReachHere();
             }
             raf = new RandomAccessFile(base.path, rafMode);
-            inputStream = new RAFInputStream();
         }
 
         @Override
@@ -487,7 +340,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             long result = raf.getFilePointer();
             switch (seekMode) {
                 case ENQUIRE:
@@ -518,7 +371,7 @@ public class FileConnections {
         @Override
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
             raf.seek(readOffset);
-            return super.readLines(n, warn, skipNul);
+            return super.readLinesInternal(n, warn, skipNul);
         }
 
         @Override
@@ -528,9 +381,8 @@ public class FileConnections {
 
         @Override
         public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            // TODO encodings
             raf.seek(writeOffset);
-            byte[] sepData = sep.getBytes();
+            byte[] sepData = sep.getBytes(base.getEncoding());
             for (int i = 0; i < lines.getLength(); i++) {
                 writeString(lines.getDataAt(i), false);
                 raf.write(sepData);
@@ -541,41 +393,17 @@ public class FileConnections {
 
         @Override
         public void writeString(String s, boolean nl) throws IOException {
-            raf.write(s.getBytes());
+            raf.write(s.getBytes(base.getEncoding()));
             if (nl) {
-                raf.writeBytes(System.lineSeparator());
+                raf.write(System.lineSeparator().getBytes(base.getEncoding()));
             }
         }
 
-        @Override
-        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
-        @Override
-        public String readChar(int nchars, boolean useBytes) throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
-        @Override
-        public int readBin(ByteBuffer buffer) throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
-        @Override
-        public byte[] readBinChars() throws IOException {
-            throw RInternalError.unimplemented();
-        }
-
         @Override
         public ByteChannel getChannel() {
             return raf.getChannel();
         }
+
     }
 
     /**
@@ -619,11 +447,6 @@ public class FileConnections {
             this.seekable = seekable;
         }
 
-        @Override
-        public ReadableByteChannel getChannel() {
-            return Channels.newChannel(inputStream);
-        }
-
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             if (seekable) {
@@ -636,6 +459,11 @@ public class FileConnections {
         public boolean isSeekable() {
             return seekable;
         }
+
+        @Override
+        public InputStream getInputStream() {
+            return inputStream;
+        }
     }
 
     private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection {
@@ -646,14 +474,12 @@ public class FileConnections {
 
     private static class CompressedOutputRConnection extends DelegateWriteRConnection {
         protected OutputStream outputStream;
-        private final WritableByteChannel channel;
         private final boolean seekable;
         private long seekPosition = 0L;
 
         protected CompressedOutputRConnection(BasePathRConnection base, OutputStream os, boolean seekable) {
             super(base);
             this.outputStream = os;
-            this.channel = Channels.newChannel(os);
             this.seekable = seekable;
         }
 
@@ -679,11 +505,6 @@ public class FileConnections {
             outputStream.flush();
         }
 
-        @Override
-        public WritableByteChannel getChannel() {
-            return channel;
-        }
-
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             if (seekable) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
index a9f9f839d2..4ca8f92405 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -26,11 +26,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.ProcessBuilder.Redirect;
-import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -102,11 +97,6 @@ public class PipeConnections {
             in = p.getInputStream();
         }
 
-        @Override
-        public ReadableByteChannel getChannel() {
-            return Channels.newChannel(in);
-        }
-
         @Override
         public InputStream getInputStream() {
             return in;
@@ -132,11 +122,6 @@ public class PipeConnections {
             out = p.getOutputStream();
         }
 
-        @Override
-        public WritableByteChannel getChannel() {
-            return Channels.newChannel(out);
-        }
-
         @Override
         public OutputStream getOutputStream() throws IOException {
             return out;
@@ -165,11 +150,6 @@ public class PipeConnections {
             out = p.getOutputStream();
         }
 
-        @Override
-        public ByteChannel getChannel() {
-            return new ReadableWriteableChannel(Channels.newChannel(in), Channels.newChannel(out));
-        }
-
         @Override
         public InputStream getInputStream() {
             return in;
@@ -187,38 +167,4 @@ public class PipeConnections {
 
     }
 
-    private static class ReadableWriteableChannel implements ByteChannel {
-
-        private final ReadableByteChannel rb;
-        private final WritableByteChannel wb;
-
-        public ReadableWriteableChannel(ReadableByteChannel rb, WritableByteChannel wb) {
-            super();
-            this.rb = rb;
-            this.wb = wb;
-        }
-
-        @Override
-        public int read(ByteBuffer dst) throws IOException {
-            return rb.read(dst);
-        }
-
-        @Override
-        public boolean isOpen() {
-            return rb.isOpen() && wb.isOpen();
-        }
-
-        @Override
-        public void close() throws IOException {
-            rb.close();
-            wb.close();
-        }
-
-        @Override
-        public int write(ByteBuffer src) throws IOException {
-            return wb.write(src);
-        }
-
-    }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 3e7a760d9c..7bc6f28b9f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -30,7 +30,6 @@ import java.util.LinkedList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
@@ -268,14 +267,14 @@ public abstract class RConnection implements AutoCloseable {
     /**
      * Support for {@code seek} Internal. Also clears push back lines.
      */
-    public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+    public final long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
         if (isSeekable()) {
             // discard any push back strings
             pushBackClear();
-
-            return seekInternal(offset, seekMode, seekRWMode);
         }
-        throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_ENABLED);
+        // Do not throw error at this position, since the error messages varies depending on the
+        // connection.
+        return seekInternal(offset, seekMode, seekRWMode);
     }
 
     /**
@@ -363,4 +362,8 @@ public abstract class RConnection implements AutoCloseable {
         return incomplete;
     }
 
+    protected void setIncomplete(boolean b) {
+        this.incomplete = b;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index fec3a53929..2f87e573b8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.SeekableByteChannel;
 import java.util.Objects;
@@ -115,7 +114,7 @@ public class RawConnections {
 
     }
 
-    static class RawReadRConnection extends DelegateReadRConnection {
+    static class RawReadRConnection extends DelegateReadNonBlockRConnection {
         private SeekableMemoryByteChannel channel;
 
         RawReadRConnection(BaseRConnection base, SeekableMemoryByteChannel channel) {
@@ -164,7 +163,7 @@ public class RawConnections {
         }
     }
 
-    private static class RawWriteBinaryConnection extends DelegateWriteRConnection {
+    private static class RawWriteBinaryConnection extends DelegateWriteNonBlockRConnection {
         private final SeekableMemoryByteChannel channel;
 
         RawWriteBinaryConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
@@ -179,16 +178,6 @@ public class RawConnections {
             }
         }
 
-        @Override
-        public void writeBin(ByteBuffer buffer) throws IOException {
-            channel.write(buffer);
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return channel.getOutputStream();
-        }
-
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
@@ -205,7 +194,7 @@ public class RawConnections {
         }
     }
 
-    private static class RawReadWriteConnection extends DelegateReadWriteRConnection {
+    private static class RawReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
 
         private final SeekableMemoryByteChannel channel;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
index 8aa5483305..83eb6723bb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
@@ -4,6 +4,7 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.Reader;
 import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
@@ -13,11 +14,14 @@ import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection.SeekMode;
 import com.oracle.truffle.r.runtime.conn.RConnection.SeekRWMode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.sun.istack.internal.NotNull;
 
+import sun.nio.cs.StreamDecoder;
+
 public class ReadWriteHelper {
 
     /**
@@ -28,7 +32,7 @@ public class ReadWriteHelper {
      * @param warn TODO
      * @param skipNul TODO
      */
-    public static String[] readLinesHelper(InputStream in, int n, boolean warn, boolean skipNul, String description, Charset encoding) throws IOException {
+    public static String[] readLinesHelper(BaseRConnection conn, InputStream in, int n, boolean warn, boolean skipNul) throws IOException {
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
         byte[] buffer = new byte[64];
@@ -50,9 +54,9 @@ public class ReadWriteHelper {
                      * refactoring is needed to be able to reliably access the "name" for the
                      * warning.
                      */
-                    lines.add(new String(buffer, 0, totalRead, encoding));
+                    lines.add(new String(buffer, 0, totalRead, conn.getEncoding()));
                     if (warn) {
-                        RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, description);
+                        RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, conn.getSummaryDescription());
                     }
                 }
                 break;
@@ -69,13 +73,13 @@ public class ReadWriteHelper {
                 }
             }
             if (lineEnd) {
-                lines.add(new String(buffer, 0, totalRead, encoding));
+                lines.add(new String(buffer, 0, totalRead, conn.getEncoding()));
                 if (n > 0 && lines.size() == n) {
                     break;
                 }
                 totalRead = 0;
             } else {
-                buffer = ConnectionSupport.checkBuffer(buffer, totalRead);
+                buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
                 buffer[totalRead++] = (byte) (ch & 0xFF);
             }
         }
@@ -84,6 +88,14 @@ public class ReadWriteHelper {
         return result;
     }
 
+    public static void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
+        for (int i = 0; i < lines.getLength(); i++) {
+            final String line = lines.getDataAt(i);
+            writeStringHelper(out, line, false, encoding);
+            writeStringHelper(out, sep, false, encoding);
+        }
+    }
+
     public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
         for (int i = 0; i < lines.getLength(); i++) {
             final String line = lines.getDataAt(i);
@@ -92,6 +104,13 @@ public class ReadWriteHelper {
         }
     }
 
+    public static void writeStringHelper(OutputStream out, String s, boolean nl, Charset encoding) throws IOException {
+        out.write(s.getBytes(encoding));
+        if (nl) {
+            out.write(System.lineSeparator().getBytes(encoding));
+        }
+    }
+
     public static void writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
         final byte[] bytes = s.getBytes(encoding);
         final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes(encoding) : null;
@@ -106,6 +125,32 @@ public class ReadWriteHelper {
         out.write(buf);
     }
 
+    /**
+     * Writes characters in binary mode (without any re-encoding) to the provided channel.
+     *
+     * @param out The output stream (must not be {@code null}.
+     * @param s The character string to write (must not be {@code null}).
+     * @param pad The number of null characters to append to the characters.
+     * @param eos The end-of-string terminator (may be {@code null}).
+     * @throws IOException
+     */
+    public static void writeCharHelper(OutputStream out, String s, int pad, String eos) throws IOException {
+
+        out.write(s.getBytes());
+        if (pad > 0) {
+            for (int i = 0; i < pad; i++) {
+                out.write(0);
+            }
+        }
+        if (eos != null) {
+            if (eos.length() > 0) {
+                out.write(eos.getBytes());
+            }
+            // function writeChar is defined to append the null character if eos != null
+            out.write(0);
+        }
+    }
+
     /**
      * Writes characters in binary mode (without any re-encoding) to the provided channel.
      *
@@ -148,6 +193,29 @@ public class ReadWriteHelper {
         outputStream.write(b);
     }
 
+    /**
+     * Reads null-terminated character strings from a {@link ReadableByteChannel}.
+     */
+    public static byte[] readBinCharsHelper(ReadableByteChannel channel) throws IOException {
+        ByteBuffer buf = ByteBuffer.allocate(1);
+        int numRead = channel.read(buf);
+        if (numRead <= 0) {
+            return null;
+        }
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        while (true) {
+            buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
+            buffer[totalRead++] = (byte) (buf.get() & 0xFF);
+            if (numRead == 0) {
+                break;
+            }
+            buf.clear();
+            numRead = channel.read(buf);
+        }
+        return buffer;
+    }
+
     /**
      * Reads null-terminated character strings from a {@link InputStream}.
      */
@@ -159,7 +227,7 @@ public class ReadWriteHelper {
         int totalRead = 0;
         byte[] buffer = new byte[64];
         while (true) {
-            buffer = ConnectionSupport.checkBuffer(buffer, totalRead);
+            buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
             buffer[totalRead++] = (byte) (ch & 0xFF);
             if (ch == 0) {
                 break;
@@ -181,18 +249,78 @@ public class ReadWriteHelper {
         return totalRead;
     }
 
-    public static String readCharHelper(int nchars, ReadableByteChannel channel, @SuppressWarnings("unused") boolean useBytes) throws IOException {
-        ByteBuffer buf = ByteBuffer.allocate(nchars);
-        channel.read(buf);
+    /**
+     * Reads a specified amount of characters.
+     *
+     * @param nchars Number of characters to read.
+     * @param in The encoded byte stream.
+     * @return The read string.
+     * @throws IOException
+     */
+    public static String readCharHelper(int nchars, Reader in) throws IOException {
+        char[] chars = new char[nchars];
+        in.read(chars);
+        int j = 0;
+        for (; j < chars.length; j++) {
+            // strings end at 0
+            if (chars[j] == 0) {
+                break;
+            }
+        }
+
+        return new String(chars, 0, j);
+    }
+
+    /**
+     * Reads a specified amount of bytes.
+     *
+     * @param nchars The number of bytes to read.
+     * @param in The input stream.
+     * @return The read string.
+     * @throws IOException
+     */
+    public static String readCharHelper(int nchars, InputStream in) throws IOException {
+        byte[] buf = new byte[nchars];
+        in.read(buf);
         int j = 0;
-        for (; j < buf.position(); j++) {
+        for (; j < buf.length; j++) {
             // strings end at 0
-            if (buf.get(j) == 0) {
+            if (buf[j] == 0) {
                 break;
             }
         }
 
-        return new String(buf.array(), 0, j);
+        return new String(buf, 0, j);
+    }
+
+    public static String readCharHelper(int nchars, ReadableByteChannel channel, boolean useBytes) throws IOException {
+        if (useBytes) {
+            ByteBuffer buf = ByteBuffer.allocate(nchars);
+            channel.read(buf);
+            int j = 0;
+            for (; j < buf.position(); j++) {
+                // strings end at 0
+                if (buf.get(j) == 0) {
+                    break;
+                }
+            }
+
+            return new String(buf.array(), 0, j);
+        } else {
+            // we need a decoder
+            StreamDecoder decoder = StreamDecoder.forDecoder(channel, Charset.defaultCharset().newDecoder(), nchars);
+            char[] chars = new char[nchars];
+            decoder.read(chars);
+            int j = 0;
+            for (; j < chars.length; j++) {
+                // strings end at 0
+                if (chars[j] == 0) {
+                    break;
+                }
+            }
+
+            return new String(chars, 0, j);
+        }
     }
 
     /**
@@ -217,4 +345,23 @@ public class ReadWriteHelper {
         }
         return position;
     }
+
+    /**
+     * Enlarges the buffer if necessary.
+     */
+    private static byte[] checkBuffer(byte[] buffer, int n) {
+        if (n > buffer.length - 1) {
+            byte[] newBuffer = new byte[buffer.length + buffer.length / 2];
+            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+            return newBuffer;
+        } else {
+            return buffer;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static String[] readLinesNonBlockHelper(BaseRConnection conn, ReadableByteChannel channel, int n, boolean warn, boolean skipNul, String summaryDescription, Charset encoding) {
+
+        throw RInternalError.unimplemented();
+    }
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index c635f00f86..e873b6585b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
@@ -59,7 +60,16 @@ public class SocketConnections {
 
         @Override
         protected void createDelegateConnection() throws IOException {
-            DelegateRConnection delegate = server ? new RServerSocketConnection(this) : new RClientSocketConnection(this);
+            DelegateRConnection delegate;
+            if (server) {
+                delegate = new RServerSocketConnection(this);
+            } else {
+                if (isBlocking()) {
+                    delegate = new RClientSocketConnection(this);
+                } else {
+                    delegate = new RClientSocketNonBlockConnection(this);
+                }
+            }
             setDelegate(delegate);
         }
 
@@ -71,7 +81,7 @@ public class SocketConnections {
 
     private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection {
         private Socket socket;
-        private SocketChannel socketChannel;
+        protected InputStream inputStream;
         protected OutputStream outputStream;
         protected final RSocketConnection thisBase;
 
@@ -82,7 +92,6 @@ public class SocketConnections {
 
         protected void openStreams(Socket socketArg) throws IOException {
             this.socket = socketArg;
-            this.socketChannel = socket.getChannel();
             if (thisBase.isBlocking()) {
                 // Java (int) timeouts do not meet the POSIX standard of 31 days
                 long millisTimeout = ((long) thisBase.timeout) * 1000;
@@ -90,9 +99,8 @@ public class SocketConnections {
                     millisTimeout = Integer.MAX_VALUE;
                 }
                 socket.setSoTimeout((int) millisTimeout);
-            } else {
-                socketChannel.configureBlocking(false);
             }
+            inputStream = socket.getInputStream();
             outputStream = socket.getOutputStream();
         }
 
@@ -106,9 +114,39 @@ public class SocketConnections {
             }
         }
 
+        @Override
+        public InputStream getInputStream() {
+            return inputStream;
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            return outputStream;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+    }
+
+    private abstract static class RSocketReadWriteNonBlockConnection extends DelegateReadWriteNonBlockRConnection {
+        private Socket socket;
+        private SocketChannel socketChannel;
+
+        protected RSocketReadWriteNonBlockConnection(RSocketConnection base) {
+            super(base);
+        }
+
+        protected void openStreams(Socket socketArg) throws IOException {
+            this.socket = socketArg;
+            this.socketChannel = socket.getChannel();
+            socketChannel.configureBlocking(false);
+        }
+
         @Override
         public void close() throws IOException {
-            // TODO(fa) I'm not sure if socket.close() is the same as channel.close()
+            socketChannel.close();
             socket.close();
         }
 
@@ -156,4 +194,13 @@ public class SocketConnections {
             openStreams(socketChannel.socket());
         }
     }
+
+    private static class RClientSocketNonBlockConnection extends RSocketReadWriteNonBlockConnection {
+
+        RClientSocketNonBlockConnection(RSocketConnection base) throws IOException {
+            super(base);
+            SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(base.host, base.port));
+            openStreams(socketChannel.socket());
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 22f8ca5d23..1f1c7541c3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -171,7 +171,7 @@ public class StdConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.UNSEEKABLE_CONNECTION);
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index aad53cdb61..b751437d15 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -23,10 +23,9 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -125,13 +124,13 @@ public class TextConnections {
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
-            throw RInternalError.shouldNotReachHere();
+        public boolean isSeekable() {
+            return false;
         }
 
         @Override
-        public boolean isSeekable() {
-            return false;
+        public InputStream getInputStream() {
+            throw RInternalError.shouldNotReachHere();
         }
     }
 
@@ -295,12 +294,6 @@ public class TextConnections {
             }
         }
 
-        @Override
-        public WritableByteChannel getChannel() {
-            // no channel available for a text connection
-            return null;
-        }
-
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_RELEVANT_FOR_TEXT_CON);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index 1b76ab39b5..a7bbc085ba 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -27,8 +27,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
@@ -78,16 +76,6 @@ public class URLConnections {
             return inputStream;
         }
 
-        @Override
-        public void close() throws IOException {
-            inputStream.close();
-        }
-
-        @Override
-        public ReadableByteChannel getChannel() {
-            return Channels.newChannel(inputStream);
-        }
-
         @Override
         public boolean isSeekable() {
             return false;
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 914d4ea03d..117a667456 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
@@ -21077,13 +21077,14 @@ fifo
 TRUE
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenInexisting#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
-#{ zz <- fifo("/tmp/pipe3408688236", "r"); close(zz); }
-Error in fifo("/tmp/pipe3408688236", "r") : cannot open the connection
+#{ zz <- fifo("/tmp/pipe3408688236", "r", blocking = TRUE); close(zz); }
+Error in fifo("/tmp/pipe3408688236", "r", blocking = TRUE) :
+  cannot open the connection
 In addition: Warning message:
-In fifo("/tmp/pipe3408688236", "r") :
+In fifo("/tmp/pipe3408688236", "r", blocking = TRUE) :
   cannot open fifo '/tmp/pipe3408688236'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenNonBlocking#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenNonBlocking#Ignored.ImplementationError#
 #{ zz <- fifo("/tmp/pipe3408688236", "r"); close(zz); }
 Error in fifo("/tmp/pipe3408688236", "r") : cannot open the connection
 In addition: Warning message:
@@ -73685,6 +73686,23 @@ Error in seek.connection(zz, 5) :
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testURLPrefixDispatch#
+#{ zz <- file("ftp://invalid.domain.name/"); res <- readLines(zz, 1); close(zz); res }
+Error in readLines(zz, 1) : cannot open the connection
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testURLPrefixDispatch#
+#{ zz <- file("http://invalid.domain.name/"); res <- readLines(zz, 1); close(zz); res }
+Error in readLines(zz, 1) : cannot open the connection
+In addition: Warning message:
+In readLines(zz, 1) : unable to resolve 'invalid.domain.name'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testURLPrefixDispatch#
+#{ zz <- file("https://invalid.domain.name/"); res <- readLines(zz, 1); close(zz); res }
+Error in readLines(zz, 1) : cannot open connection
+In addition: Warning message:
+In readLines(zz, 1) :
+  URL 'https://invalid.domain.name/': status was 'Couldn't resolve host name'
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#Ignored.Unimplemented#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
index def25b3376..e7e8c7a475 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
@@ -53,13 +53,13 @@ public class TestBuiltin_fifoConnection extends TestBase {
         assertEval("capabilities(\"fifo\")");
 
         Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
+        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\", blocking = TRUE); close(zz); }");
     }
 
     @Test(timeout = 100)
     public void testFifoOpenNonBlocking() {
         Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
+        assertEval(Ignored.ImplementationError, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
     }
 
     @AfterClass
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index ae88d43b42..e216cf440a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -26,10 +26,7 @@ import static java.nio.file.StandardOpenOption.CREATE;
 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
 import static java.nio.file.StandardOpenOption.WRITE;
 
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
@@ -208,11 +205,6 @@ public class TestConnections extends TestBase {
                         "\", \"w+\", encoding = \"UTF-8\"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }");
     }
 
-    private static String determineFileEncoding(final Path utf8File1) throws FileNotFoundException {
-        InputStreamReader r = new InputStreamReader(new FileInputStream(utf8File1.toFile()));
-        return r.getEncoding().toLowerCase();
-    }
-
     /**
      * Writes a string using the specified charset to the provided file. The file is created and
      * truncated.
-- 
GitLab


From c5e949ff0ef4dc62dafc968e3a9f9fa7e7c4fc62 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 23 Feb 2017 18:37:57 +0100
Subject: [PATCH 069/402] Small fix in warning message.

---
 .../src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java  | 2 +-
 .../r/test/builtins/connection/R/readLines_GnuR_example.R       | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
index 83eb6723bb..f9588cd89d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
@@ -56,7 +56,7 @@ public class ReadWriteHelper {
                      */
                     lines.add(new String(buffer, 0, totalRead, conn.getEncoding()));
                     if (warn) {
-                        RError.warning(RError.SHOW_CALLER2, RError.Message.INCOMPLETE_FINAL_LINE, conn.getSummaryDescription());
+                        RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_FINAL_LINE, conn.getSummaryDescription());
                     }
                 }
                 break;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
index 79e5aea04c..248f32f925 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
@@ -1,3 +1,4 @@
+# IgnoreWarningContext
 cat("TITLE extra line", "2 3 5 7", "", "11 13 17", file = "ex.data", sep = "\n")
 readLines("ex.data", n = -1)
 unlink("ex.data") # tidy up
-- 
GitLab


From b0945b4230dd33e7e0094138a68c02c881bc0ee7 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 24 Feb 2017 11:27:03 +0100
Subject: [PATCH 070/402] Implementes flag "skipNul" for readLines (blocking).
 Added micro tests for several combinations of readLines' flags.

---
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../r/runtime/conn/ReadWriteHelper.java       |  20 +++-
 .../truffle/r/test/ExpectedTestOutput.test    | 100 ++++++++++++++----
 .../r/test/library/base/TestConnections.java  |  26 +++++
 4 files changed, 126 insertions(+), 23 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index c80be71b26..3dd587a168 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -836,7 +836,8 @@ public final class RError extends RuntimeException {
         SEEK_NOT_ENABLED("'seek' not enabled for this connection"),
         CANNOT_OPEN_FIFO("cannot open fifo '%s'"),
         UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'"),
-        UNABLE_TO_RESOLVE("unable to resolve '%s'");
+        UNABLE_TO_RESOLVE("unable to resolve '%s'"),
+        LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
index f9588cd89d..e2eb4edeac 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
@@ -29,14 +29,15 @@ public class ReadWriteHelper {
      * {@link BufferedReader} but mixing binary and text operations, which is a requirement, would
      * then be difficult.
      *
-     * @param warn TODO
-     * @param skipNul TODO
+     * @param warn Specifies if warnings should be output.
+     * @param skipNul Specifies if the null character should be ignored.
      */
     public static String[] readLinesHelper(BaseRConnection conn, InputStream in, int n, boolean warn, boolean skipNul) throws IOException {
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
         byte[] buffer = new byte[64];
         int pushBack = 0;
+        boolean nullRead = false;
         while (true) {
             int ch;
             if (pushBack != 0) {
@@ -71,6 +72,11 @@ public class ReadWriteHelper {
                 } else {
                     pushBack = ch;
                 }
+            } else if (ch == 0) {
+                nullRead = true;
+                if (warn && !skipNul) {
+                    RError.warning(RError.SHOW_CALLER, RError.Message.LINE_CONTAINS_EMBEDDED_NULLS, lines.size() + 1);
+                }
             }
             if (lineEnd) {
                 lines.add(new String(buffer, 0, totalRead, conn.getEncoding()));
@@ -78,9 +84,15 @@ public class ReadWriteHelper {
                     break;
                 }
                 totalRead = 0;
+                nullRead = false;
             } else {
-                buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
-                buffer[totalRead++] = (byte) (ch & 0xFF);
+                if (!nullRead) {
+                    buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
+                    buffer[totalRead++] = (byte) (ch & 0xFF);
+                }
+                if (skipNul) {
+                    nullRead = false;
+                }
             }
         }
         String[] result = new String[lines.size()];
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 117a667456..1683949881 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
@@ -42213,7 +42213,7 @@ raw(0)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#Output.IgnoreWarningContext#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") }
 Warning message:
 In readLines("test1") : incomplete final line found on 'test1'
@@ -73661,6 +73661,87 @@ numeric(0)
 #{ con<-textConnection(c("a","b","c","d")); pushBackLength(con) }
 [1] 0
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+Warning messages:
+1: In readLines(zz, 1, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+2: In readLines(zz, 1, warn = T, skipNul = F) :
+  incomplete final line found on '/tmp/file3762346723'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+Warning message:
+In readLines(zz, 1, warn = T, skipNul = T) :
+  incomplete final line found on '/tmp/file3762346723'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+Warning message:
+In readLines(zz, 1, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+Warning message:
+In readLines(zz, 1, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd"
+Warning message:
+In readLines(zz, 1, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde"
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#
 #{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res }
 [1] FALSE
@@ -73686,23 +73767,6 @@ Error in seek.connection(zz, 5) :
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testURLPrefixDispatch#
-#{ zz <- file("ftp://invalid.domain.name/"); res <- readLines(zz, 1); close(zz); res }
-Error in readLines(zz, 1) : cannot open the connection
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testURLPrefixDispatch#
-#{ zz <- file("http://invalid.domain.name/"); res <- readLines(zz, 1); close(zz); res }
-Error in readLines(zz, 1) : cannot open the connection
-In addition: Warning message:
-In readLines(zz, 1) : unable to resolve 'invalid.domain.name'
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testURLPrefixDispatch#
-#{ zz <- file("https://invalid.domain.name/"); res <- readLines(zz, 1); close(zz); res }
-Error in readLines(zz, 1) : cannot open connection
-In addition: Warning message:
-In readLines(zz, 1) :
-  URL 'https://invalid.domain.name/': status was 'Couldn't resolve host name'
-
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#Ignored.Unimplemented#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index e216cf440a..e100694ad8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -79,6 +79,7 @@ public class TestConnections extends TestBase {
         TEMP_FILES.add(path.resolve("file4039819292"));
         TEMP_FILES.add(path.resolve("file9823674682"));
         TEMP_FILES.add(path.resolve("file3762346723"));
+        TEMP_FILES.add(path.resolve("file8723674332"));
     }
 
     @AfterClass
@@ -205,6 +206,31 @@ public class TestConnections extends TestBase {
                         "\", \"w+\", encoding = \"UTF-8\"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }");
     }
 
+    @Test
+    public void testReadLines() {
+        final Path tmpFile = TEMP_FILES.get(3);
+
+        // one line containing '\0'
+        final String lineWithNul = "c(97,98,99,100,0,101,10)";
+
+        // two lines, first containing '\0'
+        final String twoLinesOneNul = "c(97,98,99,100,0,101,10,65,66,67,10)";
+
+        // one line containing '\0' and imcomplete
+        final String lineWithNulIncomp = "c(97,98,99,100,0,101)";
+
+        // two lines, first containing '\0', second line incomplete
+        final String twoLinesOneNulIncomp = "c(97,98,99,100,0,101,10,65,66,67)";
+
+        assertEval(TestBase.template("{ fn <- \"" + tmpFile +
+                        "\"; zz <- file(fn,\"w+b\"); writeBin(as.raw(%0), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=%1, skipNul=%2); close(zz); unlink(fn); res }",
+                        arr(lineWithNul, twoLinesOneNul, lineWithNulIncomp, twoLinesOneNulIncomp), arr("T", "F"), arr("T", "F")));
+    }
+
+    private static String[] arr(String... args) {
+        return args;
+    }
+
     /**
      * Writes a string using the specified charset to the provided file. The file is created and
      * truncated.
-- 
GitLab


From dfb3b9052fcd5aecce754446955baa28efd24e11 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 10:48:52 +0100
Subject: [PATCH 071/402] Deferred resolving of character set name into
 BaseRConnection. Implemented non-blocking/text-mode behavior of function
 "readLines" (silently pushes back incomplete final lines). Refactored all
 delegate connection implementations to be based on a channel (again).

---
 .../builtin/base/ConnectionFunctions.java     |  40 +-
 .../truffle/r/runtime/RCompression.java       |   4 +
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../r/runtime/conn/ConnectionSupport.java     |  46 ++-
 .../r/runtime/conn/DelegateRConnection.java   | 370 +++++++++++++++++
 .../conn/DelegateReadNonBlockRConnection.java |  12 +-
 .../runtime/conn/DelegateReadRConnection.java |   8 +-
 .../DelegateReadWriteNonBlockRConnection.java |  21 +-
 .../conn/DelegateReadWriteRConnection.java    |  14 +-
 .../DelegateWriteNonBlockRConnection.java     |   6 +-
 .../conn/DelegateWriteRConnection.java        |   6 +-
 .../r/runtime/conn/FifoConnections.java       |  23 +-
 .../r/runtime/conn/FileConnections.java       | 180 ++++-----
 .../r/runtime/conn/PipeConnections.java       |  87 ++--
 .../truffle/r/runtime/conn/RConnection.java   |   2 +-
 .../r/runtime/conn/ReadWriteHelper.java       | 379 ------------------
 .../r/runtime/conn/SocketConnections.java     |  37 +-
 .../r/runtime/conn/TextConnections.java       |  14 +-
 .../r/runtime/conn/URLConnections.java        |  18 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 145 +++++--
 .../connection/R/readLines_GnuR_example.R     |  18 +-
 .../r/test/library/base/TestConnections.java  |  13 +-
 22 files changed, 771 insertions(+), 675 deletions(-)
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index ac5525187e..51dc436711 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -54,7 +54,6 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.DoubleBuffer;
 import java.nio.IntBuffer;
-import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
 
@@ -72,7 +71,6 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.FifoConnections.FifoRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.CompressedRConnection;
@@ -195,7 +193,7 @@ public abstract class ConnectionFunctions {
         }
 
         private static void method(Casts casts) {
-            casts.arg("method").asStringVector().findFirst();
+            casts.arg("method").asStringVector().findFirst().mustBe(equalTo("default").or(equalTo("internal")), RError.Message.UNSUPPORTED_URL_METHOD);
         }
 
         static void blockingNotSupported(Casts casts) {
@@ -218,7 +216,7 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector file(String description, String openArg, @SuppressWarnings("unused") boolean blocking, String encoding, @SuppressWarnings("unused") String method, boolean raw) {
+        protected RAbstractIntVector file(String description, String openArg, boolean blocking, String encoding, @SuppressWarnings("unused") String method, boolean raw) {
             String open = openArg;
 
             // check if the description is an URL and dispatch if necessary
@@ -226,7 +224,7 @@ public abstract class ConnectionFunctions {
             try {
                 URL url = new URL(description);
                 if (!"file".equals(url.getProtocol())) {
-                    return new URLRConnection(description, open).asVector();
+                    return new URLRConnection(description, open, encoding).asVector();
                 } else {
                     path = removeFileURLPrefix(description);
                 }
@@ -249,8 +247,7 @@ public abstract class ConnectionFunctions {
                 }
             }
             try {
-                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
-                return new FileRConnection(path, open, charset).asVector();
+                return new FileRConnection(path, open, blocking, encoding).asVector();
             } catch (IOException ex) {
                 warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
@@ -285,8 +282,7 @@ public abstract class ConnectionFunctions {
         @TruffleBoundary
         protected RAbstractIntVector zzFile(RAbstractStringVector description, String open, String encoding, int compression) {
             try {
-                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
-                return new CompressedRConnection(description.getDataAt(0), open, cType, charset, compression).asVector();
+                return new CompressedRConnection(description.getDataAt(0), open, cType, encoding, compression).asVector();
             } catch (IOException ex) {
                 throw reportError(description.getDataAt(0), ex);
             } catch (IllegalCharsetNameException ex) {
@@ -404,11 +400,19 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector socketConnection(String host, int port, boolean server, boolean blocking, String open, @SuppressWarnings("unused") RAbstractStringVector encoding, int timeout) {
+        protected RAbstractIntVector socketConnection(String host, int port, boolean server, boolean blocking, String open,
+                        String encoding, int timeout) {
             try {
+                if (server) {
+                    return new RSocketConnection(open, true, host, port, blocking, timeout, encoding).asVector();
+                } else {
+                    return new RSocketConnection(open, false, host, port, blocking, timeout, encoding).asVector();
+                }
                 return new RSocketConnection(open, server, host, port, blocking, timeout).asVector();
             } catch (IOException ex) {
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
+            } catch (IllegalCharsetNameException ex) {
+                throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -427,14 +431,16 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, @SuppressWarnings("unused") String encoding,
+        protected RAbstractIntVector urlConnection(String url, String open, @SuppressWarnings("unused") boolean blocking, String encoding,
                         @SuppressWarnings("unused") String method) {
             try {
-                return new URLRConnection(url, open).asVector();
+                return new URLRConnection(url, open, encoding).asVector();
             } catch (MalformedURLException ex) {
                 throw error(RError.Message.UNSUPPORTED_URL_SCHEME);
             } catch (IOException ex) {
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
+            } catch (IllegalCharsetNameException ex) {
+                throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -1252,11 +1258,12 @@ public abstract class ConnectionFunctions {
 
             String open = openArg;
             try {
-                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
-                return new FifoRConnection(path, open, blocking, charset).asVector();
+                return new FifoRConnection(path, open, blocking, encoding).asVector();
             } catch (IOException ex) {
                 RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
                 throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+            } catch (IllegalCharsetNameException ex) {
+                throw RError.error(this, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -1277,11 +1284,12 @@ public abstract class ConnectionFunctions {
 
             String open = openArg;
             try {
-                Charset charset = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
-                return new PipeRConnection(path, open, charset).asVector();
+                return new PipeRConnection(path, open, encoding).asVector();
             } catch (IOException ex) {
                 RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
                 throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+            } catch (IllegalCharsetNameException ex) {
+                throw RError.error(this, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
index a1d9f81682..b80c2f0d91 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
@@ -212,6 +212,8 @@ public class RCompression {
             if (rc == 0) {
                 readThread.join();
                 return Arrays.copyOf(readThread.getData(), readThread.getTotalRead());
+            } else {
+                throw new IOException("bzip2 error code: " + rc);
             }
         } catch (InterruptedException ex) {
             // fall through
@@ -239,6 +241,8 @@ public class RCompression {
                 OpenOption[] openOptions = append ? new OpenOption[]{StandardOpenOption.APPEND} : new OpenOption[0];
                 Files.write(Paths.get(path), cData, openOptions);
                 return;
+            } else {
+                throw new IOException("bzip2 error code: " + rc);
             }
         } catch (InterruptedException ex) {
             // fall through
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 3dd587a168..b0a536f50d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -837,7 +837,8 @@ public final class RError extends RuntimeException {
         CANNOT_OPEN_FIFO("cannot open fifo '%s'"),
         UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'"),
         UNABLE_TO_RESOLVE("unable to resolve '%s'"),
-        LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul");
+        LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul"),
+        UNSUPPORTED_URL_METHOD("method = \"%s\" is not supported");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 41b5362c0a..f87eee08cf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -30,6 +30,7 @@ import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -487,18 +488,6 @@ public class ConnectionSupport {
      * it subsequently will throw an error. The latter will open/close the connection (internally)
      * and this can be repeated indefinitely.
      */
-    /**
-     * @author fa
-     *
-     */
-    /**
-     * @author fa
-     *
-     */
-    /**
-     * @author fa
-     *
-     */
     public abstract static class BaseRConnection extends RConnection {
 
         /**
@@ -549,16 +538,22 @@ public class ConnectionSupport {
          * @param modeString the mode in which the connection should be opened, "" for lazy opening
          * @param defaultModeForLazy the mode to use when this connection is opened implicitly
          * @param blocking Indicates if this connection has been openend in blocking mode.
-         * @param encoding The encoding used to read from or to write to the connection.
+         * @param encoding The name of the encoding used to read from or to write to the connection
+         *            ({@code null} is allowed and sets the character set to
+         *            {@code Charset#defaultCharset()}).
          *
          */
-        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, boolean blocking, Charset encoding) throws IOException {
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, boolean blocking, String encoding) throws IOException, IllegalCharsetNameException {
             this(conClass, new OpenMode(modeString, defaultModeForLazy));
             if (conClass != ConnectionClass.Internal) {
                 this.descriptor = getContextStateImpl().setConnection(this);
             }
             this.blocking = blocking;
-            this.encoding = encoding;
+            if (encoding != null) {
+                this.encoding = Charset.forName(ConnectionSupport.convertEncodingName(encoding));
+            } else {
+                this.encoding = Charset.defaultCharset();
+            }
         }
 
         /**
@@ -580,10 +575,10 @@ public class ConnectionSupport {
          * @param conClass the specific class of the connection, e.g, {@link ConnectionClass#File}
          * @param modeString the mode in which the connection should be opened, "" for lazy opening
          * @param defaultModeForLazy the mode to use when this connection is opened implicitly
-         * @param encoding The encoding used to read from or to write to the connection.
+         * @param encoding The name of the encoding used to read from or to write to the connection.
          *
          */
-        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, Charset encoding) throws IOException {
+        protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy, String encoding) throws IOException {
             this(conClass, modeString, defaultModeForLazy, true, encoding);
         }
 
@@ -596,7 +591,7 @@ public class ConnectionSupport {
          *
          */
         protected BaseRConnection(ConnectionClass conClass, String modeString, AbstractOpenMode defaultModeForLazy) throws IOException {
-            this(conClass, modeString, defaultModeForLazy, true, Charset.defaultCharset());
+            this(conClass, modeString, defaultModeForLazy, true, null);
         }
 
         /**
@@ -723,7 +718,7 @@ public class ConnectionSupport {
         }
 
         @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        protected String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
             checkOpen();
             return theConnection.readLinesInternal(n, warn, skipNul);
         }
@@ -875,15 +870,24 @@ public class ConnectionSupport {
     abstract static class BasePathRConnection extends BaseRConnection {
         protected final String path;
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, Charset encoding) throws IOException {
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, String encoding) throws IOException {
             this(path, connectionClass, modeString, AbstractOpenMode.Read, encoding);
         }
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, Charset encoding) throws IOException {
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, boolean blocking, String encoding) throws IOException {
+            this(path, connectionClass, modeString, AbstractOpenMode.Read, blocking, encoding);
+        }
+
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, String encoding) throws IOException {
             super(connectionClass, modeString, defaultLazyOpenMode, encoding);
             this.path = Utils.tildeExpand(path);
         }
 
+        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, boolean blocking, String encoding) throws IOException {
+            super(connectionClass, modeString, defaultLazyOpenMode, blocking, encoding);
+            this.path = Utils.tildeExpand(path);
+        }
+
         @Override
         public String getSummaryDescription() {
             return path;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index ed1d60ea4d..29d1e6c9f2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -1,12 +1,26 @@
 package com.oracle.truffle.r.runtime.conn;
 
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.sun.istack.internal.NotNull;
 
+import sun.nio.cs.StreamDecoder;
+
 abstract class DelegateRConnection extends RConnection {
     protected BaseRConnection base;
 
@@ -42,4 +56,360 @@ abstract class DelegateRConnection extends RConnection {
         throw RInternalError.shouldNotReachHere("seek has not been implemented for this connection");
     }
 
+    /**
+     * {@code readLines} from an {@link InputStream}. It would be convenient to use a
+     * {@link BufferedReader} but mixing binary and text operations, which is a requirement, would
+     * then be difficult.
+     *
+     * @param warn Specifies if warnings should be output.
+     * @param skipNul Specifies if the null character should be ignored.
+     */
+    protected String[] readLinesHelper(int n, boolean warn, boolean skipNul) throws IOException {
+        ArrayList<String> lines = new ArrayList<>();
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        int pushBack = 0;
+        boolean nullRead = false;
+        while (true) {
+            int ch;
+            if (pushBack != 0) {
+                ch = pushBack;
+                pushBack = 0;
+            } else {
+                ch = getc();
+            }
+            boolean lineEnd = false;
+            if (ch < 0) {
+                if (totalRead > 0) {
+                    /*
+                     * GnuR says if non-blocking and in text mode, silently push back incomplete
+                     * lines, otherwise keep data and output warning.
+                     */
+                    final String incompleteFinalLine = new String(buffer, 0, totalRead, base.getEncoding());
+                    if (!base.isBlocking() && base.isTextMode()) {
+                        base.pushBack(RDataFactory.createStringVector(incompleteFinalLine), false);
+                    } else {
+                        lines.add(incompleteFinalLine);
+                        if (warn) {
+                            RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_FINAL_LINE, base.getSummaryDescription());
+                        }
+                    }
+                }
+                break;
+            }
+            if (ch == '\n') {
+                lineEnd = true;
+            } else if (ch == '\r') {
+                lineEnd = true;
+                ch = getc();
+                if (ch == '\n') {
+                    // swallow the trailing lf
+                } else {
+                    pushBack = ch;
+                }
+            } else if (ch == 0) {
+                nullRead = true;
+                if (warn && !skipNul) {
+                    RError.warning(RError.SHOW_CALLER, RError.Message.LINE_CONTAINS_EMBEDDED_NULLS, lines.size() + 1);
+                }
+            }
+            if (lineEnd) {
+                lines.add(new String(buffer, 0, totalRead, base.getEncoding()));
+                if (n > 0 && lines.size() == n) {
+                    break;
+                }
+                totalRead = 0;
+                nullRead = false;
+            } else {
+                if (!nullRead) {
+                    buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
+                    buffer[totalRead++] = (byte) (ch & 0xFF);
+                }
+                if (skipNul) {
+                    nullRead = false;
+                }
+            }
+        }
+        String[] result = new String[lines.size()];
+        lines.toArray(result);
+        return result;
+    }
+
+    public static void writeStringHelper(OutputStream out, String s, boolean nl, Charset encoding) throws IOException {
+        out.write(s.getBytes(encoding));
+        if (nl) {
+            out.write(System.lineSeparator().getBytes(encoding));
+        }
+    }
+
+    public static void writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
+        final byte[] bytes = s.getBytes(encoding);
+        final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes(encoding) : null;
+
+        ByteBuffer buf = ByteBuffer.allocate(bytes.length + (nl ? lineSepBytes.length : 0));
+        buf.put(bytes);
+        if (nl) {
+            buf.put(lineSepBytes);
+        }
+
+        buf.rewind();
+        out.write(buf);
+    }
+
+    /**
+     * Writes characters in binary mode (without any re-encoding) to the provided channel.
+     *
+     * @param out The output stream (must not be {@code null}.
+     * @param s The character string to write (must not be {@code null}).
+     * @param pad The number of null characters to append to the characters.
+     * @param eos The end-of-string terminator (may be {@code null}).
+     * @throws IOException
+     */
+    public static void writeCharHelper(OutputStream out, String s, int pad, String eos) throws IOException {
+
+        out.write(s.getBytes());
+        if (pad > 0) {
+            for (int i = 0; i < pad; i++) {
+                out.write(0);
+            }
+        }
+        if (eos != null) {
+            if (eos.length() > 0) {
+                out.write(eos.getBytes());
+            }
+            // function writeChar is defined to append the null character if eos != null
+            out.write(0);
+        }
+    }
+
+    /**
+     * Writes characters in binary mode (without any re-encoding) to the provided channel.
+     *
+     * @param channel The writable byte channel to write to (must not be {@code null}).
+     * @param s The character string to write (must not be {@code null}).
+     * @param pad The number of null characters to append to the characters.
+     * @param eos The end-of-string terminator (may be {@code null}).
+     * @throws IOException
+     */
+    public static void writeCharHelper(@NotNull WritableByteChannel channel, @NotNull String s, int pad, String eos) throws IOException {
+
+        final byte[] bytes = s.getBytes();
+        final byte[] eosBytes = eos != null ? eos.getBytes() : null;
+
+        final int bufLen = bytes.length + (pad > 0 ? pad : 0) + (eos != null ? eosBytes.length + 1 : 0);
+        assert bufLen >= s.length();
+        ByteBuffer buf = ByteBuffer.allocate(bufLen);
+        buf.put(bytes);
+        if (pad > 0) {
+            for (int i = 0; i < pad; i++) {
+                buf.put((byte) 0);
+            }
+        }
+        if (eos != null) {
+            if (eos.length() > 0) {
+                buf.put(eos.getBytes());
+            }
+            // function writeChar is defined to append the null character if eos != null
+            buf.put((byte) 0);
+        }
+        buf.rewind();
+        channel.write(buf);
+    }
+
+    @Deprecated
+    public static void writeBinHelper(ByteBuffer buffer, OutputStream outputStream) throws IOException {
+        int n = buffer.remaining();
+        byte[] b = new byte[n];
+        buffer.get(b);
+        outputStream.write(b);
+    }
+
+    /**
+     * Reads null-terminated character strings from a {@link ReadableByteChannel}.
+     */
+    public static byte[] readBinCharsHelper(ReadableByteChannel channel) throws IOException {
+        ByteBuffer buf = ByteBuffer.allocate(1);
+        int numRead = channel.read(buf);
+        if (numRead <= 0) {
+            return null;
+        }
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        while (true) {
+            buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
+            buffer[totalRead++] = (byte) (buf.get() & 0xFF);
+            if (numRead == 0) {
+                break;
+            }
+            buf.clear();
+            numRead = channel.read(buf);
+        }
+        return buffer;
+    }
+
+    /**
+     * Reads null-terminated character strings from a {@link InputStream}.
+     */
+    public static byte[] readBinCharsHelper(InputStream in) throws IOException {
+        int ch = in.read();
+        if (ch < 0) {
+            return null;
+        }
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        while (true) {
+            buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
+            buffer[totalRead++] = (byte) (ch & 0xFF);
+            if (ch == 0) {
+                break;
+            }
+            ch = in.read();
+        }
+        return buffer;
+    }
+
+    public static int readBinHelper(ByteBuffer buffer, InputStream inputStream) throws IOException {
+        int bytesToRead = buffer.remaining();
+        byte[] b = new byte[bytesToRead];
+        int totalRead = 0;
+        int thisRead = 0;
+        while ((totalRead < bytesToRead) && ((thisRead = inputStream.read(b, totalRead, bytesToRead - totalRead)) > 0)) {
+            totalRead += thisRead;
+        }
+        buffer.put(b, 0, totalRead);
+        return totalRead;
+    }
+
+    /**
+     * Reads a specified amount of characters.
+     *
+     * @param nchars Number of characters to read.
+     * @param in The encoded byte stream.
+     * @return The read string.
+     * @throws IOException
+     */
+    public static String readCharHelper(int nchars, Reader in) throws IOException {
+        char[] chars = new char[nchars];
+        in.read(chars);
+        int j = 0;
+        for (; j < chars.length; j++) {
+            // strings end at 0
+            if (chars[j] == 0) {
+                break;
+            }
+        }
+
+        return new String(chars, 0, j);
+    }
+
+    /**
+     * Reads a specified amount of bytes.
+     *
+     * @param nchars The number of bytes to read.
+     * @param in The input stream.
+     * @return The read string.
+     * @throws IOException
+     */
+    public static String readCharHelper(int nchars, InputStream in) throws IOException {
+        byte[] buf = new byte[nchars];
+        in.read(buf);
+        int j = 0;
+        for (; j < buf.length; j++) {
+            // strings end at 0
+            if (buf[j] == 0) {
+                break;
+            }
+        }
+
+        return new String(buf, 0, j);
+    }
+
+    public static String readCharHelper(int nchars, ReadableByteChannel channel, boolean useBytes) throws IOException {
+        if (useBytes) {
+            ByteBuffer buf = ByteBuffer.allocate(nchars);
+            channel.read(buf);
+            int j = 0;
+            for (; j < buf.position(); j++) {
+                // strings end at 0
+                if (buf.get(j) == 0) {
+                    break;
+                }
+            }
+
+            return new String(buf.array(), 0, j);
+        } else {
+            // we need a decoder
+            StreamDecoder decoder = StreamDecoder.forDecoder(channel, Charset.defaultCharset().newDecoder(), nchars);
+            char[] chars = new char[nchars];
+            decoder.read(chars);
+            int j = 0;
+            for (; j < chars.length; j++) {
+                // strings end at 0
+                if (chars[j] == 0) {
+                    break;
+                }
+            }
+
+            return new String(chars, 0, j);
+        }
+    }
+
+    /**
+     * Implements standard seeking behavior.
+     */
+    public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
+        long position = channel.position();
+        switch (seekMode) {
+            case ENQUIRE:
+                break;
+            case CURRENT:
+                if (offset != 0) {
+                    channel.position(position + offset);
+                }
+                break;
+            case START:
+                channel.position(offset);
+                break;
+            case END:
+                throw RInternalError.unimplemented();
+
+        }
+        return position;
+    }
+
+    /**
+     * Enlarges the buffer if necessary.
+     */
+    static byte[] checkBuffer(byte[] buffer, int n) {
+        if (n > buffer.length - 1) {
+            byte[] newBuffer = new byte[buffer.length + buffer.length / 2];
+            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+            return newBuffer;
+        } else {
+            return buffer;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    public static String[] readLinesNonBlockHelper(BaseRConnection conn, ReadableByteChannel channel, int n, boolean warn, boolean skipNul, String summaryDescription, Charset encoding) {
+
+        throw RInternalError.unimplemented();
+    }
+
+    public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
+        for (int i = 0; i < lines.getLength(); i++) {
+            final String line = lines.getDataAt(i);
+            DelegateRConnection.writeStringHelper(out, line, false, encoding);
+            DelegateRConnection.writeStringHelper(out, sep, false, encoding);
+        }
+    }
+
+    public static void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
+        for (int i = 0; i < lines.getLength(); i++) {
+            final String line = lines.getDataAt(i);
+            DelegateRConnection.writeStringHelper(out, line, false, encoding);
+            DelegateRConnection.writeStringHelper(out, sep, false, encoding);
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
index 682c8b4bb3..9769b1d1e4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
@@ -43,15 +43,15 @@ public abstract class DelegateReadNonBlockRConnection extends DelegateRConnectio
 
     @Override
     public int getc() throws IOException {
-        // TODO a character may consist of multiple bytes
         tmp.clear();
-        getChannel().read(tmp);
-        return tmp.get();
+        int nread = getChannel().read(tmp);
+        tmp.rewind();
+        return nread > 0 ? tmp.get() : -1;
     }
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
-        return ReadWriteHelper.readCharHelper(nchars, getChannel(), useBytes);
+        return DelegateRConnection.readCharHelper(nchars, getChannel(), useBytes);
     }
 
     @Override
@@ -61,13 +61,13 @@ public abstract class DelegateReadNonBlockRConnection extends DelegateRConnectio
 
     @Override
     public byte[] readBinChars() throws IOException {
-        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+        return DelegateRConnection.readBinCharsHelper(getChannel());
     }
 
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesNonBlockHelper(base, getChannel(), n, warn, skipNul, base.getSummaryDescription(), base.getEncoding());
+        return readLinesHelper(n, warn, skipNul);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index 6484175a5a..285666ebfe 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -49,10 +49,10 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
         if (useBytes) {
-            return ReadWriteHelper.readCharHelper(nchars, getInputStream());
+            return DelegateRConnection.readCharHelper(nchars, getInputStream());
         } else {
             final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
-            return ReadWriteHelper.readCharHelper(nchars, isr);
+            return DelegateRConnection.readCharHelper(nchars, isr);
         }
     }
 
@@ -63,13 +63,13 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
 
     @Override
     public byte[] readBinChars() throws IOException {
-        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+        return DelegateRConnection.readBinCharsHelper(getInputStream());
     }
 
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(base, getInputStream(), n, warn, skipNul);
+        return readLinesHelper(n, warn, skipNul);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
index efd4f493cf..74687a94f3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
@@ -15,6 +15,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection {
 
+    private final ByteBuffer tmp = ByteBuffer.allocate(1);
+
     protected DelegateReadWriteNonBlockRConnection(BaseRConnection base) {
         super(base);
     }
@@ -31,16 +33,19 @@ abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection
 
     @Override
     public int getc() throws IOException {
-        return getInputStream().read();
+        tmp.clear();
+        int nread = getChannel().read(tmp);
+        tmp.rewind();
+        return nread > 0 ? tmp.get() : -1;
     }
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
         if (useBytes) {
-            return ReadWriteHelper.readCharHelper(nchars, getInputStream());
+            return DelegateRConnection.readCharHelper(nchars, getInputStream());
         } else {
             final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
-            return ReadWriteHelper.readCharHelper(nchars, isr);
+            return DelegateRConnection.readCharHelper(nchars, isr);
         }
     }
 
@@ -51,13 +56,13 @@ abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection
 
     @Override
     public byte[] readBinChars() throws IOException {
-        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+        return DelegateRConnection.readBinCharsHelper(getInputStream());
     }
 
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(base, getInputStream(), n, warn, skipNul);
+        return readLinesHelper(n, warn, skipNul);
     }
 
     @Override
@@ -96,17 +101,17 @@ abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+        DelegateRConnection.writeCharHelper(getChannel(), s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+        DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 09ac19ae6f..48935e5953 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -37,10 +37,10 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
         if (useBytes) {
-            return ReadWriteHelper.readCharHelper(nchars, getInputStream());
+            return DelegateRConnection.readCharHelper(nchars, getInputStream());
         } else {
             final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
-            return ReadWriteHelper.readCharHelper(nchars, isr);
+            return DelegateRConnection.readCharHelper(nchars, isr);
         }
     }
 
@@ -51,13 +51,13 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public byte[] readBinChars() throws IOException {
-        return ReadWriteHelper.readBinCharsHelper(getInputStream());
+        return DelegateRConnection.readBinCharsHelper(getInputStream());
     }
 
     @TruffleBoundary
     @Override
     public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return ReadWriteHelper.readLinesHelper(base, getInputStream(), n, warn, skipNul);
+        return readLinesHelper(n, warn, skipNul);
     }
 
     @Override
@@ -90,17 +90,17 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeCharHelper(getOutputStream(), s, pad, eos);
+        DelegateRConnection.writeCharHelper(getOutputStream(), s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
+        DelegateRConnection.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
+        DelegateRConnection.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
index 41119a8f36..d6ce50a9db 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
@@ -90,17 +90,17 @@ abstract class DelegateWriteNonBlockRConnection extends DelegateRConnection {
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeCharHelper(getChannel(), s, pad, eos);
+        DelegateRConnection.writeCharHelper(getChannel(), s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+        DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 97ec636bdc..ec971e5392 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -83,17 +83,17 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeCharHelper(getOutputStream(), s, pad, eos);
+        DelegateRConnection.writeCharHelper(getOutputStream(), s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        ReadWriteHelper.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
+        DelegateRConnection.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        ReadWriteHelper.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
+        DelegateRConnection.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
     }
 
 }
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index 72327193e2..3adb12e43b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -22,15 +22,14 @@
  */
 package com.oracle.truffle.r.runtime.conn;
 
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.RandomAccessFile;
 import java.lang.ProcessBuilder.Redirect;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
-import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.OpenOption;
 import java.nio.file.Paths;
@@ -49,7 +48,7 @@ public class FifoConnections {
 
         private final String path;
 
-        public FifoRConnection(String path, String open, boolean blocking, Charset encoding) throws IOException {
+        public FifoRConnection(String path, String open, boolean blocking, String encoding) throws IOException {
             super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, blocking, encoding);
             this.path = path;
             openNonLazyConnection();
@@ -121,29 +120,23 @@ public class FifoConnections {
         }
     }
 
-    static class FifoReadRConnection extends DelegateReadRConnection {
-        private final RandomAccessFile raf;
+    static class FifoReadRConnection extends DelegateReadNonBlockRConnection {
+        private final FileChannel channel;
 
-        protected FifoReadRConnection(BaseRConnection base, String path) throws FileNotFoundException {
+        protected FifoReadRConnection(BaseRConnection base, String path) throws IOException {
             super(base);
-            raf = new RandomAccessFile(path, "r");
+            channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ);
         }
 
         @Override
-        public void close() throws IOException {
-            raf.close();
+        public ReadableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
         public boolean isSeekable() {
             return false;
         }
-
-        @Override
-        public InputStream getInputStream() {
-            // TODO Auto-generated method stub
-            return null;
-        }
     }
 
     private static class FifoWriteConnection extends DelegateWriteNonBlockRConnection {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index ffdb0d239d..c99cf50099 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -32,7 +32,15 @@ import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
-import java.nio.charset.Charset;
+import java.nio.channels.Channels;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.file.OpenOption;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
@@ -57,12 +65,11 @@ public class FileConnections {
 
     /**
      * Base class for all modes of file connections.
-     *
      */
     public static class FileRConnection extends BasePathRConnection {
 
-        public FileRConnection(String path, String modeString, Charset encoding) throws IOException {
-            super(checkTemp(path), ConnectionClass.File, modeString, encoding);
+        public FileRConnection(String path, String modeString, boolean blocking, String encoding) throws IOException {
+            super(checkTemp(path), ConnectionClass.File, modeString, blocking, encoding);
             openNonLazyConnection();
         }
 
@@ -82,6 +89,37 @@ public class FileConnections {
         }
     }
 
+    /**
+     * Base class for all modes of gzfile/bzfile/xzfile connections. N.B. In GNU R these can read
+     * gzip, bzip, lzma and uncompressed files, and this has to be implemented by reading the first
+     * few bytes of the file and detecting the type of the file.
+     */
+    public static class CompressedRConnection extends BasePathRConnection {
+        private final RCompression.Type cType;
+        @SuppressWarnings("unused") private final int compression; // TODO
+
+        public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException {
+            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary, encoding);
+            this.cType = cType;
+            this.compression = compression;
+            openNonLazyConnection();
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            setDelegate(FileConnections.createDelegateConnection(this, cType));
+
+        }
+
+        // @Override
+        /**
+         * GnuR behavior for lazy connections is odd, e.g. gzfile returns "text", even though the
+         * default mode is "rb".
+         */
+        // public boolean isTextMode() {
+        // }
+    }
+
     private static DelegateRConnection createUncompressedDelegateConnection(BasePathRConnection base)
                     throws IOException {
 
@@ -118,7 +156,7 @@ public class FileConnections {
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
             case ReadBinary:
-                return new CompressedInputRConnection(base, new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE), true);
+                return new CompressedInputRConnection(base, new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE));
             case Append:
             case AppendBinary:
                 append = true;
@@ -137,7 +175,7 @@ public class FileConnections {
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
             case ReadBinary:
-                return new CompressedInputRConnection(base, new XZInputStream(new FileInputStream(base.path)), false);
+                return new CompressedInputRConnection(base, new XZInputStream(new FileInputStream(base.path)));
             case Append:
             case AppendBinary:
                 append = true;
@@ -157,7 +195,7 @@ public class FileConnections {
             case Read:
             case ReadBinary:
                 byte[] bzipUdata = RCompression.bzipUncompressFromFile(base.path);
-                return new ByteStreamCompressedInputRConnection(base, new ByteArrayInputStream(bzipUdata), false);
+                return new ByteStreamCompressedInputRConnection(base, new ByteArrayInputStream(bzipUdata));
             case Append:
             case AppendBinary:
                 append = true;
@@ -178,7 +216,7 @@ public class FileConnections {
          * type.
          */
         final RCompression.Type cTypeActual;
-        if (openMode == AbstractOpenMode.Read || openMode == AbstractOpenMode.ReadBinary) {
+        if (openMode == AbstractOpenMode.Read) {
             cTypeActual = RCompression.getCompressionType(base.path);
             if (cTypeActual != cType) {
                 base.updateConnectionClass(mapConnectionClass(cTypeActual));
@@ -215,13 +253,13 @@ public class FileConnections {
         }
     }
 
-    static class FileReadBinaryRConnection extends DelegateReadRConnection {
+    static class FileReadBinaryRConnection extends DelegateReadNonBlockRConnection {
 
-        private final FileInputStream inputStream;
+        private final FileChannel channel;
 
         FileReadBinaryRConnection(BasePathRConnection base) throws IOException {
             super(base);
-            inputStream = new FileInputStream(base.path);
+            channel = FileChannel.open(Paths.get(base.path), StandardOpenOption.READ);
         }
 
         @Override
@@ -230,13 +268,8 @@ public class FileConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            return ReadWriteHelper.seek(inputStream.getChannel(), offset, seekMode, seekRWMode);
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            return inputStream;
+        public ReadableByteChannel getChannel() {
+            return channel;
         }
 
     }
@@ -270,13 +303,22 @@ public class FileConnections {
         }
     }
 
-    private static class FileWriteBinaryConnection extends DelegateWriteRConnection {
+    private static class FileWriteBinaryConnection extends DelegateWriteNonBlockRConnection {
 
-        private final FileOutputStream out;
+        private final FileChannel channel;
 
         FileWriteBinaryConnection(BasePathRConnection base, boolean append) throws IOException {
             super(base);
-            out = new FileOutputStream(base.path, append);
+            List<OpenOption> opts = new ArrayList<>();
+            opts.add(StandardOpenOption.WRITE);
+            opts.add(StandardOpenOption.CREATE);
+            if (append) {
+                opts.add(StandardOpenOption.APPEND);
+            } else {
+                opts.add(StandardOpenOption.TRUNCATE_EXISTING);
+            }
+            channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
+
         }
 
         @Override
@@ -285,13 +327,8 @@ public class FileConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            return ReadWriteHelper.seek(out.getChannel(), offset, seekMode, seekRWMode);
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return out;
+        public WritableByteChannel getChannel() {
+            return channel;
         }
 
     }
@@ -406,86 +443,40 @@ public class FileConnections {
 
     }
 
-    /**
-     * Base class for all modes of gzfile/bzfile/xzfile connections. N.B. In GNU R these can read
-     * gzip, bzip, lzma and uncompressed files, and this has to be implemented by reading the first
-     * few bytes of the file and detecting the type of the file.
-     */
-    public static class CompressedRConnection extends BasePathRConnection {
-        private final RCompression.Type cType;
-        @SuppressWarnings("unused") private final int compression; // TODO
-
-        public CompressedRConnection(String path, String modeString, Type cType, Charset encoding, int compression) throws IOException {
-            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary, encoding);
-            this.cType = cType;
-            this.compression = compression;
-            openNonLazyConnection();
-        }
-
-        @Override
-        protected void createDelegateConnection() throws IOException {
-            setDelegate(FileConnections.createDelegateConnection(this, cType));
-
-        }
-
-        // @Override
-        /**
-         * GnuR behavior for lazy connections is odd, e.g. gzfile returns "text", even though the
-         * default mode is "rb".
-         */
-        // public boolean isTextMode() {
-        // }
-    }
-
-    private static class CompressedInputRConnection extends DelegateReadRConnection {
-        private final InputStream inputStream;
-        private final boolean seekable;
+    private static class CompressedInputRConnection extends DelegateReadNonBlockRConnection {
+        private final ReadableByteChannel channel;
 
-        protected CompressedInputRConnection(BasePathRConnection base, InputStream is, boolean seekable) {
+        protected CompressedInputRConnection(BasePathRConnection base, InputStream is) {
             super(base);
-            this.inputStream = is;
-            this.seekable = seekable;
+            channel = Channels.newChannel(is);
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            if (seekable) {
-                // TODO
-            }
-            return super.seekInternal(offset, seekMode, seekRWMode);
+        public ReadableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
         public boolean isSeekable() {
-            return seekable;
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            return inputStream;
+            return false;
         }
     }
 
     private static class ByteStreamCompressedInputRConnection extends CompressedInputRConnection {
-        ByteStreamCompressedInputRConnection(BasePathRConnection base, ByteArrayInputStream is, boolean seekable) {
-            super(base, is, seekable);
+        ByteStreamCompressedInputRConnection(BasePathRConnection base, ByteArrayInputStream is) {
+            super(base, is);
         }
     }
 
-    private static class CompressedOutputRConnection extends DelegateWriteRConnection {
-        protected OutputStream outputStream;
+    private static class CompressedOutputRConnection extends DelegateWriteNonBlockRConnection {
+        protected WritableByteChannel channel;
         private final boolean seekable;
         private long seekPosition = 0L;
 
         protected CompressedOutputRConnection(BasePathRConnection base, OutputStream os, boolean seekable) {
             super(base);
-            this.outputStream = os;
             this.seekable = seekable;
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return outputStream;
+            this.channel = Channels.newChannel(os);
         }
 
         @Override
@@ -494,17 +485,6 @@ public class FileConnections {
             close();
         }
 
-        @Override
-        public void close() throws IOException {
-            flush();
-            outputStream.close();
-        }
-
-        @Override
-        public void flush() throws IOException {
-            outputStream.flush();
-        }
-
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             if (seekable) {
@@ -521,6 +501,11 @@ public class FileConnections {
         public boolean isSeekable() {
             return seekable;
         }
+
+        @Override
+        public WritableByteChannel getChannel() {
+            return channel;
+        }
     }
 
     private static class BZip2OutputRConnection extends CompressedOutputRConnection {
@@ -536,7 +521,6 @@ public class FileConnections {
         @Override
         public void close() throws IOException {
             flush();
-            outputStream.close();
             // Now actually do the compression using sub-process
             byte[] data = bos.toByteArray();
             RCompression.bzipCompressToFile(data, ((BasePathRConnection) base).path, append);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
index 4ca8f92405..b16bafb39c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -26,7 +26,11 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.ProcessBuilder.Redirect;
-import java.nio.charset.Charset;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
@@ -51,7 +55,7 @@ public class PipeConnections {
 
         private final String command;
 
-        public PipeRConnection(String command, String open, Charset encoding) throws IOException {
+        public PipeRConnection(String command, String open, String encoding) throws IOException {
             super(ConnectionClass.FIFO, open, AbstractOpenMode.Read, encoding);
             this.command = command;
             openNonLazyConnection();
@@ -88,23 +92,18 @@ public class PipeConnections {
         }
     }
 
-    static class PipeReadRConnection extends DelegateReadRConnection {
-        private final InputStream in;
+    static class PipeReadRConnection extends DelegateReadNonBlockRConnection {
+        private final ReadableByteChannel channel;
 
         protected PipeReadRConnection(BaseRConnection base, String command) throws IOException {
             super(base);
             Process p = PipeConnections.executeAndJoin(command);
-            in = p.getInputStream();
+            channel = Channels.newChannel(p.getInputStream());
         }
 
         @Override
-        public InputStream getInputStream() {
-            return in;
-        }
-
-        @Override
-        public void close() throws IOException {
-            in.close();
+        public ReadableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
@@ -113,23 +112,18 @@ public class PipeConnections {
         }
     }
 
-    private static class PipeWriteConnection extends DelegateWriteRConnection {
-        private final OutputStream out;
+    private static class PipeWriteConnection extends DelegateWriteNonBlockRConnection {
+        private final WritableByteChannel channel;
 
         PipeWriteConnection(BaseRConnection base, String command) throws IOException {
             super(base);
             Process p = PipeConnections.executeAndJoin(command);
-            out = p.getOutputStream();
-        }
-
-        @Override
-        public OutputStream getOutputStream() throws IOException {
-            return out;
+            channel = Channels.newChannel(p.getOutputStream());
         }
 
         @Override
-        public void close() throws IOException {
-            out.close();
+        public WritableByteChannel getChannel() {
+            return channel;
         }
 
         @Override
@@ -138,26 +132,19 @@ public class PipeConnections {
         }
     }
 
-    private static class PipeReadWriteConnection extends DelegateReadWriteRConnection {
+    private static class PipeReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
 
-        private final InputStream in;
-        private final OutputStream out;
+        private final RWChannel channel;
 
         protected PipeReadWriteConnection(BaseRConnection base, String command) throws IOException {
             super(base);
             Process p = PipeConnections.executeAndJoin(command);
-            in = p.getInputStream();
-            out = p.getOutputStream();
+            channel = new RWChannel(p.getInputStream(), p.getOutputStream());
         }
 
         @Override
-        public InputStream getInputStream() {
-            return in;
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            return out;
+        public ByteChannel getChannel() {
+            return channel;
         }
 
         @Override
@@ -165,6 +152,38 @@ public class PipeConnections {
             return false;
         }
 
+        private static final class RWChannel implements ByteChannel {
+            private final ReadableByteChannel rchannel;
+            private final WritableByteChannel wchannel;
+
+            public RWChannel(InputStream in, OutputStream out) {
+                rchannel = Channels.newChannel(in);
+                wchannel = Channels.newChannel(out);
+            }
+
+            @Override
+            public int read(ByteBuffer dst) throws IOException {
+                return rchannel.read(dst);
+            }
+
+            @Override
+            public boolean isOpen() {
+                return rchannel.isOpen() && wchannel.isOpen();
+            }
+
+            @Override
+            public void close() throws IOException {
+                rchannel.close();
+                wchannel.close();
+            }
+
+            @Override
+            public int write(ByteBuffer src) throws IOException {
+                return wchannel.write(src);
+            }
+
+        }
+
     }
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 7bc6f28b9f..339ad9d9d8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -72,7 +72,7 @@ public abstract class RConnection implements AutoCloseable {
      */
     private boolean incomplete = false;
 
-    public abstract String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException;
+    protected abstract String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException;
 
     private String readOneLineWithPushBack(String[] res, int ind, @SuppressWarnings("unused") boolean warn, @SuppressWarnings("unused") boolean skipNul) {
         String s = pushBack.pollLast();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
deleted file mode 100644
index e2eb4edeac..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ReadWriteHelper.java
+++ /dev/null
@@ -1,379 +0,0 @@
-package com.oracle.truffle.r.runtime.conn;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.nio.ByteBuffer;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.SeekableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.conn.RConnection.SeekMode;
-import com.oracle.truffle.r.runtime.conn.RConnection.SeekRWMode;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.sun.istack.internal.NotNull;
-
-import sun.nio.cs.StreamDecoder;
-
-public class ReadWriteHelper {
-
-    /**
-     * {@code readLines} from an {@link InputStream}. It would be convenient to use a
-     * {@link BufferedReader} but mixing binary and text operations, which is a requirement, would
-     * then be difficult.
-     *
-     * @param warn Specifies if warnings should be output.
-     * @param skipNul Specifies if the null character should be ignored.
-     */
-    public static String[] readLinesHelper(BaseRConnection conn, InputStream in, int n, boolean warn, boolean skipNul) throws IOException {
-        ArrayList<String> lines = new ArrayList<>();
-        int totalRead = 0;
-        byte[] buffer = new byte[64];
-        int pushBack = 0;
-        boolean nullRead = false;
-        while (true) {
-            int ch;
-            if (pushBack != 0) {
-                ch = pushBack;
-                pushBack = 0;
-            } else {
-                ch = in.read();
-            }
-            boolean lineEnd = false;
-            if (ch < 0) {
-                if (totalRead > 0) {
-                    /*
-                     * TODO GnuR says keep data and output a warning if blocking, otherwise silently
-                     * push back. FastR doesn't support non-blocking yet, so we keep the data. Some
-                     * refactoring is needed to be able to reliably access the "name" for the
-                     * warning.
-                     */
-                    lines.add(new String(buffer, 0, totalRead, conn.getEncoding()));
-                    if (warn) {
-                        RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_FINAL_LINE, conn.getSummaryDescription());
-                    }
-                }
-                break;
-            }
-            if (ch == '\n') {
-                lineEnd = true;
-            } else if (ch == '\r') {
-                lineEnd = true;
-                ch = in.read();
-                if (ch == '\n') {
-                    // swallow the trailing lf
-                } else {
-                    pushBack = ch;
-                }
-            } else if (ch == 0) {
-                nullRead = true;
-                if (warn && !skipNul) {
-                    RError.warning(RError.SHOW_CALLER, RError.Message.LINE_CONTAINS_EMBEDDED_NULLS, lines.size() + 1);
-                }
-            }
-            if (lineEnd) {
-                lines.add(new String(buffer, 0, totalRead, conn.getEncoding()));
-                if (n > 0 && lines.size() == n) {
-                    break;
-                }
-                totalRead = 0;
-                nullRead = false;
-            } else {
-                if (!nullRead) {
-                    buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
-                    buffer[totalRead++] = (byte) (ch & 0xFF);
-                }
-                if (skipNul) {
-                    nullRead = false;
-                }
-            }
-        }
-        String[] result = new String[lines.size()];
-        lines.toArray(result);
-        return result;
-    }
-
-    public static void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
-        for (int i = 0; i < lines.getLength(); i++) {
-            final String line = lines.getDataAt(i);
-            writeStringHelper(out, line, false, encoding);
-            writeStringHelper(out, sep, false, encoding);
-        }
-    }
-
-    public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
-        for (int i = 0; i < lines.getLength(); i++) {
-            final String line = lines.getDataAt(i);
-            writeStringHelper(out, line, false, encoding);
-            writeStringHelper(out, sep, false, encoding);
-        }
-    }
-
-    public static void writeStringHelper(OutputStream out, String s, boolean nl, Charset encoding) throws IOException {
-        out.write(s.getBytes(encoding));
-        if (nl) {
-            out.write(System.lineSeparator().getBytes(encoding));
-        }
-    }
-
-    public static void writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
-        final byte[] bytes = s.getBytes(encoding);
-        final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes(encoding) : null;
-
-        ByteBuffer buf = ByteBuffer.allocate(bytes.length + (nl ? lineSepBytes.length : 0));
-        buf.put(bytes);
-        if (nl) {
-            buf.put(lineSepBytes);
-        }
-
-        buf.rewind();
-        out.write(buf);
-    }
-
-    /**
-     * Writes characters in binary mode (without any re-encoding) to the provided channel.
-     *
-     * @param out The output stream (must not be {@code null}.
-     * @param s The character string to write (must not be {@code null}).
-     * @param pad The number of null characters to append to the characters.
-     * @param eos The end-of-string terminator (may be {@code null}).
-     * @throws IOException
-     */
-    public static void writeCharHelper(OutputStream out, String s, int pad, String eos) throws IOException {
-
-        out.write(s.getBytes());
-        if (pad > 0) {
-            for (int i = 0; i < pad; i++) {
-                out.write(0);
-            }
-        }
-        if (eos != null) {
-            if (eos.length() > 0) {
-                out.write(eos.getBytes());
-            }
-            // function writeChar is defined to append the null character if eos != null
-            out.write(0);
-        }
-    }
-
-    /**
-     * Writes characters in binary mode (without any re-encoding) to the provided channel.
-     *
-     * @param channel The writable byte channel to write to (must not be {@code null}).
-     * @param s The character string to write (must not be {@code null}).
-     * @param pad The number of null characters to append to the characters.
-     * @param eos The end-of-string terminator (may be {@code null}).
-     * @throws IOException
-     */
-    public static void writeCharHelper(@NotNull WritableByteChannel channel, @NotNull String s, int pad, String eos) throws IOException {
-
-        final byte[] bytes = s.getBytes();
-        final byte[] eosBytes = eos != null ? eos.getBytes() : null;
-
-        final int bufLen = bytes.length + (pad > 0 ? pad : 0) + (eos != null ? eosBytes.length + 1 : 0);
-        assert bufLen >= s.length();
-        ByteBuffer buf = ByteBuffer.allocate(bufLen);
-        buf.put(bytes);
-        if (pad > 0) {
-            for (int i = 0; i < pad; i++) {
-                buf.put((byte) 0);
-            }
-        }
-        if (eos != null) {
-            if (eos.length() > 0) {
-                buf.put(eos.getBytes());
-            }
-            // function writeChar is defined to append the null character if eos != null
-            buf.put((byte) 0);
-        }
-        buf.rewind();
-        channel.write(buf);
-    }
-
-    @Deprecated
-    public static void writeBinHelper(ByteBuffer buffer, OutputStream outputStream) throws IOException {
-        int n = buffer.remaining();
-        byte[] b = new byte[n];
-        buffer.get(b);
-        outputStream.write(b);
-    }
-
-    /**
-     * Reads null-terminated character strings from a {@link ReadableByteChannel}.
-     */
-    public static byte[] readBinCharsHelper(ReadableByteChannel channel) throws IOException {
-        ByteBuffer buf = ByteBuffer.allocate(1);
-        int numRead = channel.read(buf);
-        if (numRead <= 0) {
-            return null;
-        }
-        int totalRead = 0;
-        byte[] buffer = new byte[64];
-        while (true) {
-            buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
-            buffer[totalRead++] = (byte) (buf.get() & 0xFF);
-            if (numRead == 0) {
-                break;
-            }
-            buf.clear();
-            numRead = channel.read(buf);
-        }
-        return buffer;
-    }
-
-    /**
-     * Reads null-terminated character strings from a {@link InputStream}.
-     */
-    public static byte[] readBinCharsHelper(InputStream in) throws IOException {
-        int ch = in.read();
-        if (ch < 0) {
-            return null;
-        }
-        int totalRead = 0;
-        byte[] buffer = new byte[64];
-        while (true) {
-            buffer = ReadWriteHelper.checkBuffer(buffer, totalRead);
-            buffer[totalRead++] = (byte) (ch & 0xFF);
-            if (ch == 0) {
-                break;
-            }
-            ch = in.read();
-        }
-        return buffer;
-    }
-
-    public static int readBinHelper(ByteBuffer buffer, InputStream inputStream) throws IOException {
-        int bytesToRead = buffer.remaining();
-        byte[] b = new byte[bytesToRead];
-        int totalRead = 0;
-        int thisRead = 0;
-        while ((totalRead < bytesToRead) && ((thisRead = inputStream.read(b, totalRead, bytesToRead - totalRead)) > 0)) {
-            totalRead += thisRead;
-        }
-        buffer.put(b, 0, totalRead);
-        return totalRead;
-    }
-
-    /**
-     * Reads a specified amount of characters.
-     *
-     * @param nchars Number of characters to read.
-     * @param in The encoded byte stream.
-     * @return The read string.
-     * @throws IOException
-     */
-    public static String readCharHelper(int nchars, Reader in) throws IOException {
-        char[] chars = new char[nchars];
-        in.read(chars);
-        int j = 0;
-        for (; j < chars.length; j++) {
-            // strings end at 0
-            if (chars[j] == 0) {
-                break;
-            }
-        }
-
-        return new String(chars, 0, j);
-    }
-
-    /**
-     * Reads a specified amount of bytes.
-     *
-     * @param nchars The number of bytes to read.
-     * @param in The input stream.
-     * @return The read string.
-     * @throws IOException
-     */
-    public static String readCharHelper(int nchars, InputStream in) throws IOException {
-        byte[] buf = new byte[nchars];
-        in.read(buf);
-        int j = 0;
-        for (; j < buf.length; j++) {
-            // strings end at 0
-            if (buf[j] == 0) {
-                break;
-            }
-        }
-
-        return new String(buf, 0, j);
-    }
-
-    public static String readCharHelper(int nchars, ReadableByteChannel channel, boolean useBytes) throws IOException {
-        if (useBytes) {
-            ByteBuffer buf = ByteBuffer.allocate(nchars);
-            channel.read(buf);
-            int j = 0;
-            for (; j < buf.position(); j++) {
-                // strings end at 0
-                if (buf.get(j) == 0) {
-                    break;
-                }
-            }
-
-            return new String(buf.array(), 0, j);
-        } else {
-            // we need a decoder
-            StreamDecoder decoder = StreamDecoder.forDecoder(channel, Charset.defaultCharset().newDecoder(), nchars);
-            char[] chars = new char[nchars];
-            decoder.read(chars);
-            int j = 0;
-            for (; j < chars.length; j++) {
-                // strings end at 0
-                if (chars[j] == 0) {
-                    break;
-                }
-            }
-
-            return new String(chars, 0, j);
-        }
-    }
-
-    /**
-     * TODO probably, this method belongs to {@link ConnectionSupport}
-     */
-    public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
-        long position = channel.position();
-        switch (seekMode) {
-            case ENQUIRE:
-                break;
-            case CURRENT:
-                if (offset != 0) {
-                    channel.position(position + offset);
-                }
-                break;
-            case START:
-                channel.position(offset);
-                break;
-            case END:
-                throw RInternalError.unimplemented();
-
-        }
-        return position;
-    }
-
-    /**
-     * Enlarges the buffer if necessary.
-     */
-    private static byte[] checkBuffer(byte[] buffer, int n) {
-        if (n > buffer.length - 1) {
-            byte[] newBuffer = new byte[buffer.length + buffer.length / 2];
-            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
-            return newBuffer;
-        } else {
-            return buffer;
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public static String[] readLinesNonBlockHelper(BaseRConnection conn, ReadableByteChannel channel, int n, boolean warn, boolean skipNul, String summaryDescription, Charset encoding) {
-
-        throw RInternalError.unimplemented();
-    }
-}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index e873b6585b..97b64c69f4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -23,15 +23,12 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.SocketChannel;
 
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
@@ -49,8 +46,8 @@ public class SocketConnections {
         protected final int port;
         protected final int timeout;
 
-        public RSocketConnection(String modeString, boolean server, String host, int port, boolean blocking, int timeout) throws IOException {
-            super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read, blocking);
+        public RSocketConnection(String modeString, boolean server, String host, int port, boolean blocking, int timeout, String encoding) throws IOException {
+            super(ConnectionClass.Socket, modeString, AbstractOpenMode.Read, blocking, encoding);
             this.server = server;
             this.host = host;
             this.port = port;
@@ -79,10 +76,9 @@ public class SocketConnections {
         }
     }
 
-    private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection {
+    private abstract static class RSocketReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
         private Socket socket;
-        protected InputStream inputStream;
-        protected OutputStream outputStream;
+        private SocketChannel channel;
         protected final RSocketConnection thisBase;
 
         protected RSocketReadWriteConnection(RSocketConnection base) {
@@ -92,36 +88,23 @@ public class SocketConnections {
 
         protected void openStreams(Socket socketArg) throws IOException {
             this.socket = socketArg;
+            channel = socket.getChannel();
             if (thisBase.isBlocking()) {
+                channel.configureBlocking(true);
                 // Java (int) timeouts do not meet the POSIX standard of 31 days
                 long millisTimeout = ((long) thisBase.timeout) * 1000;
                 if (millisTimeout > Integer.MAX_VALUE) {
                     millisTimeout = Integer.MAX_VALUE;
                 }
                 socket.setSoTimeout((int) millisTimeout);
-            }
-            inputStream = socket.getInputStream();
-            outputStream = socket.getOutputStream();
-        }
-
-        @Override
-        public void flush() {
-            // TODO add "throws"
-            try {
-                outputStream.flush();
-            } catch (IOException e) {
-                RInternalError.shouldNotReachHere();
+            } else {
+                channel.configureBlocking(false);
             }
         }
 
         @Override
-        public InputStream getInputStream() {
-            return inputStream;
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            return outputStream;
+        public ByteChannel getChannel() {
+            return channel;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index b751437d15..4d0e008808 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -23,9 +23,11 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -83,7 +85,7 @@ public class TextConnections {
         String[] getValue();
     }
 
-    private static class TextReadRConnection extends DelegateReadRConnection implements GetConnectionValue {
+    private static class TextReadRConnection extends DelegateReadNonBlockRConnection implements GetConnectionValue {
         private final String[] lines;
         private int index;
 
@@ -129,12 +131,12 @@ public class TextConnections {
         }
 
         @Override
-        public InputStream getInputStream() {
+        public ReadableByteChannel getChannel() {
             throw RInternalError.shouldNotReachHere();
         }
     }
 
-    private static class TextWriteRConnection extends DelegateWriteRConnection implements GetConnectionValue {
+    private static class TextWriteRConnection extends DelegateWriteNonBlockRConnection implements GetConnectionValue {
         private String incompleteLine;
         private RStringVector textVec;
         private String idName;
@@ -161,8 +163,8 @@ public class TextConnections {
         }
 
         @Override
-        public OutputStream getOutputStream() throws IOException {
-            return new ConnectionOutputStream();
+        public WritableByteChannel getChannel() {
+            return Channels.newChannel(new ConnectionOutputStream());
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index a7bbc085ba..13bb2d4909 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -24,9 +24,10 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
@@ -37,8 +38,8 @@ public class URLConnections {
     public static class URLRConnection extends BaseRConnection {
         protected final String urlString;
 
-        public URLRConnection(String url, String modeString) throws IOException {
-            super(ConnectionClass.URL, modeString, AbstractOpenMode.Read);
+        public URLRConnection(String url, String modeString, String encoding) throws IOException {
+            super(ConnectionClass.URL, modeString, AbstractOpenMode.Read, encoding);
             this.urlString = url;
         }
 
@@ -52,6 +53,7 @@ public class URLConnections {
             DelegateRConnection delegate = null;
             switch (getOpenMode().abstractOpenMode) {
                 case Read:
+                case ReadBinary:
                     delegate = new URLReadRConnection(this);
                     break;
                 default:
@@ -61,19 +63,19 @@ public class URLConnections {
         }
     }
 
-    private static class URLReadRConnection extends DelegateReadRConnection {
+    private static class URLReadRConnection extends DelegateReadNonBlockRConnection {
 
-        private final BufferedInputStream inputStream;
+        private final ReadableByteChannel rchannel;
 
         protected URLReadRConnection(URLRConnection base) throws MalformedURLException, IOException {
             super(base);
             URL url = new URL(base.urlString);
-            inputStream = new BufferedInputStream(url.openStream());
+            rchannel = Channels.newChannel(new BufferedInputStream(url.openStream()));
         }
 
         @Override
-        public InputStream getInputStream() {
-            return inputStream;
+        public ReadableByteChannel getChannel() {
+            return rchannel;
         }
 
         @Override
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 1683949881..3b33753b04 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
@@ -42213,8 +42213,10 @@ raw(0)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") }
+[1] "TITLE extra line" "2 3 5 7"          ""                 "11 13 17"
+[5] "123"              "abc"              "123"              "abc def"
 Warning message:
 In readLines("test1") : incomplete final line found on 'test1'
 
@@ -73662,86 +73664,177 @@ numeric(0)
 [1] 0
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning messages:
-1: In readLines(zz, 1, warn = T, skipNul = F) :
+1: In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
-2: In readLines(zz, 1, warn = T, skipNul = F) :
+2: In readLines(zz, 2, warn = T, skipNul = F) :
   incomplete final line found on '/tmp/file3762346723'
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 Warning message:
-In readLines(zz, 1, warn = T, skipNul = T) :
+In readLines(zz, 2, warn = T, skipNul = T) :
   incomplete final line found on '/tmp/file3762346723'
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning message:
-In readLines(zz, 1, warn = T, skipNul = F) :
+In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+Warning messages:
+1: In readLines(zz, 2, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+2: In readLines(zz, 2, warn = T, skipNul = F) :
+  incomplete final line found on '/tmp/file3762346723'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+Warning message:
+In readLines(zz, 2, warn = T, skipNul = T) :
+  incomplete final line found on '/tmp/file3762346723'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+Warning message:
+In readLines(zz, 2, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
-Warning message:
-In readLines(zz, 1, warn = T, skipNul = F) :
+Warning messages:
+1: In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
+2: In readLines(zz, 2, warn = T, skipNul = F) :
+  incomplete final line found on '/tmp/file3762346723'
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
+Warning message:
+In readLines(zz, 2, warn = T, skipNul = T) :
+  incomplete final line found on '/tmp/file3762346723'
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning message:
-In readLines(zz, 1, warn = T, skipNul = F) :
+In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b"); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+Warning messages:
+1: In readLines(zz, 2, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+2: In readLines(zz, 2, warn = T, skipNul = F) :
+  incomplete final line found on '/tmp/file3762346723'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+Warning message:
+In readLines(zz, 2, warn = T, skipNul = T) :
+  incomplete final line found on '/tmp/file3762346723'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+[1] "abcd" "ABC"
+Warning message:
+In readLines(zz, 2, warn = T, skipNul = F) :
+  line 1 appears to contain an embedded nul
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+[1] "abcde" "ABC"
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#
 #{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res }
 [1] FALSE
@@ -73767,6 +73860,10 @@ Error in seek.connection(zz, 5) :
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testURLWrite#
+#url("http://localhost:8877", "w")
+can only open URLs for readingError in url("http://localhost:8877", "w") : cannot open the connection
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#Ignored.Unimplemented#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
index 248f32f925..4c6ed7c532 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
@@ -1,16 +1,12 @@
-# IgnoreWarningContext
 cat("TITLE extra line", "2 3 5 7", "", "11 13 17", file = "ex.data", sep = "\n")
-readLines("ex.data", n = -1)
-unlink("ex.data") # tidy up
-
-## difference in blocking
+r0 <- readLines("ex.data", n = -1)
+unlink("ex.data")
 cat("123\nabc", file = "test1")
-readLines("test1") # line with a warning
-
+r1 <- readLines("test1")
 con <- file("test1", "r", blocking = FALSE)
-readLines(con) # empty
+r2 <- readLines(con)
 cat(" def\n", file = "test1", append = TRUE)
-readLines(con) # gets both
+r3 <- readLines(con)
 close(con)
-
-unlink("test1") # tidy up
\ No newline at end of file
+unlink("test1")
+print(c(r0, r1, r2, r3))
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index e100694ad8..a4f1ff4177 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -101,6 +101,11 @@ public class TestConnections extends TestBase {
         }
     }
 
+    @Test
+    public void testURLWrite() {
+        assertEval("url(\"http://localhost:8877\", \"w\")");
+    }
+
     @Test
     public void testFileWriteReadLines() {
         assertEval(TestBase.template("{ writeLines(c(\"line1\", \"line2\"), file(\"%0\")) }", testDir.subDir("wl1")));
@@ -222,11 +227,13 @@ public class TestConnections extends TestBase {
         // two lines, first containing '\0', second line incomplete
         final String twoLinesOneNulIncomp = "c(97,98,99,100,0,101,10,65,66,67)";
 
-        assertEval(TestBase.template("{ fn <- \"" + tmpFile +
-                        "\"; zz <- file(fn,\"w+b\"); writeBin(as.raw(%0), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 1, warn=%1, skipNul=%2); close(zz); unlink(fn); res }",
-                        arr(lineWithNul, twoLinesOneNul, lineWithNulIncomp, twoLinesOneNulIncomp), arr("T", "F"), arr("T", "F")));
+        assertEval(Output.MayIgnoreWarningContext, TestBase.template("{ fn <- \"" + tmpFile +
+                        "\"; zz <- file(fn,\"w+b\", blocking=%0); writeBin(as.raw(%1), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=%2, skipNul=%3); close(zz); unlink(fn); res }",
+                        LVAL, arr(lineWithNul, twoLinesOneNul, lineWithNulIncomp, twoLinesOneNulIncomp), LVAL, LVAL));
     }
 
+    private static final String[] LVAL = arr("T", "F");
+
     private static String[] arr(String... args) {
         return args;
     }
-- 
GitLab


From f23372a0d0d42399f574aefe1140bcf79eafb8a3 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 11:28:15 +0100
Subject: [PATCH 072/402] Refactored socketConnection implementation to be
 purely based on channels.

---
 .../r/runtime/conn/SocketConnections.java     | 23 ++++++++++---------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index 97b64c69f4..aa4ac03913 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -24,9 +24,9 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
-import java.net.ServerSocket;
 import java.net.Socket;
 import java.nio.channels.ByteChannel;
+import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
@@ -86,9 +86,9 @@ public class SocketConnections {
             this.thisBase = base;
         }
 
-        protected void openStreams(Socket socketArg) throws IOException {
-            this.socket = socketArg;
-            channel = socket.getChannel();
+        protected void openStreams(SocketChannel socketArg) throws IOException {
+            channel = socketArg;
+            socket = socketArg.socket();
             if (thisBase.isBlocking()) {
                 channel.configureBlocking(true);
                 // Java (int) timeouts do not meet the POSIX standard of 31 days
@@ -145,21 +145,22 @@ public class SocketConnections {
     }
 
     private static class RServerSocketConnection extends RSocketReadWriteConnection {
-        private final Socket connectionSocket;
+        private final SocketChannel connectionSocket;
 
         RServerSocketConnection(RSocketConnection base) throws IOException {
             super(base);
             InetSocketAddress addr = new InetSocketAddress(base.port);
-            ServerSocket serverSocket = new ServerSocket();
+            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
+
             // we expect only one connection per-server socket; furthermore, we need to accommodate
             // for multiple connections being established locally on the same server port;
             // consequently, we close the server socket at the end of the constructor and allow
             // address reuse to be able to open the next connection after the current one closes
-            serverSocket.setReuseAddress(true);
-            serverSocket.bind(addr);
-            connectionSocket = serverSocket.accept();
+            serverSocketChannel.socket().setReuseAddress(true);
+            serverSocketChannel.socket().bind(addr);
+            connectionSocket = serverSocketChannel.accept();
             openStreams(connectionSocket);
-            serverSocket.close();
+            serverSocketChannel.close();
         }
 
         @Override
@@ -174,7 +175,7 @@ public class SocketConnections {
         RClientSocketConnection(RSocketConnection base) throws IOException {
             super(base);
             SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(base.host, base.port));
-            openStreams(socketChannel.socket());
+            openStreams(socketChannel);
         }
     }
 
-- 
GitLab


From a8c4d896f24ea7d666f1cb4eb44e07c55c4d1861 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 11:36:10 +0100
Subject: [PATCH 073/402] Removed obsolete delegate connection classes. Fixed
 checkstyle errors.

---
 .../r/runtime/conn/ConnectionSupport.java     |   4 +-
 .../r/runtime/conn/DelegateRConnection.java   |   2 +-
 .../conn/DelegateReadNonBlockRConnection.java |   2 +-
 .../runtime/conn/DelegateReadRConnection.java | 109 ------------------
 .../DelegateReadWriteNonBlockRConnection.java |   2 +-
 .../conn/DelegateReadWriteRConnection.java    | 106 -----------------
 .../DelegateWriteNonBlockRConnection.java     |   2 +-
 .../conn/DelegateWriteRConnection.java        |  99 ----------------
 .../r/runtime/conn/PipeConnections.java       |   2 +-
 .../r/test/library/base/TestConnections.java  |  14 +--
 10 files changed, 14 insertions(+), 328 deletions(-)
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index f87eee08cf..b16cb59610 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -860,8 +860,8 @@ public class ConnectionSupport {
     public static BaseRConnection getBaseConnection(RConnection conn) {
         if (conn instanceof BaseRConnection) {
             return (BaseRConnection) conn;
-        } else if (conn instanceof DelegateReadRConnection) {
-            return ((DelegateReadRConnection) conn).base;
+        } else if (conn instanceof DelegateReadNonBlockRConnection) {
+            return ((DelegateReadNonBlockRConnection) conn).base;
         } else {
             throw RInternalError.shouldNotReachHere();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 29d1e6c9f2..66e622b7a3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -412,4 +412,4 @@ abstract class DelegateRConnection extends RConnection {
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
index 9769b1d1e4..73fbc0ab60 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
@@ -109,4 +109,4 @@ public abstract class DelegateReadNonBlockRConnection extends DelegateRConnectio
         close();
     }
 
-}
\ No newline at end of file
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
deleted file mode 100644
index 285666ebfe..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.oracle.truffle.r.runtime.conn;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-/**
- * A blocking connection for reading.
- */
-public abstract class DelegateReadRConnection extends DelegateRConnection {
-
-    protected DelegateReadRConnection(BaseRConnection base) {
-        super(base);
-    }
-
-    @Override
-    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-    }
-
-    @Override
-    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-    }
-
-    @Override
-    public void writeString(String s, boolean nl) throws IOException {
-        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-    }
-
-    @Override
-    public void writeBin(ByteBuffer buffer) throws IOException {
-        throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
-    }
-
-    @Override
-    public int getc() throws IOException {
-        return getInputStream().read();
-    }
-
-    @Override
-    public String readChar(int nchars, boolean useBytes) throws IOException {
-        if (useBytes) {
-            return DelegateRConnection.readCharHelper(nchars, getInputStream());
-        } else {
-            final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
-            return DelegateRConnection.readCharHelper(nchars, isr);
-        }
-    }
-
-    @Override
-    public int readBin(ByteBuffer buffer) throws IOException {
-        return getInputStream().read(buffer.array());
-    }
-
-    @Override
-    public byte[] readBinChars() throws IOException {
-        return DelegateRConnection.readBinCharsHelper(getInputStream());
-    }
-
-    @TruffleBoundary
-    @Override
-    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return readLinesHelper(n, warn, skipNul);
-    }
-
-    @Override
-    public void flush() {
-        // nothing to do when reading
-    }
-
-    @Override
-    public OutputStream getOutputStream() {
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    @Override
-    public boolean canRead() {
-        return true;
-    }
-
-    @Override
-    public boolean canWrite() {
-        return false;
-    }
-
-    @Override
-    public abstract InputStream getInputStream();
-
-    @Override
-    public void close() throws IOException {
-        getInputStream().close();
-    }
-
-    @Override
-    public void closeAndDestroy() throws IOException {
-        base.closed = true;
-        close();
-    }
-
-}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
index 74687a94f3..e3a5924012 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
@@ -114,4 +114,4 @@ abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection
         DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
     }
 
-}
\ No newline at end of file
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
deleted file mode 100644
index 48935e5953..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.oracle.truffle.r.runtime.conn;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-/**
- * A blocking connection for reading and writing.
- */
-abstract class DelegateReadWriteRConnection extends DelegateRConnection {
-
-    protected DelegateReadWriteRConnection(BaseRConnection base) {
-        super(base);
-    }
-
-    @Override
-    public boolean canRead() {
-        return true;
-    }
-
-    @Override
-    public boolean canWrite() {
-        return true;
-    }
-
-    @Override
-    public int getc() throws IOException {
-        return getInputStream().read();
-    }
-
-    @Override
-    public String readChar(int nchars, boolean useBytes) throws IOException {
-        if (useBytes) {
-            return DelegateRConnection.readCharHelper(nchars, getInputStream());
-        } else {
-            final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
-            return DelegateRConnection.readCharHelper(nchars, isr);
-        }
-    }
-
-    @Override
-    public int readBin(ByteBuffer buffer) throws IOException {
-        return getInputStream().read(buffer.array());
-    }
-
-    @Override
-    public byte[] readBinChars() throws IOException {
-        return DelegateRConnection.readBinCharsHelper(getInputStream());
-    }
-
-    @TruffleBoundary
-    @Override
-    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return readLinesHelper(n, warn, skipNul);
-    }
-
-    @Override
-    public void flush() {
-        // nothing to do for channels
-    }
-
-    @Override
-    public abstract OutputStream getOutputStream();
-
-    @Override
-    public abstract InputStream getInputStream();
-
-    @Override
-    public void close() throws IOException {
-        getInputStream().close();
-        getOutputStream().close();
-    }
-
-    @Override
-    public void closeAndDestroy() throws IOException {
-        base.closed = true;
-        close();
-    }
-
-    @Override
-    public void writeBin(ByteBuffer buffer) throws IOException {
-        getOutputStream().write(buffer.array());
-    }
-
-    @Override
-    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        DelegateRConnection.writeCharHelper(getOutputStream(), s, pad, eos);
-    }
-
-    @Override
-    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        DelegateRConnection.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
-    }
-
-    @Override
-    public void writeString(String s, boolean nl) throws IOException {
-        DelegateRConnection.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
-    }
-
-}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
index d6ce50a9db..c369b7e8ba 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
@@ -103,4 +103,4 @@ abstract class DelegateWriteNonBlockRConnection extends DelegateRConnection {
         DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
     }
 
-}
\ No newline at end of file
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
deleted file mode 100644
index ec971e5392..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.oracle.truffle.r.runtime.conn;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-abstract class DelegateWriteRConnection extends DelegateRConnection {
-
-    protected DelegateWriteRConnection(BaseRConnection base) {
-        super(base);
-    }
-
-    @Override
-    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-    }
-
-    @Override
-    public String readChar(int nchars, boolean useBytes) throws IOException {
-        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-    }
-
-    @Override
-    public int readBin(ByteBuffer buffer) throws IOException {
-        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-    }
-
-    @Override
-    public byte[] readBinChars() throws IOException {
-        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-    }
-
-    @Override
-    public int getc() throws IOException {
-        throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
-    }
-
-    @Override
-    public InputStream getInputStream() {
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    @Override
-    public boolean canRead() {
-        return false;
-    }
-
-    @Override
-    public boolean canWrite() {
-        return true;
-    }
-
-    @Override
-    public void closeAndDestroy() throws IOException {
-        base.closed = true;
-        close();
-    }
-
-    @Override
-    public void flush() throws IOException {
-        getOutputStream().flush();
-    }
-
-    @Override
-    public void close() throws IOException {
-        flush();
-        getOutputStream().close();
-    }
-
-    @Override
-    public abstract OutputStream getOutputStream() throws IOException;
-
-    @Override
-    public void writeBin(ByteBuffer buffer) throws IOException {
-        getOutputStream().write(buffer.array());
-    }
-
-    @Override
-    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        DelegateRConnection.writeCharHelper(getOutputStream(), s, pad, eos);
-    }
-
-    @Override
-    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        DelegateRConnection.writeLinesHelper(getOutputStream(), lines, sep, base.getEncoding());
-    }
-
-    @Override
-    public void writeString(String s, boolean nl) throws IOException {
-        DelegateRConnection.writeStringHelper(getOutputStream(), s, nl, base.getEncoding());
-    }
-
-}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
index b16bafb39c..93ba04c101 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -156,7 +156,7 @@ public class PipeConnections {
             private final ReadableByteChannel rchannel;
             private final WritableByteChannel wchannel;
 
-            public RWChannel(InputStream in, OutputStream out) {
+            RWChannel(InputStream in, OutputStream out) {
                 rchannel = Channels.newChannel(in);
                 wchannel = Channels.newChannel(out);
             }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index a4f1ff4177..00e67d8222 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -60,8 +60,8 @@ public class TestConnections extends TestBase {
     }
 
     private static TestDir testDir;
-    private static Path TEMP_FILE_GZIP;
-    private static List<Path> TEMP_FILES = new ArrayList<>();
+    private static Path tempFileGzip;
+    private static final List<Path> TEMP_FILES = new ArrayList<>();
 
     @BeforeClass
     public static void setup() throws IOException {
@@ -70,8 +70,8 @@ public class TestConnections extends TestBase {
         Path path = Paths.get(System.getProperty("java.io.tmpdir"));
 
         // create a gzipped file
-        TEMP_FILE_GZIP = path.resolve("gzipped_____5137528280012599068___.gz");
-        OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(TEMP_FILE_GZIP, StandardOpenOption.WRITE, StandardOpenOption.CREATE));
+        tempFileGzip = path.resolve("gzipped_____5137528280012599068___.gz");
+        OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(tempFileGzip, StandardOpenOption.WRITE, StandardOpenOption.CREATE));
         gzos.write("Hello, World!".getBytes());
         gzos.close();
 
@@ -87,7 +87,7 @@ public class TestConnections extends TestBase {
         if (!deleteDir(testDir.testDirPath)) {
             System.err.println("WARNING: error deleting : " + testDir.testDirPath);
         }
-        deleteFile(TEMP_FILE_GZIP);
+        deleteFile(tempFileGzip);
         for (Path p : TEMP_FILES) {
             deleteFile(p);
         }
@@ -182,8 +182,8 @@ public class TestConnections extends TestBase {
     @Test
     public void testFileSummary() {
 
-        Assert.assertTrue("Could not create required temp file for test.", Files.exists(TEMP_FILE_GZIP));
-        assertEval("{ zz <- file(\"" + TEMP_FILE_GZIP + "\", \"r\"); res <- summary(zz); close(zz); res }");
+        Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip));
+        assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\"); res <- summary(zz); close(zz); res }");
     }
 
     @Test
-- 
GitLab


From 11f6515b91ee26808392cdda2ca4784bfe1c692a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 11:40:40 +0100
Subject: [PATCH 074/402] Deleted accidentally added file.

---
 SocketTest/src/Server.java | 35 -----------------------------------
 1 file changed, 35 deletions(-)
 delete mode 100644 SocketTest/src/Server.java

diff --git a/SocketTest/src/Server.java b/SocketTest/src/Server.java
deleted file mode 100644
index 8747a63dc1..0000000000
--- a/SocketTest/src/Server.java
+++ /dev/null
@@ -1,35 +0,0 @@
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.nio.charset.Charset;
-
-public class Server {
-
-	public static void main(String[] args) {
-
-		try (ServerSocket serverSocket = new ServerSocket(5678)) {
-			System.out.println("server started");
-			while (true) {
-				System.out.println("waiting for client");
-				Socket client = serverSocket.accept();
-				System.out.println("Client connected");
-				getLine();
-				PrintWriter pw = new PrintWriter(new OutputStreamWriter(client.getOutputStream()));
-				pw.println("hello");
-				pw.flush();
-				client.close();
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
-
-	private static void getLine() throws IOException {
-		new BufferedReader(new InputStreamReader(System.in, Charset.defaultCharset())).readLine();
-	}
-
-}
-- 
GitLab


From d69c2935f724c25fc61c6f470eee39501bc7f7d3 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 11:42:54 +0100
Subject: [PATCH 075/402] fixed copyrights

---
 .../r/runtime/conn/DelegateRConnection.java   | 22 +++++++++++++++++++
 .../conn/DelegateReadNonBlockRConnection.java | 22 +++++++++++++++++++
 .../DelegateReadWriteNonBlockRConnection.java | 22 +++++++++++++++++++
 .../DelegateWriteNonBlockRConnection.java     | 22 +++++++++++++++++++
 .../truffle/r/runtime/conn/RConnection.java   |  2 +-
 .../r/runtime/conn/StdConnections.java        |  2 +-
 6 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 66e622b7a3..961fd6f3e8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.BufferedReader;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
index 73fbc0ab60..430a7ad978 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
index e3a5924012..b9d51740e3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
index c369b7e8ba..150ad381b2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 339ad9d9d8..4d63186b1b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 1f1c7541c3..b7359f6363 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From afb451c3704ee5a01e0e98c35e16af2e8bcb964e Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 11:45:21 +0100
Subject: [PATCH 076/402] Renamed new delegate connection classes.

---
 .../truffle/r/runtime/conn/ConnectionSupport.java    |  4 ++--
 ...RConnection.java => DelegateReadRConnection.java} |  4 ++--
 ...ection.java => DelegateReadWriteRConnection.java} |  4 ++--
 ...Connection.java => DelegateWriteRConnection.java} |  4 ++--
 .../truffle/r/runtime/conn/FifoConnections.java      | 12 ++++++------
 .../truffle/r/runtime/conn/FileConnections.java      | 10 +++++-----
 .../truffle/r/runtime/conn/PipeConnections.java      |  6 +++---
 .../truffle/r/runtime/conn/RawConnections.java       |  6 +++---
 .../truffle/r/runtime/conn/SocketConnections.java    |  4 ++--
 .../truffle/r/runtime/conn/TextConnections.java      |  4 ++--
 .../truffle/r/runtime/conn/URLConnections.java       |  2 +-
 11 files changed, 30 insertions(+), 30 deletions(-)
 rename com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/{DelegateReadNonBlockRConnection.java => DelegateReadRConnection.java} (96%)
 rename com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/{DelegateReadWriteNonBlockRConnection.java => DelegateReadWriteRConnection.java} (96%)
 rename com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/{DelegateWriteNonBlockRConnection.java => DelegateWriteRConnection.java} (96%)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index b16cb59610..f87eee08cf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -860,8 +860,8 @@ public class ConnectionSupport {
     public static BaseRConnection getBaseConnection(RConnection conn) {
         if (conn instanceof BaseRConnection) {
             return (BaseRConnection) conn;
-        } else if (conn instanceof DelegateReadNonBlockRConnection) {
-            return ((DelegateReadNonBlockRConnection) conn).base;
+        } else if (conn instanceof DelegateReadRConnection) {
+            return ((DelegateReadRConnection) conn).base;
         } else {
             throw RInternalError.shouldNotReachHere();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
similarity index 96%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index 430a7ad978..25b0b0f3dd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -35,11 +35,11 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
-public abstract class DelegateReadNonBlockRConnection extends DelegateRConnection {
+public abstract class DelegateReadRConnection extends DelegateRConnection {
 
     private final ByteBuffer tmp = ByteBuffer.allocate(1);
 
-    protected DelegateReadNonBlockRConnection(BaseRConnection base) {
+    protected DelegateReadRConnection(BaseRConnection base) {
         super(base);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
similarity index 96%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index b9d51740e3..681dbb9f22 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -35,11 +35,11 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
-abstract class DelegateReadWriteNonBlockRConnection extends DelegateRConnection {
+abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     private final ByteBuffer tmp = ByteBuffer.allocate(1);
 
-    protected DelegateReadWriteNonBlockRConnection(BaseRConnection base) {
+    protected DelegateReadWriteRConnection(BaseRConnection base) {
         super(base);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
similarity index 96%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 150ad381b2..151214f7a7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteNonBlockRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -34,9 +34,9 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
-abstract class DelegateWriteNonBlockRConnection extends DelegateRConnection {
+abstract class DelegateWriteRConnection extends DelegateRConnection {
 
-    protected DelegateWriteNonBlockRConnection(BaseRConnection base) {
+    protected DelegateWriteRConnection(BaseRConnection base) {
         super(base);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index 3adb12e43b..aec1223016 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -120,7 +120,7 @@ public class FifoConnections {
         }
     }
 
-    static class FifoReadRConnection extends DelegateReadNonBlockRConnection {
+    static class FifoReadRConnection extends DelegateReadRConnection {
         private final FileChannel channel;
 
         protected FifoReadRConnection(BaseRConnection base, String path) throws IOException {
@@ -139,7 +139,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoWriteConnection extends DelegateWriteNonBlockRConnection {
+    private static class FifoWriteConnection extends DelegateWriteRConnection {
         private final RandomAccessFile raf;
 
         FifoWriteConnection(BaseRConnection base, String path) throws IOException {
@@ -163,7 +163,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
+    private static class FifoReadWriteConnection extends DelegateReadWriteRConnection {
 
         private final RandomAccessFile raf;
 
@@ -184,7 +184,7 @@ public class FifoConnections {
 
     }
 
-    static class FifoReadNonBlockingRConnection extends DelegateReadNonBlockRConnection {
+    static class FifoReadNonBlockingRConnection extends DelegateReadRConnection {
         private final FileChannel channel;
 
         protected FifoReadNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
@@ -203,7 +203,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoWriteNonBlockingRConnection extends DelegateWriteNonBlockRConnection {
+    private static class FifoWriteNonBlockingRConnection extends DelegateWriteRConnection {
         private final FileChannel channel;
 
         FifoWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
@@ -222,7 +222,7 @@ public class FifoConnections {
         }
     }
 
-    private static class FifoReadWriteNonBlockingRConnection extends DelegateReadWriteNonBlockRConnection {
+    private static class FifoReadWriteNonBlockingRConnection extends DelegateReadWriteRConnection {
         private final FileChannel channel;
 
         FifoReadWriteNonBlockingRConnection(BaseRConnection base, String path) throws IOException {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index c99cf50099..585a301ac6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -253,7 +253,7 @@ public class FileConnections {
         }
     }
 
-    static class FileReadBinaryRConnection extends DelegateReadNonBlockRConnection {
+    static class FileReadBinaryRConnection extends DelegateReadRConnection {
 
         private final FileChannel channel;
 
@@ -303,7 +303,7 @@ public class FileConnections {
         }
     }
 
-    private static class FileWriteBinaryConnection extends DelegateWriteNonBlockRConnection {
+    private static class FileWriteBinaryConnection extends DelegateWriteRConnection {
 
         private final FileChannel channel;
 
@@ -333,7 +333,7 @@ public class FileConnections {
 
     }
 
-    private static class FileReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
+    private static class FileReadWriteConnection extends DelegateReadWriteRConnection {
         /*
          * This is a minimal implementation to support one specific use in package installation.
          *
@@ -443,7 +443,7 @@ public class FileConnections {
 
     }
 
-    private static class CompressedInputRConnection extends DelegateReadNonBlockRConnection {
+    private static class CompressedInputRConnection extends DelegateReadRConnection {
         private final ReadableByteChannel channel;
 
         protected CompressedInputRConnection(BasePathRConnection base, InputStream is) {
@@ -468,7 +468,7 @@ public class FileConnections {
         }
     }
 
-    private static class CompressedOutputRConnection extends DelegateWriteNonBlockRConnection {
+    private static class CompressedOutputRConnection extends DelegateWriteRConnection {
         protected WritableByteChannel channel;
         private final boolean seekable;
         private long seekPosition = 0L;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
index 93ba04c101..10780d615a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -92,7 +92,7 @@ public class PipeConnections {
         }
     }
 
-    static class PipeReadRConnection extends DelegateReadNonBlockRConnection {
+    static class PipeReadRConnection extends DelegateReadRConnection {
         private final ReadableByteChannel channel;
 
         protected PipeReadRConnection(BaseRConnection base, String command) throws IOException {
@@ -112,7 +112,7 @@ public class PipeConnections {
         }
     }
 
-    private static class PipeWriteConnection extends DelegateWriteNonBlockRConnection {
+    private static class PipeWriteConnection extends DelegateWriteRConnection {
         private final WritableByteChannel channel;
 
         PipeWriteConnection(BaseRConnection base, String command) throws IOException {
@@ -132,7 +132,7 @@ public class PipeConnections {
         }
     }
 
-    private static class PipeReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
+    private static class PipeReadWriteConnection extends DelegateReadWriteRConnection {
 
         private final RWChannel channel;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 2f87e573b8..5fe3cd0e8a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -114,7 +114,7 @@ public class RawConnections {
 
     }
 
-    static class RawReadRConnection extends DelegateReadNonBlockRConnection {
+    static class RawReadRConnection extends DelegateReadRConnection {
         private SeekableMemoryByteChannel channel;
 
         RawReadRConnection(BaseRConnection base, SeekableMemoryByteChannel channel) {
@@ -163,7 +163,7 @@ public class RawConnections {
         }
     }
 
-    private static class RawWriteBinaryConnection extends DelegateWriteNonBlockRConnection {
+    private static class RawWriteBinaryConnection extends DelegateWriteRConnection {
         private final SeekableMemoryByteChannel channel;
 
         RawWriteBinaryConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
@@ -194,7 +194,7 @@ public class RawConnections {
         }
     }
 
-    private static class RawReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
+    private static class RawReadWriteConnection extends DelegateReadWriteRConnection {
 
         private final SeekableMemoryByteChannel channel;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index aa4ac03913..2f978e6fa9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -76,7 +76,7 @@ public class SocketConnections {
         }
     }
 
-    private abstract static class RSocketReadWriteConnection extends DelegateReadWriteNonBlockRConnection {
+    private abstract static class RSocketReadWriteConnection extends DelegateReadWriteRConnection {
         private Socket socket;
         private SocketChannel channel;
         protected final RSocketConnection thisBase;
@@ -113,7 +113,7 @@ public class SocketConnections {
         }
     }
 
-    private abstract static class RSocketReadWriteNonBlockConnection extends DelegateReadWriteNonBlockRConnection {
+    private abstract static class RSocketReadWriteNonBlockConnection extends DelegateReadWriteRConnection {
         private Socket socket;
         private SocketChannel socketChannel;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index 4d0e008808..ba21f9b876 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -85,7 +85,7 @@ public class TextConnections {
         String[] getValue();
     }
 
-    private static class TextReadRConnection extends DelegateReadNonBlockRConnection implements GetConnectionValue {
+    private static class TextReadRConnection extends DelegateReadRConnection implements GetConnectionValue {
         private final String[] lines;
         private int index;
 
@@ -136,7 +136,7 @@ public class TextConnections {
         }
     }
 
-    private static class TextWriteRConnection extends DelegateWriteNonBlockRConnection implements GetConnectionValue {
+    private static class TextWriteRConnection extends DelegateWriteRConnection implements GetConnectionValue {
         private String incompleteLine;
         private RStringVector textVec;
         private String idName;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index 13bb2d4909..89aa21762c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -63,7 +63,7 @@ public class URLConnections {
         }
     }
 
-    private static class URLReadRConnection extends DelegateReadNonBlockRConnection {
+    private static class URLReadRConnection extends DelegateReadRConnection {
 
         private final ReadableByteChannel rchannel;
 
-- 
GitLab


From 284df6e3fd898980ee87f7ad954f4bd0f596ec21 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 16:49:08 +0100
Subject: [PATCH 077/402] Implemented isIncomplete. Merged tests for raw
 connections into TestConnections.

---
 .../builtin/base/ConnectionFunctions.java     |   5 +-
 .../r/runtime/conn/DelegateRConnection.java   | 160 ++++--------------
 .../conn/DelegateReadWriteRConnection.java    |  12 +-
 .../conn/DelegateWriteRConnection.java        |   3 +-
 .../r/runtime/conn/FileConnections.java       |   2 +-
 .../truffle/r/runtime/conn/RConnection.java   |  46 +++--
 .../r/runtime/conn/TextConnections.java       |   5 +
 .../builtins/TestBuiltin_rawConnection.java   |  71 --------
 .../r/test/library/base/TestConnections.java  |  56 +++++-
 9 files changed, 134 insertions(+), 226 deletions(-)
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 51dc436711..4b1c2ede3d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -1304,9 +1304,10 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected boolean isIncomplete(int con) {
+        protected RLogicalVector isIncomplete(int con) {
 
-            return RConnection.fromIndex(con).isIncomplete();
+            final boolean res = RConnection.fromIndex(con).isIncomplete();
+            return RDataFactory.createLogicalVectorFromScalar(res);
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 961fd6f3e8..8992103a9b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -24,8 +24,6 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.Reader;
 import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
@@ -33,6 +31,7 @@ import java.nio.channels.SeekableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
+import java.util.Objects;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -43,11 +42,18 @@ import com.sun.istack.internal.NotNull;
 
 import sun.nio.cs.StreamDecoder;
 
+/**
+ * Actually performs the I/O operations for a connections.<br>
+ * <p>
+ * A delegate connection is called from its base connection and implements the actual I/O
+ * operations.
+ * </p>
+ */
 abstract class DelegateRConnection extends RConnection {
-    protected BaseRConnection base;
+    protected final BaseRConnection base;
 
-    DelegateRConnection(@NotNull BaseRConnection base) {
-        this.base = base;
+    DelegateRConnection(BaseRConnection base) {
+        this.base = Objects.requireNonNull(base);
     }
 
     @Override
@@ -79,14 +85,14 @@ abstract class DelegateRConnection extends RConnection {
     }
 
     /**
-     * {@code readLines} from an {@link InputStream}. It would be convenient to use a
-     * {@link BufferedReader} but mixing binary and text operations, which is a requirement, would
-     * then be difficult.
+     * {@code readLines} from the connection. It would be convenient to use a {@link BufferedReader}
+     * but mixing binary and text operations, which is a requirement, would then be difficult.
      *
      * @param warn Specifies if warnings should be output.
      * @param skipNul Specifies if the null character should be ignored.
      */
     protected String[] readLinesHelper(int n, boolean warn, boolean skipNul) throws IOException {
+        base.setIncomplete(false);
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
         byte[] buffer = new byte[64];
@@ -110,6 +116,7 @@ abstract class DelegateRConnection extends RConnection {
                     final String incompleteFinalLine = new String(buffer, 0, totalRead, base.getEncoding());
                     if (!base.isBlocking() && base.isTextMode()) {
                         base.pushBack(RDataFactory.createStringVector(incompleteFinalLine), false);
+                        base.setIncomplete(true);
                     } else {
                         lines.add(incompleteFinalLine);
                         if (warn) {
@@ -157,14 +164,18 @@ abstract class DelegateRConnection extends RConnection {
         return result;
     }
 
-    public static void writeStringHelper(OutputStream out, String s, boolean nl, Charset encoding) throws IOException {
-        out.write(s.getBytes(encoding));
-        if (nl) {
-            out.write(System.lineSeparator().getBytes(encoding));
-        }
-    }
-
-    public static void writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
+    /**
+     * Writes a string to a channel.
+     *
+     * @param out the channel
+     * @param s The actual string to write.
+     * @param nl Indicates if a line separator should be appended.
+     * @param encoding The encoding to use for writing.
+     * @return {@code true} if an incomplete line was written; {@code false} otherwise
+     * @throws IOException
+     */
+    public static boolean writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
+        boolean incomplete;
         final byte[] bytes = s.getBytes(encoding);
         final byte[] lineSepBytes = nl ? System.lineSeparator().getBytes(encoding) : null;
 
@@ -172,36 +183,14 @@ abstract class DelegateRConnection extends RConnection {
         buf.put(bytes);
         if (nl) {
             buf.put(lineSepBytes);
+            incomplete = false;
+        } else {
+            incomplete = !s.contains("\n");
         }
 
         buf.rewind();
         out.write(buf);
-    }
-
-    /**
-     * Writes characters in binary mode (without any re-encoding) to the provided channel.
-     *
-     * @param out The output stream (must not be {@code null}.
-     * @param s The character string to write (must not be {@code null}).
-     * @param pad The number of null characters to append to the characters.
-     * @param eos The end-of-string terminator (may be {@code null}).
-     * @throws IOException
-     */
-    public static void writeCharHelper(OutputStream out, String s, int pad, String eos) throws IOException {
-
-        out.write(s.getBytes());
-        if (pad > 0) {
-            for (int i = 0; i < pad; i++) {
-                out.write(0);
-            }
-        }
-        if (eos != null) {
-            if (eos.length() > 0) {
-                out.write(eos.getBytes());
-            }
-            // function writeChar is defined to append the null character if eos != null
-            out.write(0);
-        }
+        return incomplete;
     }
 
     /**
@@ -238,14 +227,6 @@ abstract class DelegateRConnection extends RConnection {
         channel.write(buf);
     }
 
-    @Deprecated
-    public static void writeBinHelper(ByteBuffer buffer, OutputStream outputStream) throws IOException {
-        int n = buffer.remaining();
-        byte[] b = new byte[n];
-        buffer.get(b);
-        outputStream.write(b);
-    }
-
     /**
      * Reads null-terminated character strings from a {@link ReadableByteChannel}.
      */
@@ -269,39 +250,6 @@ abstract class DelegateRConnection extends RConnection {
         return buffer;
     }
 
-    /**
-     * Reads null-terminated character strings from a {@link InputStream}.
-     */
-    public static byte[] readBinCharsHelper(InputStream in) throws IOException {
-        int ch = in.read();
-        if (ch < 0) {
-            return null;
-        }
-        int totalRead = 0;
-        byte[] buffer = new byte[64];
-        while (true) {
-            buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
-            buffer[totalRead++] = (byte) (ch & 0xFF);
-            if (ch == 0) {
-                break;
-            }
-            ch = in.read();
-        }
-        return buffer;
-    }
-
-    public static int readBinHelper(ByteBuffer buffer, InputStream inputStream) throws IOException {
-        int bytesToRead = buffer.remaining();
-        byte[] b = new byte[bytesToRead];
-        int totalRead = 0;
-        int thisRead = 0;
-        while ((totalRead < bytesToRead) && ((thisRead = inputStream.read(b, totalRead, bytesToRead - totalRead)) > 0)) {
-            totalRead += thisRead;
-        }
-        buffer.put(b, 0, totalRead);
-        return totalRead;
-    }
-
     /**
      * Reads a specified amount of characters.
      *
@@ -324,28 +272,6 @@ abstract class DelegateRConnection extends RConnection {
         return new String(chars, 0, j);
     }
 
-    /**
-     * Reads a specified amount of bytes.
-     *
-     * @param nchars The number of bytes to read.
-     * @param in The input stream.
-     * @return The read string.
-     * @throws IOException
-     */
-    public static String readCharHelper(int nchars, InputStream in) throws IOException {
-        byte[] buf = new byte[nchars];
-        in.read(buf);
-        int j = 0;
-        for (; j < buf.length; j++) {
-            // strings end at 0
-            if (buf[j] == 0) {
-                break;
-            }
-        }
-
-        return new String(buf, 0, j);
-    }
-
     public static String readCharHelper(int nchars, ReadableByteChannel channel, boolean useBytes) throws IOException {
         if (useBytes) {
             ByteBuffer buf = ByteBuffer.allocate(nchars);
@@ -402,7 +328,7 @@ abstract class DelegateRConnection extends RConnection {
     /**
      * Enlarges the buffer if necessary.
      */
-    static byte[] checkBuffer(byte[] buffer, int n) {
+    private static byte[] checkBuffer(byte[] buffer, int n) {
         if (n > buffer.length - 1) {
             byte[] newBuffer = new byte[buffer.length + buffer.length / 2];
             System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
@@ -412,26 +338,14 @@ abstract class DelegateRConnection extends RConnection {
         }
     }
 
-    @SuppressWarnings("unused")
-    public static String[] readLinesNonBlockHelper(BaseRConnection conn, ReadableByteChannel channel, int n, boolean warn, boolean skipNul, String summaryDescription, Charset encoding) {
-
-        throw RInternalError.unimplemented();
-    }
-
-    public static void writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
-        for (int i = 0; i < lines.getLength(); i++) {
-            final String line = lines.getDataAt(i);
-            DelegateRConnection.writeStringHelper(out, line, false, encoding);
-            DelegateRConnection.writeStringHelper(out, sep, false, encoding);
-        }
-    }
-
-    public static void writeLinesHelper(OutputStream out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
+    public static boolean writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
+        boolean incomplete = false;
         for (int i = 0; i < lines.getLength(); i++) {
             final String line = lines.getDataAt(i);
-            DelegateRConnection.writeStringHelper(out, line, false, encoding);
-            DelegateRConnection.writeStringHelper(out, sep, false, encoding);
+            incomplete = DelegateRConnection.writeStringHelper(out, line, false, encoding);
+            incomplete = DelegateRConnection.writeStringHelper(out, sep, false, encoding) || incomplete;
         }
+        return incomplete;
     }
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 681dbb9f22..3b9440d497 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -63,12 +63,7 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
-        if (useBytes) {
-            return DelegateRConnection.readCharHelper(nchars, getInputStream());
-        } else {
-            final InputStreamReader isr = new InputStreamReader(getInputStream(), base.getEncoding());
-            return DelegateRConnection.readCharHelper(nchars, isr);
-        }
+        return DelegateRConnection.readCharHelper(nchars, getChannel(), useBytes);
     }
 
     @Override
@@ -78,7 +73,7 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public byte[] readBinChars() throws IOException {
-        return DelegateRConnection.readBinCharsHelper(getInputStream());
+        return DelegateRConnection.readBinCharsHelper(getChannel());
     }
 
     @TruffleBoundary
@@ -128,7 +123,8 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        setIncomplete(incomplete);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 151214f7a7..7b1f02277e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -117,7 +117,8 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        setIncomplete(incomplete);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 585a301ac6..bf3c5e7ad0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -216,7 +216,7 @@ public class FileConnections {
          * type.
          */
         final RCompression.Type cTypeActual;
-        if (openMode == AbstractOpenMode.Read) {
+        if (openMode == AbstractOpenMode.Read || openMode == AbstractOpenMode.ReadBinary) {
             cTypeActual = RCompression.getCompressionType(base.path);
             if (cTypeActual != cType) {
                 base.updateConnectionClass(mapConnectionClass(cTypeActual));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 4d63186b1b..9984f34461 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -26,7 +26,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.LinkedList;
+import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
@@ -74,7 +77,7 @@ public abstract class RConnection implements AutoCloseable {
 
     protected abstract String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException;
 
-    private String readOneLineWithPushBack(String[] res, int ind, @SuppressWarnings("unused") boolean warn, @SuppressWarnings("unused") boolean skipNul) {
+    private String readOneLineWithPushBack(List<String> res, int ind) {
         String s = pushBack.pollLast();
         if (s == null) {
             return null;
@@ -86,7 +89,8 @@ public abstract class RConnection implements AutoCloseable {
                     // suffix is not empty and needs to be processed later
                     pushBack.push(lines[1]);
                 }
-                res[ind] = lines[0];
+                assert res.size() == ind;
+                res.add(ind, lines[0]);
                 return null;
             } else {
                 // no end of the line found yet
@@ -106,7 +110,8 @@ public abstract class RConnection implements AutoCloseable {
                             // suffix is not empty and needs to be processed later
                             pushBack.push(lines[1]);
                         }
-                        res[ind] = sb.append(lines[0]).toString();
+                        assert res.size() == ind;
+                        res.add(ind, sb.append(lines[0]).toString());
                         return null;
                     } // else continue
                 } while (true);
@@ -115,15 +120,29 @@ public abstract class RConnection implements AutoCloseable {
         }
     }
 
+    /**
+     * TODO(fa) This method is subject for refactoring. I modified the original implementation to be
+     * capable to handle a negative 'n' parameter. It indicates to read as much lines as available.
+     */
     @TruffleBoundary
     private String[] readLinesWithPushBack(int n, boolean warn, boolean skipNul) throws IOException {
-        String[] res = new String[n];
-        for (int i = 0; i < n; i++) {
-            String s = readOneLineWithPushBack(res, i, warn, skipNul);
+        // NOTE: 'n' may be negative indicating to read as much lines as available
+        final List<String> res;
+        if (n >= 0) {
+            res = new ArrayList<>(n);
+        } else {
+            res = new ArrayList<>();
+        }
+
+        for (int i = 0; i < n || n < 0; i++) {
+            String s = readOneLineWithPushBack(res, i);
+            final int remainingLineCount = n >= 0 ? n - i : n;
             if (s == null) {
-                if (res[i] == null) {
+                if (i >= res.size() || res.get(i) == null) {
                     // no more push back value
-                    System.arraycopy(readLinesInternal(n - i, warn, skipNul), 0, res, i, n - i);
+
+                    String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul);
+                    res.addAll(Arrays.asList(resInternal));
                     pushBack = null;
                     break;
                 }
@@ -131,13 +150,18 @@ public abstract class RConnection implements AutoCloseable {
             } else {
                 // reached the last push back value without reaching and of line
                 assert pushBack.size() == 0;
-                System.arraycopy(readLinesInternal(n - i, warn, skipNul), 0, res, i, n - i);
-                res[i] = s + res[i];
+                String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul);
+                res.addAll(i, Arrays.asList(resInternal));
+                if (res.get(i) != null) {
+                    res.set(i, s + res.get(i));
+                } else {
+                    res.set(i, s);
+                }
                 pushBack = null;
                 break;
             }
         }
-        return res;
+        return res.toArray(new String[res.size()]);
     }
 
     /**
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index ba21f9b876..79df873a23 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -173,6 +173,7 @@ public class TextConnections {
             if (incompleteLine != null) {
                 appendData(new String[]{incompleteLine});
                 incompleteLine = null;
+                base.setIncomplete(false);
             }
             base.closed = true;
             TextRConnection textBase = (TextRConnection) base;
@@ -192,6 +193,7 @@ public class TextConnections {
                 if (incompleteLine != null) {
                     appendedLines.add(new StringBuffer(incompleteLine).append(result.substring(px, nlIndex)).toString());
                     incompleteLine = null;
+                    base.setIncomplete(false);
                 } else {
                     appendedLines.add(result.substring(px, nlIndex));
                 }
@@ -202,9 +204,11 @@ public class TextConnections {
             if (incompleteLine != null && !endOfLine) {
                 // end of line not found - accumulate incomplete line
                 incompleteLine = new StringBuffer(incompleteLine).append(result).toString();
+                base.setIncomplete(true);
             } else if (px < result.length()) {
                 // only reset incompleteLine if
                 incompleteLine = result.substring(px);
+                base.setIncomplete(true);
             }
             if (appendedLines.size() > 0) {
                 // update the vector data
@@ -238,6 +242,7 @@ public class TextConnections {
             if (incompleteLine != null) {
                 sb.append(incompleteLine);
                 incompleteLine = null;
+                base.setIncomplete(false);
             }
             for (int i = 0; i < lines.getLength(); i++) {
                 sb.append(lines.getDataAt(i));
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
deleted file mode 100644
index 33ae519955..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rawConnection.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.builtins;
-
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestRBase;
-
-// Checkstyle: stop line length check
-public class TestBuiltin_rawConnection extends TestRBase {
-
-    @Override
-    protected String getTestDir() {
-        return "builtins/connection";
-    }
-
-    @Test
-    public void testReadAppendText() {
-
-        assertEval("{ rc <- rawConnection(raw(0), \"a+\"); close(rc); write(charToRaw(\"A\"), rc) }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
-    }
-
-    @Test
-    public void testReadWriteText() {
-
-        assertEval("{ rc <- rawConnection(raw(0), \"r+\"); close(rc); write(charToRaw(\"A\"), rc) }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
-    }
-
-    @Test
-    public void testWriteText() {
-
-        assertEval("{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"w\"); writeChar(s, rc); rawConnectionValue(rc) }");
-        assertEval("{ rc <- rawConnection(raw(0), \"w\"); writeChar(\"Hello\", rc); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
-    }
-
-    @Test
-    public void testWriteBinary() {
-        // this test is currently ignored, since 'charToRaw' is not compliant
-        assertEval(Ignored.Unknown, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
-    }
-
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 00e67d8222..6900a7b8a6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -45,8 +45,10 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestRBase;
 
-public class TestConnections extends TestBase {
+// Checkstyle: stop line length check
+public class TestConnections extends TestRBase {
     private static final class TestDir {
         private final Path testDirPath;
 
@@ -63,6 +65,11 @@ public class TestConnections extends TestBase {
     private static Path tempFileGzip;
     private static final List<Path> TEMP_FILES = new ArrayList<>();
 
+    @Override
+    protected String getTestDir() {
+        return "builtins/connection";
+    }
+
     @BeforeClass
     public static void setup() throws IOException {
         testDir = new TestDir();
@@ -101,11 +108,6 @@ public class TestConnections extends TestBase {
         }
     }
 
-    @Test
-    public void testURLWrite() {
-        assertEval("url(\"http://localhost:8877\", \"w\")");
-    }
-
     @Test
     public void testFileWriteReadLines() {
         assertEval(TestBase.template("{ writeLines(c(\"line1\", \"line2\"), file(\"%0\")) }", testDir.subDir("wl1")));
@@ -168,7 +170,7 @@ public class TestConnections extends TestBase {
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); tcval; close(con) }");
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); writeLines(\"\", con); tcval; close(con) }");
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\\nb\", con); tcval; close(con) }");
-        assertEval(Ignored.Unimplemented, "c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\\n', file=c); isIncomplete(c); close(c); out");
+        assertEval("c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\\n', file=c); isIncomplete(c); close(c); out");
 
         assertEval("{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection(\"buf\", open=\"w\", local=T); write.table(d, c); buf }");
     }
@@ -193,13 +195,13 @@ public class TestConnections extends TestBase {
         final Path utf8File = TEMP_FILES.get(0);
         writeEncodedString(utf8File, "utf8", "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß.\n");
         assertEval(Ignored.ImplementationError, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
-        assertEval("fin <- file(\"" + utf8File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
+        assertEval(Ignored.ImplementationError, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
 
         // read from ISO-8859-1 (aka Latin1) file
         final Path latin1File = TEMP_FILES.get(1);
         writeEncodedString(latin1File, "ISO-8859-1", "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß.\n");
         assertEval(Ignored.Unknown, "fin <- file(\"" + latin1File + "\", \"r\"); lines <- readLines(fin, 1, encoding = \"UTF-8\"); close(fin); lines");
-        assertEval("fin <- file(\"" + latin1File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
+        assertEval(Ignored.ImplementationError, "fin <- file(\"" + latin1File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
         assertEval(Ignored.ImplementationError, "fin <- file(\"" + latin1File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
 
         // use inexisting charset
@@ -232,6 +234,42 @@ public class TestConnections extends TestBase {
                         LVAL, arr(lineWithNul, twoLinesOneNul, lineWithNulIncomp, twoLinesOneNulIncomp), LVAL, LVAL));
     }
 
+    @Test
+    public void testRawReadAppendText() {
+
+        assertEval("{ rc <- rawConnection(raw(0), \"a+\"); close(rc); write(charToRaw(\"A\"), rc) }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"a+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+    }
+
+    @Test
+    public void testRawReadWriteText() {
+
+        assertEval("{ rc <- rawConnection(raw(0), \"r+\"); close(rc); write(charToRaw(\"A\"), rc) }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); writeChar(\", World\", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval("{ rv <- charToRaw(\"Hello\"); rc <- rawConnection(rv, \"r+\"); write(charToRaw(\", World\"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }");
+    }
+
+    @Test
+    public void testRawWriteText() {
+
+        assertEval("{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"w\"); writeChar(s, rc); rawConnectionValue(rc) }");
+        assertEval("{ rc <- rawConnection(raw(0), \"w\"); writeChar(\"Hello\", rc); writeChar(\", World\", rc); res <- rawConnectionValue(rc); close(rc); res }");
+    }
+
+    @Test
+    public void testRawWriteBinary() {
+
+        // this test is currently ignored, since 'charToRaw' is not compliant
+        assertEval(Ignored.Unknown, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval(Output.IgnoreWarningContext,
+                        "{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
+    }
+
     private static final String[] LVAL = arr("T", "F");
 
     private static String[] arr(String... args) {
-- 
GitLab


From ce7e735b186fb58a156b4f2a5bd1d131fdb3c69d Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 27 Feb 2017 18:38:14 +0100
Subject: [PATCH 078/402] Refactored base classes RConnection, BaseRConnection,
 and DelegateRConnection to strictly seperate the concerns. BaseRConnection
 now stores "session data" whereas a delegate connection performs the I/O
 operation. RConnection is now just an interface defining common operations.

---
 .../builtin/base/ConnectionFunctions.java     |   2 +-
 .../r/runtime/conn/ConnectionSupport.java     | 214 ++++++++++++++-
 .../r/runtime/conn/DelegateRConnection.java   |  13 +-
 .../runtime/conn/DelegateReadRConnection.java |   7 -
 .../conn/DelegateReadWriteRConnection.java    |   9 +-
 .../conn/DelegateWriteRConnection.java        |   4 +-
 .../r/runtime/conn/FileConnections.java       |  10 +-
 .../truffle/r/runtime/conn/RConnection.java   | 251 +++---------------
 .../r/runtime/conn/RawConnections.java        |   6 +-
 .../r/runtime/conn/StdConnections.java        |   6 +-
 .../r/runtime/conn/TextConnections.java       |   4 +-
 11 files changed, 259 insertions(+), 267 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 4b1c2ede3d..d00ec703ff 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -1170,7 +1170,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector getConnection(int what) {
-            RConnection con = RContext.getInstance().stateRConnection.getConnection(what, false);
+            BaseRConnection con = RContext.getInstance().stateRConnection.getConnection(what, false);
             if (con == null) {
                 throw error(RError.Message.NO_SUCH_CONNECTION, what);
             } else {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index f87eee08cf..03e0047e39 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -32,14 +32,22 @@ import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RExternalPtr;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -347,17 +355,12 @@ public class ConnectionSupport {
 
     // TODO implement all open modes
 
-    public static final class InvalidConnection extends RConnection {
+    public static final class InvalidConnection implements RConnection {
 
         public static final InvalidConnection instance = new InvalidConnection();
 
         private static final int INVALID_DESCRIPTOR = -1;
 
-        @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
-        }
-
         @Override
         public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
@@ -464,9 +467,15 @@ public class ConnectionSupport {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public void pushBack(RAbstractStringVector lines, boolean addNewLine) {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
+
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            // TODO Auto-generated method stub
+            return 0;
+        }
     }
 
     /**
@@ -488,7 +497,7 @@ public class ConnectionSupport {
      * it subsequently will throw an error. The latter will open/close the connection (internally)
      * and this can be repeated indefinitely.
      */
-    public abstract static class BaseRConnection extends RConnection {
+    public abstract static class BaseRConnection implements RConnection {
 
         /**
          * {@code true} is the connection has been opened successfully. N.B. This supports lazy
@@ -531,6 +540,14 @@ public class ConnectionSupport {
 
         private ConnectionClass conClass;
 
+        private LinkedList<String> pushBack;
+
+        /**
+         * Indicates that the last line read operation was incomplete.<br>
+         * This is only relevant for connections in text and non-blocking mode.
+         */
+        private boolean incomplete = false;
+
         /**
          * The constructor for every connection class except {@link StdConnections}.
          *
@@ -717,10 +734,9 @@ public class ConnectionSupport {
             opened = true;
         }
 
-        @Override
         protected String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
             checkOpen();
-            return theConnection.readLinesInternal(n, warn, skipNul);
+            return theConnection.readLines(n, warn, skipNul);
         }
 
         @Override
@@ -811,10 +827,9 @@ public class ConnectionSupport {
             return theConnection.getc();
         }
 
-        @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             checkOpen();
-            return theConnection.seekInternal(offset, seekMode, seekRWMode);
+            return theConnection.seek(offset, seekMode, seekRWMode);
         }
 
         @Override
@@ -855,6 +870,179 @@ public class ConnectionSupport {
         public boolean isClosed() {
             return closed;
         }
+
+        private String readOneLineWithPushBack(List<String> res, int ind) {
+            String s = pushBack.pollLast();
+            if (s == null) {
+                return null;
+            } else {
+                String[] lines = s.split("\n", 2);
+                if (lines.length == 2) {
+                    // we hit end of the line
+                    if (lines[1].length() != 0) {
+                        // suffix is not empty and needs to be processed later
+                        pushBack.push(lines[1]);
+                    }
+                    assert res.size() == ind;
+                    res.add(ind, lines[0]);
+                    return null;
+                } else {
+                    // no end of the line found yet
+                    StringBuilder sb = new StringBuilder();
+                    do {
+                        assert lines.length == 1;
+                        sb.append(lines[0]);
+                        s = pushBack.pollLast();
+                        if (s == null) {
+                            break;
+                        }
+
+                        lines = s.split("\n", 2);
+                        if (lines.length == 2) {
+                            // we hit end of the line
+                            if (lines[1].length() != 0) {
+                                // suffix is not empty and needs to be processed later
+                                pushBack.push(lines[1]);
+                            }
+                            assert res.size() == ind;
+                            res.add(ind, sb.append(lines[0]).toString());
+                            return null;
+                        } // else continue
+                    } while (true);
+                    return sb.toString();
+                }
+            }
+        }
+
+        /**
+         * TODO(fa) This method is subject for refactoring. I modified the original implementation
+         * to be capable to handle a negative 'n' parameter. It indicates to read as much lines as
+         * available.
+         */
+        @TruffleBoundary
+        private String[] readLinesWithPushBack(int n, boolean warn, boolean skipNul) throws IOException {
+            // NOTE: 'n' may be negative indicating to read as much lines as available
+            final List<String> res;
+            if (n >= 0) {
+                res = new ArrayList<>(n);
+            } else {
+                res = new ArrayList<>();
+            }
+
+            for (int i = 0; i < n || n < 0; i++) {
+                String s = readOneLineWithPushBack(res, i);
+                final int remainingLineCount = n >= 0 ? n - i : n;
+                if (s == null) {
+                    if (i >= res.size() || res.get(i) == null) {
+                        // no more push back value
+
+                        String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul);
+                        res.addAll(Arrays.asList(resInternal));
+                        pushBack = null;
+                        break;
+                    }
+                    // else res[i] has been filled - move to trying to fill the next one
+                } else {
+                    // reached the last push back value without reaching and of line
+                    assert pushBack.size() == 0;
+                    String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul);
+                    res.addAll(i, Arrays.asList(resInternal));
+                    if (res.get(i) != null) {
+                        res.set(i, s + res.get(i));
+                    } else {
+                        res.set(i, s);
+                    }
+                    pushBack = null;
+                    break;
+                }
+            }
+            return res.toArray(new String[res.size()]);
+        }
+
+        @Override
+        public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
+            if (pushBack == null) {
+                return readLinesInternal(n, warn, skipNul);
+            } else if (pushBack.size() == 0) {
+                pushBack = null;
+                return readLinesInternal(n, warn, skipNul);
+            } else {
+                return readLinesWithPushBack(n, warn, skipNul);
+            }
+        }
+
+        /**
+         * Pushes lines back to the connection.
+         */
+        @Override
+        @TruffleBoundary
+        public final void pushBack(RAbstractStringVector lines, boolean addNewLine) {
+            if (pushBack == null) {
+                pushBack = new LinkedList<>();
+            }
+            for (int i = 0; i < lines.getLength(); i++) {
+                String newLine = lines.getDataAt(i);
+                if (addNewLine) {
+                    newLine = newLine + '\n';
+                }
+                pushBack.addFirst(newLine);
+            }
+        }
+
+        /**
+         * Return the length of the push back.
+         */
+        @TruffleBoundary
+        public final int pushBackLength() {
+            return pushBack == null ? 0 : pushBack.size();
+        }
+
+        /**
+         * Clears the pushback.
+         */
+        @TruffleBoundary
+        public final void pushBackClear() {
+            pushBack = null;
+        }
+
+        /**
+         * Support for {@code seek} Internal. Also clears push back lines.
+         */
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            if (isSeekable()) {
+                // discard any push back strings
+                pushBackClear();
+            }
+            // Do not throw error at this position, since the error messages varies depending on the
+            // connection.
+            return seekInternal(offset, seekMode, seekRWMode);
+        }
+
+        /**
+         * Returns {@code true} iff the last read operation was blocked or there is unflushed
+         * output.
+         */
+        public boolean isIncomplete() {
+            return incomplete;
+        }
+
+        protected void setIncomplete(boolean b) {
+            this.incomplete = b;
+        }
+
+        public final RAbstractIntVector asVector() {
+            String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass().getPrintName(), "connection"};
+
+            RAbstractIntVector result = RDataFactory.createIntVector(new int[]{getDescriptor()}, true);
+
+            RStringVector classVector = RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR);
+            // it's important to put "this" into the externalptr, so that it doesn't get collected
+            RExternalPtr connectionId = RDataFactory.createExternalPtr(null, this, RDataFactory.createSymbol("connection"), RNull.instance);
+            DynamicObject attrs = RAttributesLayout.createClassWithConnId(classVector, connectionId);
+            result.initAttributes(attrs);
+            return result;
+        }
     }
 
     public static BaseRConnection getBaseConnection(RConnection conn) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 8992103a9b..7cefc299b9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -33,6 +33,7 @@ import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Objects;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
@@ -49,7 +50,7 @@ import sun.nio.cs.StreamDecoder;
  * operations.
  * </p>
  */
-abstract class DelegateRConnection extends RConnection {
+abstract class DelegateRConnection implements RConnection {
     protected final BaseRConnection base;
 
     DelegateRConnection(BaseRConnection base) {
@@ -77,7 +78,7 @@ abstract class DelegateRConnection extends RConnection {
     }
 
     @Override
-    protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+    public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
         if (!isSeekable()) {
             throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_ENABLED);
         }
@@ -91,7 +92,9 @@ abstract class DelegateRConnection extends RConnection {
      * @param warn Specifies if warnings should be output.
      * @param skipNul Specifies if the null character should be ignored.
      */
-    protected String[] readLinesHelper(int n, boolean warn, boolean skipNul) throws IOException {
+    @Override
+    @TruffleBoundary
+    public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
         base.setIncomplete(false);
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
@@ -348,4 +351,8 @@ abstract class DelegateRConnection extends RConnection {
         return incomplete;
     }
 
+    @Override
+    public void pushBack(RAbstractStringVector lines, boolean addNewLine) {
+        throw RInternalError.shouldNotReachHere();
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index 25b0b0f3dd..1ffc079510 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -29,7 +29,6 @@ import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
@@ -86,12 +85,6 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
         return DelegateRConnection.readBinCharsHelper(getChannel());
     }
 
-    @TruffleBoundary
-    @Override
-    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return readLinesHelper(n, warn, skipNul);
-    }
-
     @Override
     public void flush() {
         // nothing to do when reading
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 3b9440d497..e9f2a58054 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
@@ -76,12 +75,6 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
         return DelegateRConnection.readBinCharsHelper(getChannel());
     }
 
-    @TruffleBoundary
-    @Override
-    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-        return readLinesHelper(n, warn, skipNul);
-    }
-
     @Override
     public void flush() {
         // nothing to do for channels
@@ -124,7 +117,7 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
         boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
-        setIncomplete(incomplete);
+        base.setIncomplete(incomplete);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 7b1f02277e..fd7d9a9c2e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -41,7 +41,7 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
     }
 
     @Override
-    public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+    public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
         throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
     }
 
@@ -118,7 +118,7 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
         boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
-        setIncomplete(incomplete);
+        base.setIncomplete(incomplete);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index bf3c5e7ad0..5072705e00 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -377,7 +377,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             long result = raf.getFilePointer();
             switch (seekMode) {
                 case ENQUIRE:
@@ -406,9 +406,9 @@ public class FileConnections {
         }
 
         @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
             raf.seek(readOffset);
-            return super.readLinesInternal(n, warn, skipNul);
+            return super.readLines(n, warn, skipNul);
         }
 
         @Override
@@ -486,7 +486,7 @@ public class FileConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             if (seekable) {
                 // TODO GZIP is basically seekable; however, the output stream does not allow any
                 // seeking
@@ -494,7 +494,7 @@ public class FileConnections {
                 seekPosition = offset;
                 return oldPos;
             }
-            return super.seekInternal(offset, seekMode, seekRWMode);
+            return super.seek(offset, seekMode, seekRWMode);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 9984f34461..d2a4d2ac02 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -26,186 +26,47 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RAttributesLayout;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RExternalPtr;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 /**
  * Denotes an R {@code connection} instance used in the {@code base} I/O library.
- *
- * TODO Refactor the pushBack code into ConnectionsSupport
  */
-public abstract class RConnection implements AutoCloseable {
-
-    public final RAbstractIntVector asVector() {
-        String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass().getPrintName(), "connection"};
+public interface RConnection extends AutoCloseable {
 
-        RAbstractIntVector result = RDataFactory.createIntVector(new int[]{getDescriptor()}, true);
-
-        RStringVector classVector = RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR);
-        // it's important to put "this" into the externalptr, so that it doesn't get collected
-        RExternalPtr connectionId = RDataFactory.createExternalPtr(null, this, RDataFactory.createSymbol("connection"), RNull.instance);
-        DynamicObject attrs = RAttributesLayout.createClassWithConnId(classVector, connectionId);
-        result.initAttributes(attrs);
-        return result;
-    }
-
-    public static BaseRConnection fromIndex(int con) {
+    static BaseRConnection fromIndex(int con) {
         return RContext.getInstance().stateRConnection.getConnection(con, true);
     }
 
-    private LinkedList<String> pushBack;
-
-    /**
-     * Indicates that the last line read operation was incomplete.<br>
-     * This is only relevant for connections in text and non-blocking mode.
-     */
-    private boolean incomplete = false;
-
-    protected abstract String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException;
-
-    private String readOneLineWithPushBack(List<String> res, int ind) {
-        String s = pushBack.pollLast();
-        if (s == null) {
-            return null;
-        } else {
-            String[] lines = s.split("\n", 2);
-            if (lines.length == 2) {
-                // we hit end of the line
-                if (lines[1].length() != 0) {
-                    // suffix is not empty and needs to be processed later
-                    pushBack.push(lines[1]);
-                }
-                assert res.size() == ind;
-                res.add(ind, lines[0]);
-                return null;
-            } else {
-                // no end of the line found yet
-                StringBuilder sb = new StringBuilder();
-                do {
-                    assert lines.length == 1;
-                    sb.append(lines[0]);
-                    s = pushBack.pollLast();
-                    if (s == null) {
-                        break;
-                    }
-
-                    lines = s.split("\n", 2);
-                    if (lines.length == 2) {
-                        // we hit end of the line
-                        if (lines[1].length() != 0) {
-                            // suffix is not empty and needs to be processed later
-                            pushBack.push(lines[1]);
-                        }
-                        assert res.size() == ind;
-                        res.add(ind, sb.append(lines[0]).toString());
-                        return null;
-                    } // else continue
-                } while (true);
-                return sb.toString();
-            }
-        }
-    }
-
-    /**
-     * TODO(fa) This method is subject for refactoring. I modified the original implementation to be
-     * capable to handle a negative 'n' parameter. It indicates to read as much lines as available.
-     */
-    @TruffleBoundary
-    private String[] readLinesWithPushBack(int n, boolean warn, boolean skipNul) throws IOException {
-        // NOTE: 'n' may be negative indicating to read as much lines as available
-        final List<String> res;
-        if (n >= 0) {
-            res = new ArrayList<>(n);
-        } else {
-            res = new ArrayList<>();
-        }
-
-        for (int i = 0; i < n || n < 0; i++) {
-            String s = readOneLineWithPushBack(res, i);
-            final int remainingLineCount = n >= 0 ? n - i : n;
-            if (s == null) {
-                if (i >= res.size() || res.get(i) == null) {
-                    // no more push back value
-
-                    String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul);
-                    res.addAll(Arrays.asList(resInternal));
-                    pushBack = null;
-                    break;
-                }
-                // else res[i] has been filled - move to trying to fill the next one
-            } else {
-                // reached the last push back value without reaching and of line
-                assert pushBack.size() == 0;
-                String[] resInternal = readLinesInternal(remainingLineCount, warn, skipNul);
-                res.addAll(i, Arrays.asList(resInternal));
-                if (res.get(i) != null) {
-                    res.set(i, s + res.get(i));
-                } else {
-                    res.set(i, s);
-                }
-                pushBack = null;
-                break;
-            }
-        }
-        return res.toArray(new String[res.size()]);
-    }
-
-    /**
-     * Read (n > 0 up to n else unlimited) lines on the connection.
-     *
-     */
-    @TruffleBoundary
-    public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
-        if (pushBack == null) {
-            return readLinesInternal(n, warn, skipNul);
-        } else if (pushBack.size() == 0) {
-            pushBack = null;
-            return readLinesInternal(n, warn, skipNul);
-        } else {
-            return readLinesWithPushBack(n, warn, skipNul);
-        }
-    }
-
     /**
      * Return the underlying input stream (for internal use). TODO Replace with a more principled
      * solution.
      */
-    public abstract InputStream getInputStream() throws IOException;
+    InputStream getInputStream() throws IOException;
 
     /**
      * Return the underlying output stream (for internal use). TODO Replace with a more principled
      * solution.
      */
-    public abstract OutputStream getOutputStream() throws IOException;
+    OutputStream getOutputStream() throws IOException;
 
     /**
      * Close the connection. The corresponds to the {@code R close} function.
      */
-    public abstract void closeAndDestroy() throws IOException;
+    void closeAndDestroy() throws IOException;
 
     /**
      * Returns {@ode true} iff we can read on this connection.
      */
-    public abstract boolean canRead();
+    boolean canRead();
 
     /**
      * Returns {@ode true} iff we can write on this connection.
      */
-    public abstract boolean canWrite();
+    boolean canWrite();
 
     /**
      * Forces the connection open. If the connection was already open does nothing. Otherwise, tries
@@ -228,56 +89,23 @@ public abstract class RConnection implements AutoCloseable {
      * rely on it but should use the result in the body of the {@code try} block. If the connection
      * cannot be opened {@link IOException} is thrown.
      */
-    public abstract RConnection forceOpen(String modeString) throws IOException;
+    RConnection forceOpen(String modeString) throws IOException;
 
     /**
      * Closes the internal state of the stream, but does not set the connection state to "closed",
      * i.e., allowing it to be re-opened.
      */
     @Override
-    public abstract void close() throws IOException;
+    void close() throws IOException;
 
-    /**
-     * Pushes lines back to the connection.
-     */
-    @TruffleBoundary
-    public final void pushBack(RAbstractStringVector lines, boolean addNewLine) {
-        if (pushBack == null) {
-            pushBack = new LinkedList<>();
-        }
-        for (int i = 0; i < lines.getLength(); i++) {
-            String newLine = lines.getDataAt(i);
-            if (addNewLine) {
-                newLine = newLine + '\n';
-            }
-            pushBack.addFirst(newLine);
-        }
-    }
-
-    /**
-     * Return the length of the push back.
-     */
-    @TruffleBoundary
-    public final int pushBackLength() {
-        return pushBack == null ? 0 : pushBack.size();
-    }
-
-    /**
-     * Clears the pushback.
-     */
-    @TruffleBoundary
-    public final void pushBackClear() {
-        pushBack = null;
-    }
-
-    public enum SeekMode {
+    enum SeekMode {
         ENQUIRE,
         START,
         CURRENT,
         END
     }
 
-    public enum SeekRWMode {
+    enum SeekRWMode {
         LAST,
         READ,
         WRITE
@@ -286,40 +114,27 @@ public abstract class RConnection implements AutoCloseable {
     /**
      * Support for {@code isSeekable} Internal.
      */
-    public abstract boolean isSeekable();
-
-    /**
-     * Support for {@code seek} Internal. Also clears push back lines.
-     */
-    public final long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-        if (isSeekable()) {
-            // discard any push back strings
-            pushBackClear();
-        }
-        // Do not throw error at this position, since the error messages varies depending on the
-        // connection.
-        return seekInternal(offset, seekMode, seekRWMode);
-    }
+    boolean isSeekable();
 
     /**
      * Allows to seek in the connection.
      */
-    protected abstract long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException;
+    long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException;
 
     /**
      * Internal support for reading one character at a time.
      */
-    public abstract int getc() throws IOException;
+    int getc() throws IOException;
 
     /**
      * Write the {@code lines} to the connection, with {@code sep} appended after each "line". N.B.
      * The output will only appear as a sequence of lines if {@code sep == "\n"}.
      */
-    public abstract void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException;
+    void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException;
 
-    public abstract void flush() throws IOException;
+    void flush() throws IOException;
 
-    public abstract int getDescriptor();
+    int getDescriptor();
 
     /**
      * Writes {@code s} optionally followed by a newline to the connection. This does not correspond
@@ -327,7 +142,7 @@ public abstract class RConnection implements AutoCloseable {
      * Since these can be diverted by the {@code sink} builtin, every output connection class must
      * support this.
      */
-    public abstract void writeString(String s, boolean nl) throws IOException;
+    void writeString(String s, boolean nl) throws IOException;
 
     /**
      * Internal connection-specific support for the {@code writeChar} builtin.
@@ -337,20 +152,20 @@ public abstract class RConnection implements AutoCloseable {
      * @param eos string to append to s
      * @param useBytes TODO
      */
-    public abstract void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException;
+    void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException;
 
     /**
      * Internal connection-specific support for the {@code readChar} builtin.
      *
      * @param nchars number of characters to read
      */
-    public abstract String readChar(int nchars, boolean useBytes) throws IOException;
+    String readChar(int nchars, boolean useBytes) throws IOException;
 
     /**
      * Internal connection-specific support for the {@code writeBin} builtin. The implementation
      * should attempt to write all the data, denoted by {@code buffer.remaining()}.
      */
-    public abstract void writeBin(ByteBuffer buffer) throws IOException;
+    void writeBin(ByteBuffer buffer) throws IOException;
 
     /**
      * Internal connection-specific support for the {@code readBin} builtin. The buffer is allocated
@@ -358,7 +173,7 @@ public abstract class RConnection implements AutoCloseable {
      * should attempt to read that much data, returning the actual number read as the result. EOS is
      * denoted by a return value of zero.
      */
-    public abstract int readBin(ByteBuffer buffer) throws IOException;
+    int readBin(ByteBuffer buffer) throws IOException;
 
     /**
      * Internal connection-specific support for the {@code readBin} builtin on character data.
@@ -367,27 +182,23 @@ public abstract class RConnection implements AutoCloseable {
      * implies that no data was read. The caller must locate the null terminator to determine the
      * length of the string.
      */
-    public abstract byte[] readBinChars() throws IOException;
+    byte[] readBinChars() throws IOException;
 
     /**
-     * Returns {@code true} iff this is a text mode connection.
+     * Read (n > 0 up to n else unlimited) lines on the connection.
      */
-    public abstract boolean isTextMode();
+    @TruffleBoundary
+    String[] readLines(int n, boolean warn, boolean skipNul) throws IOException;
 
     /**
-     * Returns {@code true} iff this connection is open.
+     * Returns {@code true} iff this is a text mode connection.
      */
-    public abstract boolean isOpen();
+    boolean isTextMode();
 
     /**
-     * Returns {@code true} iff the last read operation was blocked or there is unflushed output.
+     * Returns {@code true} iff this connection is open.
      */
-    public boolean isIncomplete() {
-        return incomplete;
-    }
-
-    protected void setIncomplete(boolean b) {
-        this.incomplete = b;
-    }
+    boolean isOpen();
 
+    void pushBack(RAbstractStringVector lines, boolean addNewLine);
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 5fe3cd0e8a..3213cfc97f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -148,7 +148,7 @@ public class RawConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
@@ -179,7 +179,7 @@ public class RawConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
@@ -211,7 +211,7 @@ public class RawConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index b7359f6363..58699a574c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -79,15 +79,15 @@ public class StdConnections {
         return RContext.getInstance().stateStdConnections;
     }
 
-    public static RConnection getStdin() {
+    public static BaseRConnection getStdin() {
         return getContextState().stdin;
     }
 
-    public static RConnection getStdout() {
+    public static BaseRConnection getStdout() {
         return getContextState().stdout;
     }
 
-    public static RConnection getStderr() {
+    public static BaseRConnection getStderr() {
         return getContextState().stderr;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index 79df873a23..686a25a829 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -101,7 +101,7 @@ public class TextConnections {
         }
 
         @Override
-        public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
+        public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
             int nleft = lines.length - index;
             int nlines = nleft;
             if (n > 0) {
@@ -302,7 +302,7 @@ public class TextConnections {
         }
 
         @Override
-        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_RELEVANT_FOR_TEXT_CON);
         }
 
-- 
GitLab


From c511704667d1698f267ee975789ef5071f992da9 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 09:43:45 +0100
Subject: [PATCH 079/402] Fixed a compilation error introduced by rebasing.
 Replaced "RError.error(this..." by "RError.error(RError.SHOW_CALLER...".
 Implemented handling of flag 'raw' when opening files. Added a test for this.
 Fixed warning in class ConnectionFunctions.

---
 .../builtin/base/ConnectionFunctions.java     |  32 ++--
 .../conn/DelegateReadWriteRConnection.java    |   1 -
 .../r/runtime/conn/FileConnections.java       |  14 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 174 ++++++++++++++----
 .../r/test/library/base/TestConnections.java  |   6 +
 5 files changed, 163 insertions(+), 64 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index d00ec703ff..dc54eaa2f7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -231,8 +231,8 @@ public abstract class ConnectionFunctions {
             } catch (MalformedURLException e) {
                 // ignore and try to open file
             } catch (IOException e) {
-                RError.warning(this, RError.Message.UNABLE_TO_RESOLVE, e.getMessage());
-                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+                RError.warning(RError.SHOW_CALLER, RError.Message.UNABLE_TO_RESOLVE, e.getMessage());
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
             }
 
             if (path.length() == 0) {
@@ -247,13 +247,13 @@ public abstract class ConnectionFunctions {
                 }
             }
             try {
-                return new FileRConnection(path, open, blocking, encoding).asVector();
+                return new FileRConnection(path, open, blocking, encoding, raw).asVector();
             } catch (IOException ex) {
                 warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
                 throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
-            }
+            } 
         }
     }
 
@@ -286,7 +286,7 @@ public abstract class ConnectionFunctions {
             } catch (IOException ex) {
                 throw reportError(description.getDataAt(0), ex);
             } catch (IllegalCharsetNameException ex) {
-                throw RError.error(this, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
+                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
 
@@ -353,7 +353,6 @@ public abstract class ConnectionFunctions {
             }
         }
 
-        @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector textConnection(String description, RNull text, String open, REnvironment env, int encoding) {
@@ -403,12 +402,7 @@ public abstract class ConnectionFunctions {
         protected RAbstractIntVector socketConnection(String host, int port, boolean server, boolean blocking, String open,
                         String encoding, int timeout) {
             try {
-                if (server) {
-                    return new RSocketConnection(open, true, host, port, blocking, timeout, encoding).asVector();
-                } else {
-                    return new RSocketConnection(open, false, host, port, blocking, timeout, encoding).asVector();
-                }
-                return new RSocketConnection(open, server, host, port, blocking, timeout).asVector();
+                return new RSocketConnection(open, server, host, port, blocking, timeout, encoding).asVector();
             } catch (IOException ex) {
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
@@ -1222,13 +1216,15 @@ public abstract class ConnectionFunctions {
              * for the NA (enquiry) case.
              */
             long offset = 0;
+            final int actualOrigin;
             if (RRuntime.isNAorNaN(where)) {
-                origin = 0;
+                actualOrigin = 0;
             } else {
                 offset = (long) where;
+                actualOrigin = origin;
             }
             try {
-                long newOffset = RConnection.fromIndex(con).seek(offset, RConnection.SeekMode.values()[origin], RConnection.SeekRWMode.values()[rw]);
+                long newOffset = RConnection.fromIndex(con).seek(offset, RConnection.SeekMode.values()[actualOrigin], RConnection.SeekRWMode.values()[rw]);
                 if (newOffset > Integer.MAX_VALUE) {
                     throw RError.nyi(RError.SHOW_CALLER, "seek > Integer.MAX_VALUE");
                 }
@@ -1261,9 +1257,9 @@ public abstract class ConnectionFunctions {
                 return new FifoRConnection(path, open, blocking, encoding).asVector();
             } catch (IOException ex) {
                 RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
-                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
-                throw RError.error(this, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
+                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -1287,9 +1283,9 @@ public abstract class ConnectionFunctions {
                 return new PipeRConnection(path, open, encoding).asVector();
             } catch (IOException ex) {
                 RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
-                throw RError.error(this, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
-                throw RError.error(this, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
+                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index e9f2a58054..bac95d6d9f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -29,7 +29,6 @@ import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.Channels;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 5072705e00..2c45f99e8f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -67,9 +67,11 @@ public class FileConnections {
      * Base class for all modes of file connections.
      */
     public static class FileRConnection extends BasePathRConnection {
+        private final boolean raw;
 
-        public FileRConnection(String path, String modeString, boolean blocking, String encoding) throws IOException {
+        public FileRConnection(String path, String modeString, boolean blocking, String encoding, boolean raw) throws IOException {
             super(checkTemp(path), ConnectionClass.File, modeString, blocking, encoding);
+            this.raw = raw;
             openNonLazyConnection();
         }
 
@@ -84,7 +86,7 @@ public class FileConnections {
         @Override
         protected void createDelegateConnection() throws IOException {
 
-            DelegateRConnection delegate = FileConnections.createDelegateConnection(this, RCompression.Type.NONE);
+            DelegateRConnection delegate = FileConnections.createDelegateConnection(this, RCompression.Type.NONE, raw);
             setDelegate(delegate);
         }
     }
@@ -107,7 +109,7 @@ public class FileConnections {
 
         @Override
         protected void createDelegateConnection() throws IOException {
-            setDelegate(FileConnections.createDelegateConnection(this, cType));
+            setDelegate(FileConnections.createDelegateConnection(this, cType, false));
 
         }
 
@@ -208,15 +210,15 @@ public class FileConnections {
         }
     }
 
-    private static DelegateRConnection createDelegateConnection(BasePathRConnection base, RCompression.Type cType) throws IOException {
+    private static DelegateRConnection createDelegateConnection(BasePathRConnection base, RCompression.Type cType, boolean raw) throws IOException {
         AbstractOpenMode openMode = base.getOpenMode().abstractOpenMode;
 
         /*
          * For input, we check the actual compression type as GNU R is permissive about the claimed
-         * type.
+         * type except 'raw' is true.
          */
         final RCompression.Type cTypeActual;
-        if (openMode == AbstractOpenMode.Read || openMode == AbstractOpenMode.ReadBinary) {
+        if (!raw && (openMode == AbstractOpenMode.Read || openMode == AbstractOpenMode.ReadBinary)) {
             cTypeActual = RCompression.getCompressionType(base.path);
             if (cTypeActual != cType) {
                 base.updateConnectionClass(mapConnectionClass(cTypeActual));
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 3b33753b04..11618c92fd 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
@@ -42197,6 +42197,7 @@ numeric(0)
 #argv <- structure(list(length = 0), .Names = 'length');do.call('raw', argv)
 raw(0)
 
+<<<<<<< ce7e735b186fb58a156b4f2a5bd1d131fdb3c69d
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#Ignored.Unknown#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R") }
 [1] "abc"
@@ -73501,7 +73502,38 @@ NULL
 #withRestarts({cat("<start>");invokeRestart("foo", 123L, 456L);789L},<<<NEWLINE>>> foo=list(description="my handler", handler=function(a,b) c(a,b)))
 <start>[1] 123 456
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#Ignored.Unknown#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R") }
+[1] "abc"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R") }
+
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R") }
+
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R") }
+
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
+
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") }
+[1] "TITLE extra line" "2 3 5 7"          ""                 "11 13 17"
+[5] "123"              "abc"              "123"              "abc def"
+Warning message:
+In readLines("test1") : incomplete final line found on 'test1'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R") }
+Read 4 items
+Read 4 items
+
+Summary of Residuals:
+
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
 #fin <- file("/tmp/file3408688236", "r", encoding = "UTF-8"); lines <- readLines(fin, 1); close(fin); lines
 [1] "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß."
 
@@ -73527,7 +73559,7 @@ Warning messages:
   incomplete final line found on '/tmp/file4039819292'
 [1] "This is a sentence using german Umlauts like "
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
 #fin <- file("/tmp/file4039819292", "r", encoding = "latin1"); lines <- readLines(fin, 1); close(fin); lines
 [1] "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß."
 
@@ -73535,6 +73567,10 @@ Warning messages:
 #{ wline <- "Hellö"; fin <- file("/tmp/file9823674682", "w+", encoding = "UTF-8"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }
 [1] "Hellö" "Hellö" "TRUE"
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testFileOpenRaw#
+#{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }
+Error in readBin(zz, raw(), 4) : can only read from a binary connection
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary#
 #{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res }
 $description
@@ -73663,15 +73699,79 @@ numeric(0)
 #{ con<-textConnection(c("a","b","c","d")); pushBackLength(con) }
 [1] 0
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText#
+#{ rc <- rawConnection(raw(0), "a+"); close(rc); write(charToRaw("A"), rc) }
+Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
+  invalid connection
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 48 65 6c 6c 6f 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34
+[26] 0a
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] "Hello2c 20 57 6f 72\n6c 64\n"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 00
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadAppendText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] "Hello, World"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText#
+#{ rc <- rawConnection(raw(0), "r+"); close(rc); write(charToRaw("A"), rc) }
+Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
+  invalid connection
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34 0a
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] "2c 20 57 6f 72\n6c 64\n"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
+[1] 2c 20 57 6f 72 6c 64 00
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawReadWriteText#
+#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
+[1] ", World"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.Unknown#
+#{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Output.IgnoreWarningContext#
+#{ zz <- rawConnection(raw(0), "wb"); x <- c("a", "this will be truncated", "abc"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = "\r\n"); res <- rawConnectionValue(zz); close(zz); res }
+ [1] 61 00 00 74 68 69 73 20 77 69 6c 6c 20 61 62 63 61 0d 0a 00 74 68 69 73 20
+[26] 77 69 6c 6c 20 62 65 20 74 72 75 6e 63 61 74 65 64 0d 0a 00 61 62 63 0d 0a
+[51] 00
+Warning message:
+In writeChar(x, zz, nc, eos = NULL) :
+  writeChar: more characters requested than are in the string - will zero-pad
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteText#
+#{ rc <- rawConnection(raw(0), "w"); writeChar("Hello", rc); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
+ [1] 48 65 6c 6c 6f 00 2c 20 57 6f 72 6c 64 00
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteText#
+#{ s <- "äöüß"; rc <- rawConnection(raw(0), "w"); writeChar(s, rc); rawConnectionValue(rc) }
+[1] c3 a4 c3 b6 c3 bc c3 9f 00
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning messages:
@@ -73680,41 +73780,41 @@ Warning messages:
 2: In readLines(zz, 2, warn = T, skipNul = F) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 Warning messages:
@@ -73723,41 +73823,41 @@ Warning messages:
 2: In readLines(zz, 2, warn = T, skipNul = F) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning messages:
@@ -73766,41 +73866,41 @@ Warning messages:
 2: In readLines(zz, 2, warn = T, skipNul = F) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 Warning messages:
@@ -73809,29 +73909,29 @@ Warning messages:
 2: In readLines(zz, 2, warn = T, skipNul = F) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
   incomplete final line found on '/tmp/file3762346723'
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
 [1] "abcd" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#
+##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
 #{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
 [1] "abcde" "ABC"
 
@@ -73860,11 +73960,7 @@ Error in seek.connection(zz, 5) :
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testURLWrite#
-#url("http://localhost:8877", "w")
-can only open URLs for readingError in url("http://localhost:8877", "w") : cannot open the connection
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
 [1] FALSE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 6900a7b8a6..54d2d01d6d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -188,6 +188,12 @@ public class TestConnections extends TestRBase {
         assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\"); res <- summary(zz); close(zz); res }");
     }
 
+    @Test
+    public void testFileOpenRaw() {
+        Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip));
+        assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }");
+    }
+
     @Test
     public void testEncoding() throws IOException {
 
-- 
GitLab


From fd12f7651afe37e760eaba698181aa4e6cbcc730 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 12:05:14 +0100
Subject: [PATCH 080/402] Implemented support for anonymous text connections.

---
 .../builtin/base/ConnectionFunctions.java     | 29 ++++--
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../r/runtime/conn/TextConnections.java       | 90 +++++++++++--------
 .../truffle/r/test/ExpectedTestOutput.test    | 20 +++--
 .../r/test/library/base/TestConnections.java  |  9 +-
 5 files changed, 96 insertions(+), 55 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index dc54eaa2f7..f694df57b3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -65,6 +65,7 @@ import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.WriteDataNodeGen;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.HeadPhaseBuilder;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder;
 import com.oracle.truffle.r.runtime.RCompression;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -143,8 +144,16 @@ public abstract class ConnectionFunctions {
     }
 
     public static final class CastsHelper {
-        private static void description(Casts casts) {
-            casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
+        private static HeadPhaseBuilder<String> description(Casts casts) {
+            return descriptionInternal(casts.arg("description"));
+        }
+
+        private static HeadPhaseBuilder<String> descriptionNull(Casts casts) {
+            return descriptionInternal(casts.arg("description").allowNull());
+        }
+
+        private static HeadPhaseBuilder<String> descriptionInternal(InitialPhaseBuilder<Object> casts) {
+	    return casts.mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
         }
 
         private static HeadPhaseBuilder<String> open(Casts casts) {
@@ -334,9 +343,7 @@ public abstract class ConnectionFunctions {
 
         static {
             Casts casts = new Casts(TextConnection.class);
-            CastsHelper.description(casts);
-            // TODO how to have either a RNull or a String/RStringVector and have the latter coerced
-            // to a RAbstractStringVector to avoid the explicit handling in the specialization
+            CastsHelper.descriptionNull(casts);
             casts.arg("text").allowNull().mustBe(stringValue());
             CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
             casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
@@ -354,6 +361,7 @@ public abstract class ConnectionFunctions {
         }
 
         @Specialization
+<<<<<<< c511704667d1698f267ee975789ef5071f992da9
         @TruffleBoundary
         protected RAbstractIntVector textConnection(String description, RNull text, String open, REnvironment env, int encoding) {
             if (open.length() == 0 || open.equals("r")) {
@@ -361,6 +369,11 @@ public abstract class ConnectionFunctions {
             } else {
                 throw RError.nyi(RError.SHOW_CALLER, "textConnection: NULL");
             }
+=======
+        protected RAbstractIntVector textConnection(String description, @SuppressWarnings("unused") RNull text, String open,
+                        REnvironment env, int encoding) {
+            return this.textConnection(description, (RAbstractStringVector) null, open, env, encoding);
+>>>>>>> Implemented support for anonymous text connections.
         }
     }
 
@@ -374,10 +387,10 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object textConnection(int con) {
+        protected RAbstractStringVector textConnection(int con) {
             RConnection connection = RConnection.fromIndex(con);
             if (connection instanceof TextRConnection) {
-                return RDataFactory.createStringVector(((TextRConnection) connection).getValue(), RDataFactory.COMPLETE_VECTOR);
+                return ((TextRConnection) connection).getValue();
             } else {
                 throw error(Message.NOT_A_TEXT_CONNECTION);
             }
@@ -614,7 +627,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected Object readLines(int con, int n, boolean ok, boolean warn, @SuppressWarnings("unused") String encoding, boolean skipNul) {
-            // TODO implement all the arguments
+            // TODO Implement argument 'encoding'.
             try (RConnection openConn = RConnection.fromIndex(con).forceOpen("rt")) {
                 String[] lines = openConn.readLines(n, warn, skipNul);
                 if (n > 0 && lines.length < n && !ok) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index b0a536f50d..09e7edf54a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -373,6 +373,7 @@ public final class RError extends RuntimeException {
         ONLY_WRITE_BINARY_CONNECTION("can only write to a binary connection"),
         ONLY_WRITE_CHAR_OBJECTS("can only write character objects"),
         NOT_A_TEXT_CONNECTION("'con' is not a textConnection"),
+        NOT_AN_OUTPUT_TEXT_CONNECTION("'con' is not an output textConnection"),
         UNSEEKABLE_CONNECTION("'con' is not seekable"),
         MUST_BE_STRING_OR_CONNECTION("'%s' must be a character string or a connection"),
         MORE_CHARACTERS("writeChar: more characters requested than are in the string - will zero-pad"),
@@ -833,7 +834,7 @@ public final class RError extends RuntimeException {
         SEEK_OUTSITE_RAW_CONNECTION("attempt to seek outside the range of the raw connection"),
         VECTOR_IS_TOO_LARGE("vector is too large"),
         SEEK_NOT_RELEVANT_FOR_TEXT_CON("seek is not relevant for text connection"),
-        SEEK_NOT_ENABLED("'seek' not enabled for this connection"),
+        NOT_ENABLED_FOR_THIS_CONN("'%s' not enabled for this connection"),
         CANNOT_OPEN_FIFO("cannot open fifo '%s'"),
         UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'"),
         UNABLE_TO_RESOLVE("unable to resolve '%s'"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index 686a25a829..36a99e1181 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 public class TextConnections {
     public static class TextRConnection extends BaseRConnection {
         protected String description;
-        protected RAbstractStringVector object;
+        private final RAbstractStringVector object;
         protected REnvironment env;
 
         public TextRConnection(String description, RAbstractStringVector object, REnvironment env, String modeString) throws IOException {
@@ -65,10 +65,14 @@ public class TextConnections {
             DelegateRConnection delegate = null;
             switch (getOpenMode().abstractOpenMode) {
                 case Read:
-                    delegate = new TextReadRConnection(this);
+                    if (object != null) {
+                        delegate = new TextReadRConnection(this, object);
+                    } else {
+                        throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT, "text");
+                    }
                     break;
                 case Write:
-                    delegate = new TextWriteRConnection(this);
+                    delegate = new TextWriteRConnection(this, object);
                     break;
                 default:
                     throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + getOpenMode().modeString);
@@ -76,24 +80,25 @@ public class TextConnections {
             setDelegate(delegate);
         }
 
-        public String[] getValue() {
+        public RAbstractStringVector getValue() {
             return ((GetConnectionValue) theConnection).getValue();
         }
     }
 
     private interface GetConnectionValue {
-        String[] getValue();
+        RAbstractStringVector getValue();
     }
 
     private static class TextReadRConnection extends DelegateReadRConnection implements GetConnectionValue {
         private final String[] lines;
         private int index;
 
-        TextReadRConnection(TextRConnection base) {
+        TextReadRConnection(TextRConnection base, RAbstractStringVector object) {
             super(base);
+            assert object != null;
             StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < base.object.getLength(); i++) {
-                sb.append(base.object.getDataAt(i));
+            for (int i = 0; i < object.getLength(); i++) {
+                sb.append(object.getDataAt(i));
                 // vector elements are implicitly terminated with a newline
                 sb.append('\n');
             }
@@ -114,12 +119,6 @@ public class TextConnections {
             return result;
         }
 
-        @Override
-        public String[] getValue() {
-            // TODO refactor
-            throw RInternalError.shouldNotReachHere();
-        }
-
         @Override
         public void close() throws IOException {
             // nothing to do
@@ -134,30 +133,43 @@ public class TextConnections {
         public ReadableByteChannel getChannel() {
             throw RInternalError.shouldNotReachHere();
         }
+
+        @Override
+        public RAbstractStringVector getValue() {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_AN_OUTPUT_TEXT_CONNECTION);
+        }
     }
 
     private static class TextWriteRConnection extends DelegateWriteRConnection implements GetConnectionValue {
         private String incompleteLine;
         private RStringVector textVec;
         private String idName;
+        private RAbstractStringVector object;
+
+        /** Indicates if the connection is anonymous, i.e., not input object has been provided. */
+        private final boolean anonymous;
 
         private void initTextVec(RStringVector v, TextRConnection textBase) {
-            if (textBase.description.equals("NULL")) {
-                throw RError.nyi(null, "anonymous text output connection");
-            }
-            idName = textBase.object.getDataAt(0);
-            try {
-                textVec = v;
-                textBase.env.put(idName, textVec);
-            } catch (PutException ex) {
-                throw RError.error(RError.SHOW_CALLER2, ex);
+
+            if (anonymous) {
+                object = v;
+            } else {
+                idName = object.getDataAt(0);
+                try {
+                    textVec = v;
+                    textBase.env.put(idName, textVec);
+                } catch (PutException ex) {
+                    throw RError.error(RError.SHOW_CALLER2, ex);
+                }
+                // lock the binding
+                textBase.env.lockBinding(idName);
             }
-            // lock the binding
-            textBase.env.lockBinding(idName);
         }
 
-        protected TextWriteRConnection(BaseRConnection base) {
+        protected TextWriteRConnection(BaseRConnection base, RAbstractStringVector object) {
             super(base);
+            this.object = object;
+            this.anonymous = object == null;
             TextRConnection textBase = (TextRConnection) base;
             initTextVec(RDataFactory.createStringVector(0), textBase);
         }
@@ -177,7 +189,13 @@ public class TextConnections {
             }
             base.closed = true;
             TextRConnection textBase = (TextRConnection) base;
-            textBase.env.unlockBinding(idName);
+            unlockBinding(textBase);
+        }
+
+        private void unlockBinding(TextRConnection textBase) {
+            if (idName != null) {
+                textBase.env.unlockBinding(idName);
+            }
         }
 
         @Override
@@ -191,7 +209,7 @@ public class TextConnections {
             ArrayList<String> appendedLines = new ArrayList<>();
             while ((nlIndex = result.indexOf('\n', px)) >= 0) {
                 if (incompleteLine != null) {
-                    appendedLines.add(new StringBuffer(incompleteLine).append(result.substring(px, nlIndex)).toString());
+                    appendedLines.add(new StringBuilder(incompleteLine).append(result.substring(px, nlIndex)).toString());
                     incompleteLine = null;
                     base.setIncomplete(false);
                 } else {
@@ -219,7 +237,7 @@ public class TextConnections {
         }
 
         void appendData(String[] appendedData) {
-            String[] existingData = textVec.getDataWithoutCopying();
+            String[] existingData = textVec != null ? textVec.getDataWithoutCopying() : new String[0];
             String[] updateData = appendedData;
             if (existingData.length > 0) {
                 updateData = new String[existingData.length + appendedData.length];
@@ -227,11 +245,7 @@ public class TextConnections {
                 System.arraycopy(appendedData, 0, updateData, existingData.length, appendedData.length);
             }
             TextRConnection textBase = (TextRConnection) base;
-            /*
-             * N.B. This assumes one thread per RContext else another thread could be calling
-             * lockBinding
-             */
-            textBase.env.unlockBinding(idName);
+            unlockBinding(textBase);
             // TODO: is vector really complete?
             initTextVec(RDataFactory.createStringVector(updateData, RDataFactory.COMPLETE_VECTOR), textBase);
         }
@@ -262,17 +276,17 @@ public class TextConnections {
 
         @Override
         public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-            throw RError.nyi(null, "writeChar on text connection");
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.NOT_ENABLED_FOR_THIS_CONN, "write");
         }
 
         @Override
         public void writeBin(ByteBuffer buffer) throws IOException {
-            throw RError.nyi(null, "writeBin on text connection");
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.ONLY_WRITE_BINARY_CONNECTION);
         }
 
         @Override
-        public String[] getValue() {
-            throw RError.nyi(null, "textConnectionValue");
+        public RAbstractStringVector getValue() {
+            return object;
         }
 
         private class ConnectionOutputStream extends OutputStream {
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 11618c92fd..72f287c9e3 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
@@ -73944,6 +73944,10 @@ In readLines(zz, 2, warn = T, skipNul = F) :
 Error in seek.connection(zz, 5) :
   seek is not relevant for text connection
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testTextReadConnection#Output.IgnoreErrorContext#
+#textConnection(NULL, 'r')
+Error in textConnection(NULL, "r") : invalid 'text' argument
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testTextReadConnection#
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con) }
 [1] "1" "2" "3" "4"
@@ -73960,25 +73964,29 @@ Error in seek.connection(zz, 5) :
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
 [1] FALSE
 [1] "testtexttesttext2"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
+#{ c <- textConnection(NULL, 'w'); cat('testtext\n', file=c); textConnectionValue(c) }
+[1] "testtext"
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #{ con <- textConnection("tcval", open="w"); writeLines("a", con); tcval; close(con) }
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #{ con <- textConnection("tcval", open="w"); writeLines("a", con); writeLines(c("a", "b"), con, sep="."); tcval; close(con) }
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #{ con <- textConnection("tcval", open="w"); writeLines("a", con); writeLines(c("a", "b"), con, sep="."); writeLines("", con); tcval; close(con) }
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #{ con <- textConnection("tcval", open="w"); writeLines("a\nb", con); tcval; close(con) }
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection#
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection("buf", open="w", local=T); write.table(d, c); buf }
 [1] "\"c.1..2.\" \"c.10..20.\"" "\"1\" 1 10"
 [3] "\"2\" 2 20"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 54d2d01d6d..db6a8afd6f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -135,6 +135,8 @@ public class TestConnections extends TestRBase {
 
     @Test
     public void testTextReadConnection() {
+        assertEval(Output.IgnoreErrorContext, "textConnection(NULL, 'r')");
+
         assertEval("{ con <- textConnection(c(\"1\", \"2\", \"3\",\"4\")); readLines(con) }");
         assertEval("{ con <- textConnection(c(\"1\", \"2\", \"3\",\"4\")); readLines(con, 2) }");
         assertEval("{ con <- textConnection(c(\"1\", \"2\", \"3\",\"4\")); readLines(con, 2); readLines(con, 2) }");
@@ -165,13 +167,16 @@ public class TestConnections extends TestRBase {
     }
 
     @Test
-    public void testWriteConnection() {
+    public void testWriteTextConnection() {
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); tcval; close(con) }");
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); tcval; close(con) }");
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); writeLines(\"\", con); tcval; close(con) }");
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\\nb\", con); tcval; close(con) }");
         assertEval("c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\\n', file=c); isIncomplete(c); close(c); out");
 
+        // anonymous connection
+        assertEval("{ c <- textConnection(NULL, 'w'); cat('testtext\\n', file=c); textConnectionValue(c) }");
+
         assertEval("{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection(\"buf\", open=\"w\", local=T); write.table(d, c); buf }");
     }
 
@@ -211,7 +216,7 @@ public class TestConnections extends TestRBase {
         assertEval(Ignored.ImplementationError, "fin <- file(\"" + latin1File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
 
         // use inexisting charset
-        assertEval(Output.IgnoreErrorContext, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"___inexistingCharSet___\")");
+        assertEval("fin <- file(\"" + utf8File + "\", \"r\", encoding = \"___inexistingCharSet___\")");
 
         // write UTF-8 file
         final Path utf8File1 = TEMP_FILES.get(2);
-- 
GitLab


From 4966862e58d469f79ba075a9cc2f576a9c2461c0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 13:25:18 +0100
Subject: [PATCH 081/402] Added method 'ByteBuffer getChannel()' to interface
 RConnection and therefore exposing the unterlying channel for FastR internal
 use. Removed fall-through cases in FileConnections.

---
 .../r/runtime/conn/ConnectionSupport.java     | 80 ++++++++++++++++++-
 .../r/runtime/conn/DelegateRConnection.java   |  2 +-
 .../runtime/conn/DelegateReadRConnection.java |  4 -
 .../conn/DelegateReadWriteRConnection.java    |  6 +-
 .../conn/DelegateWriteRConnection.java        |  4 -
 .../r/runtime/conn/FifoConnections.java       |  3 +-
 .../r/runtime/conn/FileConnections.java       | 37 ++++-----
 .../r/runtime/conn/PipeConnections.java       | 12 +--
 .../truffle/r/runtime/conn/RConnection.java   | 14 +++-
 .../r/runtime/conn/TextConnections.java       | 10 +--
 .../r/runtime/conn/URLConnections.java        |  9 +--
 11 files changed, 117 insertions(+), 64 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 03e0047e39..8207080b17 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -29,6 +29,10 @@ import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
@@ -353,8 +357,6 @@ public class ConnectionSupport {
         }
     }
 
-    // TODO implement all open modes
-
     public static final class InvalidConnection implements RConnection {
 
         public static final InvalidConnection instance = new InvalidConnection();
@@ -367,11 +369,15 @@ public class ConnectionSupport {
         }
 
         @Override
+        @Deprecated
+        @SuppressWarnings("deprecation")
         public InputStream getInputStream() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
         @Override
+        @Deprecated
+        @SuppressWarnings("deprecation")
         public OutputStream getOutputStream() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
@@ -473,8 +479,12 @@ public class ConnectionSupport {
 
         @Override
         public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            // TODO Auto-generated method stub
-            return 0;
+            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
+        }
+
+        @Override
+        public ByteChannel getChannel() throws IOException {
+            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
     }
 
@@ -740,17 +750,25 @@ public class ConnectionSupport {
         }
 
         @Override
+        @SuppressWarnings("deprecation")
         public InputStream getInputStream() throws IOException {
             checkOpen();
             return theConnection.getInputStream();
         }
 
         @Override
+        @SuppressWarnings("deprecation")
         public OutputStream getOutputStream() throws IOException {
             checkOpen();
             return theConnection.getOutputStream();
         }
 
+        @Override
+        public ByteChannel getChannel() throws IOException {
+            checkOpen();
+            return theConnection.getChannel();
+        }
+
         @Override
         public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
             checkOpen();
@@ -1082,6 +1100,60 @@ public class ConnectionSupport {
         }
     }
 
+    public static ByteChannel newChannel(InputStream in) {
+        final ReadableByteChannel newChannel = Channels.newChannel(in);
+        return new ByteChannel() {
+
+            @Override
+            public int read(ByteBuffer dst) throws IOException {
+                return newChannel.read(dst);
+            }
+
+            @Override
+            public boolean isOpen() {
+                return newChannel.isOpen();
+            }
+
+            @Override
+            public void close() throws IOException {
+                newChannel.close();
+
+            }
+
+            @Override
+            public int write(ByteBuffer src) throws IOException {
+                throw new IOException("This channel is read-only.");
+            }
+        };
+    }
+
+    public static ByteChannel newChannel(OutputStream out) {
+        final WritableByteChannel newChannel = Channels.newChannel(out);
+        return new ByteChannel() {
+
+            @Override
+            public int read(ByteBuffer dst) throws IOException {
+                throw new IOException("This channel is write-only.");
+            }
+
+            @Override
+            public boolean isOpen() {
+                return newChannel.isOpen();
+            }
+
+            @Override
+            public void close() throws IOException {
+                newChannel.close();
+
+            }
+
+            @Override
+            public int write(ByteBuffer src) throws IOException {
+                return newChannel.write(src);
+            }
+        };
+    }
+
     /**
      * Converts between character set names of iconv and Java.
      *
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 7cefc299b9..91359d131f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -80,7 +80,7 @@ abstract class DelegateRConnection implements RConnection {
     @Override
     public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
         if (!isSeekable()) {
-            throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_ENABLED);
+            throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_ENABLED_FOR_THIS_CONN, "seek");
         }
         throw RInternalError.shouldNotReachHere("seek has not been implemented for this connection");
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index 1ffc079510..d317847217 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -27,7 +27,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -105,10 +104,7 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
         return false;
     }
 
-    public abstract ReadableByteChannel getChannel();
-
     @Override
-    @Deprecated
     public InputStream getInputStream() throws IOException {
         return Channels.newInputStream(getChannel());
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index bac95d6d9f..98f788574c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -26,7 +26,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
 import java.nio.channels.Channels;
 
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -84,11 +83,8 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
         throw RInternalError.shouldNotReachHere();
     }
 
-    public abstract ByteChannel getChannel();
-
     @Override
-    @Deprecated
-    public InputStream getInputStream() {
+    public InputStream getInputStream() throws IOException {
         return Channels.newInputStream(getChannel());
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index fd7d9a9c2e..4d4520d88c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -27,7 +27,6 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
-import java.nio.channels.WritableByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -97,10 +96,7 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
         getChannel().close();
     }
 
-    public abstract WritableByteChannel getChannel();
-
     @Override
-    @Deprecated
     public OutputStream getOutputStream() throws IOException {
         return Channels.newOutputStream(getChannel());
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index aec1223016..df63d1fc42 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -28,7 +28,6 @@ import java.io.RandomAccessFile;
 import java.lang.ProcessBuilder.Redirect;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.file.Files;
 import java.nio.file.OpenOption;
@@ -129,7 +128,7 @@ public class FifoConnections {
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 2c45f99e8f..79ff4fcc8c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -32,10 +32,7 @@ import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
-import java.nio.channels.Channels;
 import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
 import java.nio.file.OpenOption;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
@@ -154,18 +151,16 @@ public class FileConnections {
 
     private static DelegateRConnection createGZIPDelegateConnection(BasePathRConnection base) throws IOException {
 
-        boolean append = false;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
             case ReadBinary:
                 return new CompressedInputRConnection(base, new GZIPInputStream(new FileInputStream(base.path), GZIP_BUFFER_SIZE));
             case Append:
             case AppendBinary:
-                append = true;
-                // intentionally fall through !
+                return new CompressedOutputRConnection(base, new GZIPOutputStream(new FileOutputStream(base.path, true), GZIP_BUFFER_SIZE), true);
             case Write:
             case WriteBinary:
-                return new CompressedOutputRConnection(base, new GZIPOutputStream(new FileOutputStream(base.path, append), GZIP_BUFFER_SIZE), true);
+                return new CompressedOutputRConnection(base, new GZIPOutputStream(new FileOutputStream(base.path, false), GZIP_BUFFER_SIZE), true);
             default:
                 throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
         }
@@ -173,18 +168,16 @@ public class FileConnections {
 
     private static DelegateRConnection createXZDelegateConnection(BasePathRConnection base) throws IOException {
 
-        boolean append = false;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
             case ReadBinary:
                 return new CompressedInputRConnection(base, new XZInputStream(new FileInputStream(base.path)));
             case Append:
             case AppendBinary:
-                append = true;
-                // intentionally fall through !
+                return new CompressedOutputRConnection(base, new XZOutputStream(new FileOutputStream(base.path, true), new LZMA2Options(), XZ.CHECK_CRC32), false);
             case Write:
             case WriteBinary:
-                return new CompressedOutputRConnection(base, new XZOutputStream(new FileOutputStream(base.path, append), new LZMA2Options(), XZ.CHECK_CRC32), false);
+                return new CompressedOutputRConnection(base, new XZOutputStream(new FileOutputStream(base.path, false), new LZMA2Options(), XZ.CHECK_CRC32), false);
             default:
                 throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
         }
@@ -192,7 +185,6 @@ public class FileConnections {
 
     private static DelegateRConnection createBZIP2DelegateConnection(BasePathRConnection base) throws IOException {
 
-        boolean append = false;
         switch (base.getOpenMode().abstractOpenMode) {
             case Read:
             case ReadBinary:
@@ -200,11 +192,10 @@ public class FileConnections {
                 return new ByteStreamCompressedInputRConnection(base, new ByteArrayInputStream(bzipUdata));
             case Append:
             case AppendBinary:
-                append = true;
-                // intentionally fall through !
+                return new BZip2OutputRConnection(base, new ByteArrayOutputStream(), true);
             case Write:
             case WriteBinary:
-                return new BZip2OutputRConnection(base, new ByteArrayOutputStream(), append);
+                return new BZip2OutputRConnection(base, new ByteArrayOutputStream(), false);
             default:
                 throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
         }
@@ -270,7 +261,7 @@ public class FileConnections {
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
 
@@ -329,7 +320,7 @@ public class FileConnections {
         }
 
         @Override
-        public WritableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
 
@@ -446,15 +437,15 @@ public class FileConnections {
     }
 
     private static class CompressedInputRConnection extends DelegateReadRConnection {
-        private final ReadableByteChannel channel;
+        private final ByteChannel channel;
 
         protected CompressedInputRConnection(BasePathRConnection base, InputStream is) {
             super(base);
-            channel = Channels.newChannel(is);
+            channel = ConnectionSupport.newChannel(is);
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
 
@@ -471,14 +462,14 @@ public class FileConnections {
     }
 
     private static class CompressedOutputRConnection extends DelegateWriteRConnection {
-        protected WritableByteChannel channel;
+        protected ByteChannel channel;
         private final boolean seekable;
         private long seekPosition = 0L;
 
         protected CompressedOutputRConnection(BasePathRConnection base, OutputStream os, boolean seekable) {
             super(base);
             this.seekable = seekable;
-            this.channel = Channels.newChannel(os);
+            this.channel = ConnectionSupport.newChannel(os);
         }
 
         @Override
@@ -505,7 +496,7 @@ public class FileConnections {
         }
 
         @Override
-        public WritableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
index 10780d615a..8aa871b1b2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -93,16 +93,16 @@ public class PipeConnections {
     }
 
     static class PipeReadRConnection extends DelegateReadRConnection {
-        private final ReadableByteChannel channel;
+        private final ByteChannel channel;
 
         protected PipeReadRConnection(BaseRConnection base, String command) throws IOException {
             super(base);
             Process p = PipeConnections.executeAndJoin(command);
-            channel = Channels.newChannel(p.getInputStream());
+            channel = ConnectionSupport.newChannel(p.getInputStream());
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
 
@@ -113,16 +113,16 @@ public class PipeConnections {
     }
 
     private static class PipeWriteConnection extends DelegateWriteRConnection {
-        private final WritableByteChannel channel;
+        private final ByteChannel channel;
 
         PipeWriteConnection(BaseRConnection base, String command) throws IOException {
             super(base);
             Process p = PipeConnections.executeAndJoin(command);
-            channel = Channels.newChannel(p.getOutputStream());
+            channel = ConnectionSupport.newChannel(p.getOutputStream());
         }
 
         @Override
-        public WritableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return channel;
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index d2a4d2ac02..761e543d6c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -26,6 +26,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
@@ -42,17 +43,22 @@ public interface RConnection extends AutoCloseable {
     }
 
     /**
-     * Return the underlying input stream (for internal use). TODO Replace with a more principled
-     * solution.
+     * Return the underlying input stream (for internal use).
      */
     InputStream getInputStream() throws IOException;
 
     /**
-     * Return the underlying output stream (for internal use). TODO Replace with a more principled
-     * solution.
+     * Return the underlying output stream (for internal use).
      */
     OutputStream getOutputStream() throws IOException;
 
+    /**
+     * Return the underlying byte channel (for internal use).
+     *
+     * @throws IOException
+     */
+    ByteChannel getChannel() throws IOException;
+
     /**
      * Close the connection. The corresponds to the {@code R close} function.
      */
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index 36a99e1181..e789830946 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -25,9 +25,7 @@ package com.oracle.truffle.r.runtime.conn;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
+import java.nio.channels.ByteChannel;
 import java.util.ArrayList;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -130,7 +128,7 @@ public class TextConnections {
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             throw RInternalError.shouldNotReachHere();
         }
 
@@ -175,8 +173,8 @@ public class TextConnections {
         }
 
         @Override
-        public WritableByteChannel getChannel() {
-            return Channels.newChannel(new ConnectionOutputStream());
+        public ByteChannel getChannel() {
+            return ConnectionSupport.newChannel(new ConnectionOutputStream());
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
index 89aa21762c..9bd5460030 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/URLConnections.java
@@ -26,8 +26,7 @@ import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ByteChannel;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
@@ -65,16 +64,16 @@ public class URLConnections {
 
     private static class URLReadRConnection extends DelegateReadRConnection {
 
-        private final ReadableByteChannel rchannel;
+        private final ByteChannel rchannel;
 
         protected URLReadRConnection(URLRConnection base) throws MalformedURLException, IOException {
             super(base);
             URL url = new URL(base.urlString);
-            rchannel = Channels.newChannel(new BufferedInputStream(url.openStream()));
+            rchannel = ConnectionSupport.newChannel(new BufferedInputStream(url.openStream()));
         }
 
         @Override
-        public ReadableByteChannel getChannel() {
+        public ByteChannel getChannel() {
             return rchannel;
         }
 
-- 
GitLab


From 3cd76525a923aff2c73069381a16ba779f7fb4a2 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 15:18:33 +0100
Subject: [PATCH 082/402] Fixed bug in class DelegateReadWriteRConnection: Did
 not properly return the output stream for compatibility. Ignored a test using
 JUnit's Ignore annotation.

---
 .../truffle/r/runtime/conn/DelegateReadWriteRConnection.java | 5 ++---
 .../truffle/r/test/builtins/TestBuiltin_fifoConnection.java  | 2 ++
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 98f788574c..664f74183e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -28,7 +28,6 @@ import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
 
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -79,8 +78,8 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     }
 
     @Override
-    public OutputStream getOutputStream() {
-        throw RInternalError.shouldNotReachHere();
+    public OutputStream getOutputStream() throws IOException {
+        return Channels.newOutputStream(getChannel());
     }
 
     @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
index e7e8c7a475..106799d228 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
@@ -32,6 +32,7 @@ import java.util.List;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
@@ -57,6 +58,7 @@ public class TestBuiltin_fifoConnection extends TestBase {
     }
 
     @Test(timeout = 100)
+    @Ignore
     public void testFifoOpenNonBlocking() {
         Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
         assertEval(Ignored.ImplementationError, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
-- 
GitLab


From ba4462d50f427583dd719a8edc130e69084fb4ad Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 16:40:15 +0100
Subject: [PATCH 083/402] Fixed summary description for files when opening temp
 files. Refactored unit tests to not use temp dir (does not work reliably).

---
 .../builtin/base/ConnectionFunctions.java     |   8 +-
 .../r/runtime/conn/ConnectionSupport.java     |  28 ++--
 .../r/runtime/conn/FileConnections.java       |   6 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 150 +++++++++---------
 .../r/test/library/base/TestConnections.java  |  65 +-------
 5 files changed, 101 insertions(+), 156 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index f694df57b3..78081fae25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -256,7 +256,7 @@ public abstract class ConnectionFunctions {
                 }
             }
             try {
-                return new FileRConnection(path, open, blocking, encoding, raw).asVector();
+                return new FileRConnection(description, path, open, blocking, encoding, raw).asVector();
             } catch (IOException ex) {
                 warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
@@ -289,11 +289,11 @@ public abstract class ConnectionFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector zzFile(RAbstractStringVector description, String open, String encoding, int compression) {
+        protected RAbstractIntVector zzFile(String description, String open, String encoding, int compression) {
             try {
-                return new CompressedRConnection(description.getDataAt(0), open, cType, encoding, compression).asVector();
+                return new CompressedRConnection(description, open, cType, encoding, compression).asVector();
             } catch (IOException ex) {
-                throw reportError(description.getDataAt(0), ex);
+                throw reportError(description, ex);
             } catch (IllegalCharsetNameException ex) {
                 throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 8207080b17..8609c429b7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -369,15 +369,11 @@ public class ConnectionSupport {
         }
 
         @Override
-        @Deprecated
-        @SuppressWarnings("deprecation")
         public InputStream getInputStream() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
         @Override
-        @Deprecated
-        @SuppressWarnings("deprecation")
         public OutputStream getOutputStream() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
@@ -750,14 +746,12 @@ public class ConnectionSupport {
         }
 
         @Override
-        @SuppressWarnings("deprecation")
         public InputStream getInputStream() throws IOException {
             checkOpen();
             return theConnection.getInputStream();
         }
 
         @Override
-        @SuppressWarnings("deprecation")
         public OutputStream getOutputStream() throws IOException {
             checkOpen();
             return theConnection.getOutputStream();
@@ -1074,29 +1068,37 @@ public class ConnectionSupport {
     }
 
     abstract static class BasePathRConnection extends BaseRConnection {
+        /** The path of the actual file to open. */
         protected final String path;
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, String encoding) throws IOException {
-            this(path, connectionClass, modeString, AbstractOpenMode.Read, encoding);
+        /** The description used in the call (required summary output). */
+        protected final String description;
+
+        protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, String encoding) throws IOException {
+            this(description, path, connectionClass, modeString, AbstractOpenMode.Read, encoding);
         }
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, boolean blocking, String encoding) throws IOException {
-            this(path, connectionClass, modeString, AbstractOpenMode.Read, blocking, encoding);
+        protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, boolean blocking, String encoding) throws IOException {
+            this(description, path, connectionClass, modeString, AbstractOpenMode.Read, blocking, encoding);
         }
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, String encoding) throws IOException {
+        protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, String encoding) throws IOException {
             super(connectionClass, modeString, defaultLazyOpenMode, encoding);
             this.path = Utils.tildeExpand(path);
+            this.description = description;
         }
 
-        protected BasePathRConnection(String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, boolean blocking, String encoding) throws IOException {
+        protected BasePathRConnection(String description, String path, ConnectionClass connectionClass, String modeString, AbstractOpenMode defaultLazyOpenMode, boolean blocking, String encoding)
+                        throws IOException {
             super(connectionClass, modeString, defaultLazyOpenMode, blocking, encoding);
             this.path = Utils.tildeExpand(path);
+            this.description = description;
         }
 
         @Override
         public String getSummaryDescription() {
-            return path;
+            // Use 'description' and not 'path' since this may be different, e.g., on temp files.
+            return description;
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 79ff4fcc8c..a72e817ec1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -66,8 +66,8 @@ public class FileConnections {
     public static class FileRConnection extends BasePathRConnection {
         private final boolean raw;
 
-        public FileRConnection(String path, String modeString, boolean blocking, String encoding, boolean raw) throws IOException {
-            super(checkTemp(path), ConnectionClass.File, modeString, blocking, encoding);
+        public FileRConnection(String description, String path, String modeString, boolean blocking, String encoding, boolean raw) throws IOException {
+            super(description, checkTemp(path), ConnectionClass.File, modeString, blocking, encoding);
             this.raw = raw;
             openNonLazyConnection();
         }
@@ -98,7 +98,7 @@ public class FileConnections {
         @SuppressWarnings("unused") private final int compression; // TODO
 
         public CompressedRConnection(String path, String modeString, Type cType, String encoding, int compression) throws IOException {
-            super(path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary, encoding);
+            super(path, path, mapConnectionClass(cType), modeString, AbstractOpenMode.ReadBinary, encoding);
             this.cType = cType;
             this.compression = compression;
             openNonLazyConnection();
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 72f287c9e3..ff293ba0e3 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
@@ -21084,13 +21084,6 @@ In addition: Warning message:
 In fifo("/tmp/pipe3408688236", "r", blocking = TRUE) :
   cannot open fifo '/tmp/pipe3408688236'
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenNonBlocking#Ignored.ImplementationError#
-#{ zz <- fifo("/tmp/pipe3408688236", "r"); close(zz); }
-Error in fifo("/tmp/pipe3408688236", "r") : cannot open the connection
-In addition: Warning message:
-In fifo("/tmp/pipe3408688236", "r") :
-  cannot open fifo '/tmp/pipe3408688236'
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_fileaccess.testfileaccess1#
 #argv <- list(character(0), 0); .Internal(file.access(argv[[1]], argv[[2]]))
 integer(0)
@@ -73533,48 +73526,47 @@ Read 4 items
 Summary of Residuals:
 
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
-#fin <- file("/tmp/file3408688236", "r", encoding = "UTF-8"); lines <- readLines(fin, 1); close(fin); lines
-[1] "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß."
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Output.IgnoreErrorContext#
-#fin <- file("/tmp/file3408688236", "r", encoding = "___inexistingCharSet___")
-Error in file("/tmp/file3408688236", "r", encoding = "___inexistingCharSet___") :
+##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
+#fin <- file('', "w+", encoding = "___inexistingCharSet___")
+Error in file("", "w+", encoding = "___inexistingCharSet___") :
   unsupported conversion from '___inexistingCharSet___' to ''
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
-#fin <- file("/tmp/file3408688236", "r", encoding = "latin1"); lines <- readLines(fin, 1); close(fin); lines
-[1] "This is a sentence using german Umlauts like ö, ä, ü, Ã\u0096, Ã\u0084, Ã\u009c but also Ã\u009f."
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.Unknown#
-#fin <- file("/tmp/file4039819292", "r"); lines <- readLines(fin, 1, encoding = "UTF-8"); close(fin); lines
-[1] "This is a sentence using german Umlauts like \xf6, \xe4, \xfc, \xd6, \xc4, \xdc but also \xdf."
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
-#fin <- file("/tmp/file4039819292", "r", encoding = "UTF-8"); lines <- readLines(fin, 1); close(fin); lines
-Warning messages:
-1: In readLines(fin, 1) :
-  invalid input found on input connection '/tmp/file4039819292'
-2: In readLines(fin, 1) :
-  incomplete final line found on '/tmp/file4039819292'
-[1] "This is a sentence using german Umlauts like "
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#Ignored.ImplementationError#
-#fin <- file("/tmp/file4039819292", "r", encoding = "latin1"); lines <- readLines(fin, 1); close(fin); lines
-[1] "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß."
-
 ##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
-#{ wline <- "Hellö"; fin <- file("/tmp/file9823674682", "w+", encoding = "UTF-8"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }
+#{ wline <- 'Hellö'; fin <- file('', 'w+', encoding = 'UTF-8'); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }
 [1] "Hellö" "Hellö" "TRUE"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileOpenRaw#
-#{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }
+#{ zz <- file("gzipped_____5137528280012599068___.gz", "r", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }
 Error in readBin(zz, raw(), 4) : can only read from a binary connection
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary#
-#{ zz <- file("/tmp/gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res }
+#zz <- file('', 'w+'); summary(zz); close(zz)
+$description
+[1] ""
+
+$class
+[1] "file"
+
+$mode
+[1] "w+"
+
+$text
+[1] "text"
+
+$opened
+[1] "opened"
+
+$`can read`
+[1] "yes"
+
+$`can write`
+[1] "yes"
+
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary#
+#{ zz <- file("gzipped_____5137528280012599068___.gz", "r"); res <- summary(zz); close(zz); res }
 $description
-[1] "/tmp/gzipped_____5137528280012599068___.gz"
+[1] "gzipped_____5137528280012599068___.gz"
 
 $class
 [1] "gzfile"
@@ -73764,175 +73756,175 @@ In writeChar(x, zz, nc, eos = NULL) :
 [1] c3 a4 c3 b6 c3 bc c3 9f 00
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd"
 Warning messages:
 1: In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 2: In readLines(zz, 2, warn = T, skipNul = F) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 Warning messages:
 1: In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 2: In readLines(zz, 2, warn = T, skipNul = F) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=F); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd"
 Warning messages:
 1: In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 2: In readLines(zz, 2, warn = T, skipNul = F) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 Warning messages:
 1: In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 2: In readLines(zz, 2, warn = T, skipNul = F) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = T) :
-  incomplete final line found on '/tmp/file3762346723'
+  incomplete final line found on ''
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=F, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=F); close(zz); res }
 [1] "abcd" "ABC"
 Warning message:
 In readLines(zz, 2, warn = T, skipNul = F) :
   line 1 appears to contain an embedded nul
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testReadLines#Output.MayIgnoreWarningContext#
-#{ fn <- "/tmp/file3762346723"; zz <- file(fn,"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); unlink(fn); res }
+#{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index db6a8afd6f..4377f27eab 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -22,21 +22,12 @@
  */
 package com.oracle.truffle.r.test.library.base;
 
-import static java.nio.file.StandardOpenOption.CREATE;
-import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
-import static java.nio.file.StandardOpenOption.WRITE;
-
 import java.io.IOException;
 import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.zip.GZIPOutputStream;
 
 import org.junit.AfterClass;
@@ -63,7 +54,6 @@ public class TestConnections extends TestRBase {
 
     private static TestDir testDir;
     private static Path tempFileGzip;
-    private static final List<Path> TEMP_FILES = new ArrayList<>();
 
     @Override
     protected String getTestDir() {
@@ -74,19 +64,11 @@ public class TestConnections extends TestRBase {
     public static void setup() throws IOException {
         testDir = new TestDir();
 
-        Path path = Paths.get(System.getProperty("java.io.tmpdir"));
-
         // create a gzipped file
-        tempFileGzip = path.resolve("gzipped_____5137528280012599068___.gz");
+        tempFileGzip = Paths.get("gzipped_____5137528280012599068___.gz");
         OutputStream gzos = new GZIPOutputStream(Files.newOutputStream(tempFileGzip, StandardOpenOption.WRITE, StandardOpenOption.CREATE));
         gzos.write("Hello, World!".getBytes());
         gzos.close();
-
-        TEMP_FILES.add(path.resolve("file3408688236"));
-        TEMP_FILES.add(path.resolve("file4039819292"));
-        TEMP_FILES.add(path.resolve("file9823674682"));
-        TEMP_FILES.add(path.resolve("file3762346723"));
-        TEMP_FILES.add(path.resolve("file8723674332"));
     }
 
     @AfterClass
@@ -95,9 +77,6 @@ public class TestConnections extends TestRBase {
             System.err.println("WARNING: error deleting : " + testDir.testDirPath);
         }
         deleteFile(tempFileGzip);
-        for (Path p : TEMP_FILES) {
-            deleteFile(p);
-        }
     }
 
     private static void deleteFile(Path p) {
@@ -188,9 +167,10 @@ public class TestConnections extends TestRBase {
 
     @Test
     public void testFileSummary() {
-
         Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip));
         assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\"); res <- summary(zz); close(zz); res }");
+
+        assertEval("zz <- file('', 'w+'); summary(zz); close(zz)");
     }
 
     @Test
@@ -200,34 +180,16 @@ public class TestConnections extends TestRBase {
     }
 
     @Test
-    public void testEncoding() throws IOException {
-
-        // read from UTF-8 file
-        final Path utf8File = TEMP_FILES.get(0);
-        writeEncodedString(utf8File, "utf8", "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß.\n");
-        assertEval(Ignored.ImplementationError, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
-        assertEval(Ignored.ImplementationError, "fin <- file(\"" + utf8File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
-
-        // read from ISO-8859-1 (aka Latin1) file
-        final Path latin1File = TEMP_FILES.get(1);
-        writeEncodedString(latin1File, "ISO-8859-1", "This is a sentence using german Umlauts like ö, ä, ü, Ö, Ä, Ü but also ß.\n");
-        assertEval(Ignored.Unknown, "fin <- file(\"" + latin1File + "\", \"r\"); lines <- readLines(fin, 1, encoding = \"UTF-8\"); close(fin); lines");
-        assertEval(Ignored.ImplementationError, "fin <- file(\"" + latin1File + "\", \"r\", encoding = \"latin1\"); lines <- readLines(fin, 1); close(fin); lines");
-        assertEval(Ignored.ImplementationError, "fin <- file(\"" + latin1File + "\", \"r\", encoding = \"UTF-8\"); lines <- readLines(fin, 1); close(fin); lines");
-
+    public void testEncoding() {
         // use inexisting charset
-        assertEval("fin <- file(\"" + utf8File + "\", \"r\", encoding = \"___inexistingCharSet___\")");
+        assertEval("fin <- file('', \"w+\", encoding = \"___inexistingCharSet___\")");
 
         // write UTF-8 file
-        final Path utf8File1 = TEMP_FILES.get(2);
-        assertEval("{ wline <- \"Hellö\"; fin <- file(\"" + utf8File1 +
-                        "\", \"w+\", encoding = \"UTF-8\"); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }");
+        assertEval("{ wline <- 'Hellö'; fin <- file('', 'w+', encoding = 'UTF-8'); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }");
     }
 
     @Test
     public void testReadLines() {
-        final Path tmpFile = TEMP_FILES.get(3);
-
         // one line containing '\0'
         final String lineWithNul = "c(97,98,99,100,0,101,10)";
 
@@ -240,8 +202,8 @@ public class TestConnections extends TestRBase {
         // two lines, first containing '\0', second line incomplete
         final String twoLinesOneNulIncomp = "c(97,98,99,100,0,101,10,65,66,67)";
 
-        assertEval(Output.MayIgnoreWarningContext, TestBase.template("{ fn <- \"" + tmpFile +
-                        "\"; zz <- file(fn,\"w+b\", blocking=%0); writeBin(as.raw(%1), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=%2, skipNul=%3); close(zz); unlink(fn); res }",
+        assertEval(Output.MayIgnoreWarningContext, TestBase.template(
+                        "{ zz <- file('',\"w+b\", blocking=%0); writeBin(as.raw(%1), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=%2, skipNul=%3); close(zz); res }",
                         LVAL, arr(lineWithNul, twoLinesOneNul, lineWithNulIncomp, twoLinesOneNulIncomp), LVAL, LVAL));
     }
 
@@ -286,15 +248,4 @@ public class TestConnections extends TestRBase {
     private static String[] arr(String... args) {
         return args;
     }
-
-    /**
-     * Writes a string using the specified charset to the provided file. The file is created and
-     * truncated.
-     */
-    private static void writeEncodedString(Path p, String enc, String s) throws IOException {
-        ByteBuffer encode = Charset.forName(enc).encode(s);
-        FileChannel open = FileChannel.open(p, CREATE, WRITE, TRUNCATE_EXISTING);
-        open.write(encode);
-        open.close();
-    }
 }
-- 
GitLab


From a5b5d37df87261774053e53388013c0d84d3a024 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 17:43:01 +0100
Subject: [PATCH 084/402] Removed unnecessary implementation of deleting a temp
 file since there was already support for this.

---
 .../truffle/r/test/library/base/TestConnections.java   | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 4377f27eab..01c0bebf9f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -76,15 +76,7 @@ public class TestConnections extends TestRBase {
         if (!deleteDir(testDir.testDirPath)) {
             System.err.println("WARNING: error deleting : " + testDir.testDirPath);
         }
-        deleteFile(tempFileGzip);
-    }
-
-    private static void deleteFile(Path p) {
-        try {
-            Files.delete(p);
-        } catch (IOException e) {
-            // ignore
-        }
+        deleteDir(tempFileGzip);
     }
 
     @Test
-- 
GitLab


From 14b00d34f8b9cd9be44a12036b26cdb0a519390f Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Feb 2017 17:43:56 +0100
Subject: [PATCH 085/402] Using the more specific type BaseRConnection where
 appropriate.

---
 .../truffle/r/nodes/builtin/base/ConnectionFunctions.java | 8 ++++----
 .../oracle/truffle/r/runtime/conn/ConnectionSupport.java  | 2 +-
 .../com/oracle/truffle/r/runtime/conn/StdConnections.java | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 78081fae25..84eb967ab7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -494,7 +494,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected Object textConnection(int con) {
-            RConnection connection = RConnection.fromIndex(con);
+            BaseRConnection connection = RConnection.fromIndex(con);
             if (connection instanceof RawRConnection) {
                 return RDataFactory.createRawVector(((RawRConnection) connection).getValue());
             } else {
@@ -571,7 +571,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected RLogicalVector isOpen(int con, int rw) {
-            RConnection baseCon = getBaseConnection(RConnection.fromIndex(con));
+            BaseRConnection baseCon = getBaseConnection(RConnection.fromIndex(con));
             boolean result = baseCon.isOpen();
             switch (rw) {
                 case 0:
@@ -601,7 +601,7 @@ public abstract class ConnectionFunctions {
         @Specialization
         @TruffleBoundary
         protected Object close(int con, @SuppressWarnings("unused") String type) {
-            RConnection connection = RConnection.fromIndex(con);
+            BaseRConnection connection = RConnection.fromIndex(con);
             try {
                 connection.closeAndDestroy();
             } catch (IOException ex) {
@@ -750,7 +750,7 @@ public abstract class ConnectionFunctions {
         @Specialization(guards = "!ncharsEmpty(nchars)")
         @TruffleBoundary
         protected RStringVector readChar(int con, RAbstractIntVector nchars, boolean useBytes) {
-            try (RConnection openConn = RConnection.fromIndex(con).forceOpen("rb")) {
+            try (BaseRConnection openConn = RConnection.fromIndex(con).forceOpen("rb")) {
                 String[] data = new String[nchars.getLength()];
                 for (int i = 0; i < data.length; i++) {
                     data[i] = openConn.readChar(nchars.getDataAt(i), useBytes);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 8609c429b7..b772be488a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -704,7 +704,7 @@ public class ConnectionSupport {
         }
 
         @Override
-        public RConnection forceOpen(String modeString) throws IOException {
+        public BaseRConnection forceOpen(String modeString) throws IOException {
             if (closed) {
                 throw new IOException(RError.Message.INVALID_CONNECTION.message);
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 58699a574c..6150dc902b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -161,7 +161,7 @@ public class StdConnections {
         }
 
         @Override
-        public RConnection forceOpen(String modeString) {
+        public BaseRConnection forceOpen(String modeString) {
             return this;
         }
 
-- 
GitLab


From abbc94d159eaeb1e17b7676ec021a8e59db81183 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 1 Mar 2017 13:53:24 +0100
Subject: [PATCH 086/402] Fixed serious bug during decoding: Did not properly
 use the decoder when reading single 'elements' from a connection using method
 'getc'. An element is either a character or a byte depending on the
 connection mode text or binary, respectively. Now, a stream decoder is
 created on demand and used for any subsequent character-based reading. As in
 GnuR, mixing binary- and text-based reading and writing leads to undefined
 behavior since the decoder may already have consumed some bytes.

---
 .../r/runtime/conn/ConnectionSupport.java     |  2 +-
 .../r/runtime/conn/DelegateRConnection.java   | 82 +++++++++++++------
 .../runtime/conn/DelegateReadRConnection.java | 18 ++--
 .../conn/DelegateReadWriteRConnection.java    |  6 +-
 .../truffle/r/runtime/conn/RConnection.java   | 15 +++-
 5 files changed, 90 insertions(+), 33 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index b772be488a..3e0941dce2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -1061,7 +1061,7 @@ public class ConnectionSupport {
         if (conn instanceof BaseRConnection) {
             return (BaseRConnection) conn;
         } else if (conn instanceof DelegateReadRConnection) {
-            return ((DelegateReadRConnection) conn).base;
+            return ((DelegateRConnection) conn).base;
         } else {
             throw RInternalError.shouldNotReachHere();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 91359d131f..0139c2e9a7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -30,6 +30,8 @@ import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
 import java.util.ArrayList;
 import java.util.Objects;
 
@@ -52,6 +54,7 @@ import sun.nio.cs.StreamDecoder;
  */
 abstract class DelegateRConnection implements RConnection {
     protected final BaseRConnection base;
+    private StreamDecoder decoder;
 
     DelegateRConnection(BaseRConnection base) {
         this.base = Objects.requireNonNull(base);
@@ -275,34 +278,54 @@ abstract class DelegateRConnection implements RConnection {
         return new String(chars, 0, j);
     }
 
-    public static String readCharHelper(int nchars, ReadableByteChannel channel, boolean useBytes) throws IOException {
-        if (useBytes) {
-            ByteBuffer buf = ByteBuffer.allocate(nchars);
-            channel.read(buf);
-            int j = 0;
-            for (; j < buf.position(); j++) {
-                // strings end at 0
-                if (buf.get(j) == 0) {
-                    break;
-                }
+    /**
+     * Reads a specified number of single-byte characters.<br>
+     * <p>
+     * This method is meant to be used if R's function {@code readChar} is called with parameter
+     * {@code useBytes=TRUE}.
+     * </p>
+     *
+     * @param nchars The number of single-byte characters to read.
+     * @param channel The channel to read from (must not be {@code null}).
+     * @throws IOException
+     */
+    public static String readCharHelper(int nchars, ReadableByteChannel channel) throws IOException {
+        ByteBuffer buf = ByteBuffer.allocate(nchars);
+        channel.read(buf);
+        int j = 0;
+        for (; j < buf.position(); j++) {
+            // strings end at 0
+            if (buf.get(j) == 0) {
+                break;
             }
+        }
 
-            return new String(buf.array(), 0, j);
-        } else {
-            // we need a decoder
-            StreamDecoder decoder = StreamDecoder.forDecoder(channel, Charset.defaultCharset().newDecoder(), nchars);
-            char[] chars = new char[nchars];
-            decoder.read(chars);
-            int j = 0;
-            for (; j < chars.length; j++) {
-                // strings end at 0
-                if (chars[j] == 0) {
-                    break;
-                }
-            }
+        return new String(buf.array(), 0, j);
+    }
 
-            return new String(chars, 0, j);
+    /**
+     * Reads a specified number of characters (not bytes).<br>
+     * <p>
+     * This method is meant to be used if R's function {@code readChar} is called with parameter
+     * {@code useBytes=FALSE}.
+     * </p>
+     *
+     * @param nchars The number of characters to read.
+     * @param decoder The stream decoder to use (must not be {@code null}).
+     * @throws IOException
+     */
+    public static String readCharHelper(int nchars, StreamDecoder decoder) throws IOException {
+        // we need a decoder
+        char[] chars = new char[nchars];
+        decoder.read(chars);
+        int j = 0;
+        for (; j < chars.length; j++) {
+            // strings end at 0
+            if (chars[j] == 0) {
+                break;
+            }
         }
+        return new String(chars, 0, j);
     }
 
     /**
@@ -355,4 +378,15 @@ abstract class DelegateRConnection implements RConnection {
     public void pushBack(RAbstractStringVector lines, boolean addNewLine) {
         throw RInternalError.shouldNotReachHere();
     }
+
+    /**
+     * Creates the stream decoder on demand and returns it.
+     */
+    protected StreamDecoder getDecoder() throws IOException {
+        if (decoder == null) {
+            CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
+            decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, -1);
+        }
+        return decoder;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index d317847217..70a2bac8df 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -63,15 +63,23 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
 
     @Override
     public int getc() throws IOException {
-        tmp.clear();
-        int nread = getChannel().read(tmp);
-        tmp.rewind();
-        return nread > 0 ? tmp.get() : -1;
+        if (isTextMode()) {
+            return getDecoder().read();
+        } else {
+            tmp.clear();
+            int nread = getChannel().read(tmp);
+            tmp.rewind();
+            return nread > 0 ? tmp.get() : -1;
+        }
     }
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
-        return DelegateRConnection.readCharHelper(nchars, getChannel(), useBytes);
+        if (useBytes) {
+            return DelegateRConnection.readCharHelper(nchars, getChannel());
+        } else {
+            return DelegateRConnection.readCharHelper(nchars, getDecoder());
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 664f74183e..011cf49d1b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -59,7 +59,11 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
-        return DelegateRConnection.readCharHelper(nchars, getChannel(), useBytes);
+        if (useBytes) {
+            return DelegateRConnection.readCharHelper(nchars, getChannel());
+        } else {
+            return DelegateRConnection.readCharHelper(nchars, getDecoder());
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 761e543d6c..341d12e3ba 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -43,12 +43,23 @@ public interface RConnection extends AutoCloseable {
     }
 
     /**
-     * Return the underlying input stream (for internal use).
+     * Return the underlying input stream (for internal use).<br>
+     * <p>
+     * <b>NOTE:</b> The connection may do some caching internally! Therefore, the behavior is
+     * undefined if you mix using the input stream directly and using the read methods of the
+     * connection.
+     * </p>
+     *
      */
     InputStream getInputStream() throws IOException;
 
     /**
-     * Return the underlying output stream (for internal use).
+     * Return the underlying output stream (for internal use).<br>
+     * <p>
+     * <b>NOTE:</b> The connection may do some caching internally! Therefore, the behavior is
+     * undefined if you mix using the output stream directly and using the write methods of the
+     * connection.
+     * </p>
      */
     OutputStream getOutputStream() throws IOException;
 
-- 
GitLab


From 067cde283f72d89446c723b8fad630e07f65bd49 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 1 Mar 2017 14:14:45 +0100
Subject: [PATCH 087/402] Fixed a small issue introduced during merging.
 Refined a test case.

---
 .../builtin/base/ConnectionFunctions.java     |  19 +---
 .../truffle/r/test/ExpectedTestOutput.test    | 104 +-----------------
 .../r/test/library/base/TestConnections.java  |   3 +-
 3 files changed, 9 insertions(+), 117 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 84eb967ab7..30aa8c4efb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -153,7 +153,7 @@ public abstract class ConnectionFunctions {
         }
 
         private static HeadPhaseBuilder<String> descriptionInternal(InitialPhaseBuilder<Object> casts) {
-	    return casts.mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
+            return casts.mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
         }
 
         private static HeadPhaseBuilder<String> open(Casts casts) {
@@ -262,7 +262,7 @@ public abstract class ConnectionFunctions {
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
                 throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
-            } 
+            }
         }
     }
 
@@ -361,19 +361,8 @@ public abstract class ConnectionFunctions {
         }
 
         @Specialization
-<<<<<<< c511704667d1698f267ee975789ef5071f992da9
-        @TruffleBoundary
-        protected RAbstractIntVector textConnection(String description, RNull text, String open, REnvironment env, int encoding) {
-            if (open.length() == 0 || open.equals("r")) {
-                throw error(RError.Message.INVALID_ARGUMENT, "text");
-            } else {
-                throw RError.nyi(RError.SHOW_CALLER, "textConnection: NULL");
-            }
-=======
-        protected RAbstractIntVector textConnection(String description, @SuppressWarnings("unused") RNull text, String open,
-                        REnvironment env, int encoding) {
-            return this.textConnection(description, (RAbstractStringVector) null, open, env, encoding);
->>>>>>> Implemented support for anonymous text connections.
+        protected RAbstractIntVector textConnection(String description, @SuppressWarnings("unused") RNull text, String open, REnvironment env, int encoding) {
+            return textConnection(description, (RAbstractStringVector) null, open, env, encoding);
         }
     }
 
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 ff293ba0e3..88bd852e6c 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
@@ -27891,7 +27891,7 @@ Error in lengths(quote(a)) : 'x' must be a list or atomic vector
 #{ x <- 1 ; levels(x)<-4.5; levels(x);}
 [1] 4.5
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_levels.testLevels#Output.MayIgnoreErrorContext#
 #{ x <- 1 ; levels(x)<-NULL; levels(notx)}
 Error in levels(notx) : object 'notx' not found
 
@@ -42190,102 +42190,6 @@ numeric(0)
 #argv <- structure(list(length = 0), .Names = 'length');do.call('raw', argv)
 raw(0)
 
-<<<<<<< ce7e735b186fb58a156b4f2a5bd1d131fdb3c69d
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#Ignored.Unknown#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R") }
-[1] "abc"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R") }
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R") }
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R") }
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") }
-[1] "TITLE extra line" "2 3 5 7"          ""                 "11 13 17"
-[5] "123"              "abc"              "123"              "abc def"
-Warning message:
-In readLines("test1") : incomplete final line found on 'test1'
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R") }
-Read 4 items
-Read 4 items
-
-Summary of Residuals:
-
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
-#{ rc <- rawConnection(raw(0), "a+"); close(rc); write(charToRaw("A"), rc) }
-Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
-  invalid connection
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res }
- [1] 48 65 6c 6c 6f 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34
-[26] 0a
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
-[1] "Hello2c 20 57 6f 72\n6c 64\n"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
- [1] 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 00
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadAppendText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "a+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
-[1] "Hello, World"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
-#{ rc <- rawConnection(raw(0), "r+"); close(rc); write(charToRaw("A"), rc) }
-Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
-  invalid connection
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawConnectionValue(rc); close(rc); res }
- [1] 32 63 20 32 30 20 35 37 20 36 66 20 37 32 0a 36 63 20 36 34 0a
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); write(charToRaw(", World"), rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
-[1] "2c 20 57 6f 72\n6c 64\n"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
-[1] 2c 20 57 6f 72 6c 64 00
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testReadWriteText#
-#{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
-[1] ", World"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteBinary#Ignored.Unknown#
-#{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }
- [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteBinary#
-#{ zz <- rawConnection(raw(0), "wb"); x <- c("a", "this will be truncated", "abc"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = "\r\n"); res <- rawConnectionValue(zz); close(zz); res }
- [1] 61 00 00 74 68 69 73 20 77 69 6c 6c 20 61 62 63 61 0d 0a 00 74 68 69 73 20
-[26] 77 69 6c 6c 20 62 65 20 74 72 75 6e 63 61 74 65 64 0d 0a 00 61 62 63 0d 0a
-[51] 00
-Warning message:
-In writeChar(x, zz, nc, eos = NULL) :
-  writeChar: more characters requested than are in the string - will zero-pad
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteText#
-#{ rc <- rawConnection(raw(0), "w"); writeChar("Hello", rc); writeChar(", World", rc); res <- rawConnectionValue(rc); close(rc); res }
- [1] 48 65 6c 6c 6f 00 2c 20 57 6f 72 6c 64 00
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rawConnection.testWriteText#
-#{ s <- "äöüß"; rc <- rawConnection(raw(0), "w"); writeChar(s, rc); rawConnectionValue(rc) }
-[1] c3 a4 c3 b6 c3 bc c3 9f 00
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rawShift.testrawShift1#
 #argv <- structure(list(x = as.raw(c(0, 1, 32, 127, 128, 255, 123)), n = -1.1), .Names = c('x', 'n'));do.call('rawShift', argv)
 [1] 00 00 10 3f 40 7f 3d
@@ -73738,7 +73642,7 @@ Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
 #{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }
  [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#
 #{ zz <- rawConnection(raw(0), "wb"); x <- c("a", "this will be truncated", "abc"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = "\r\n"); res <- rawConnectionValue(zz); close(zz); res }
  [1] 61 00 00 74 68 69 73 20 77 69 6c 6c 20 61 62 63 61 0d 0a 00 74 68 69 73 20
 [26] 77 69 6c 6c 20 62 65 20 74 72 75 6e 63 61 74 65 64 0d 0a 00 61 62 63 0d 0a
@@ -80019,7 +79923,7 @@ $class
 #{ x<-as.raw(c(7L,42L)); y<-as.data.frame(x, row.names=NULL, nm="x"); is.data.frame(y); }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#
+##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.MayIgnoreWarningContext#
 #{ x<-c(7L,42L); y<-as.data.frame(x, row.names="r1", nm="x"); attributes(y); }
 $names
 [1] "x"
@@ -80062,7 +79966,7 @@ $class
 [1] "data.frame"
 
 
-##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#
+##com.oracle.truffle.r.test.library.base.TestSimpleDataFrames.testAsDataFrame#Output.MayIgnoreWarningContext#
 #{ x<-c(7L,42L); y<-as.data.frame(x, row.names=c("r1", "r2", "r3"), nm="x"); attributes(y); }
 $names
 [1] "x"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 01c0bebf9f..c4cfaa4a57 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -231,8 +231,7 @@ public class TestConnections extends TestRBase {
 
         // this test is currently ignored, since 'charToRaw' is not compliant
         assertEval(Ignored.Unknown, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
-        assertEval(Output.IgnoreWarningContext,
-                        "{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
+        assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
     }
 
     private static final String[] LVAL = arr("T", "F");
-- 
GitLab


From f8cc663bc39bd202c5609d67a4fc3e78fde6b8d4 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 24 Feb 2017 16:05:19 +0100
Subject: [PATCH 088/402] Cast to boolean: NA is by default TRUE + possibility
 to specify otherwise.

---
 .../library/methods/MethodsListDispatch.java  |  2 +-
 .../truffle/r/library/tools/DirChmod.java     |  2 +-
 .../oracle/truffle/r/library/utils/Rprof.java | 11 ++--
 .../truffle/r/nodes/builtin/base/Combine.java |  2 +-
 .../r/nodes/builtin/base/IsUnsorted.java      |  2 +-
 .../truffle/r/nodes/builtin/base/NChar.java   | 51 +++++++++++++----
 .../truffle/r/nodes/builtin/base/NZChar.java  |  2 +-
 .../truffle/r/nodes/builtin/base/Order.java   |  2 +-
 .../r/nodes/builtin/base/Quantifier.java      |  8 ++-
 .../truffle/r/nodes/builtin/base/Scan.java    |  4 +-
 .../truffle/r/nodes/builtin/base/Sum.java     |  2 +-
 .../truffle/r/nodes/builtin/CastBuilder.java  |  6 +-
 .../truffle/r/nodes/builtin/casts/Mapper.java |  7 +--
 .../builtin/casts/PipelineToCastNode.java     |  2 +-
 .../builtin/casts/ValueForwardingNode.java    |  2 +-
 .../analysis/ForwardingAnalysisResult.java    |  7 ++-
 .../oracle/truffle/r/runtime/RRuntime.java    |  7 ++-
 .../truffle/r/test/ExpectedTestOutput.test    | 56 ++++++++++++++++++-
 .../test/builtins/TestBuiltin_isunsorted.java |  3 +-
 .../r/test/builtins/TestBuiltin_max.java      |  2 +
 .../r/test/builtins/TestBuiltin_min.java      |  2 +
 .../r/test/builtins/TestBuiltin_nchar.java    | 20 ++++++-
 .../r/test/builtins/TestBuiltin_nzchar.java   |  3 +-
 .../r/test/builtins/TestBuiltin_order.java    |  4 +-
 .../r/test/builtins/TestBuiltin_sum.java      |  1 +
 25 files changed, 164 insertions(+), 46 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 0cec2ee980..461f4feb45 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -326,7 +326,7 @@ public class MethodsListDispatch {
 
             checkSingleString(casts, 0, "f", "The argument \"f\" to getGeneric", true, clsHierFn, vecLenFn);
 
-            casts.arg(1, "mustFind").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+            casts.arg(1, "mustFind").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
 
             casts.arg(2, "env").mustBe(instanceOf(REnvironment.class));
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
index 28efcde356..98db4f99c4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
@@ -44,7 +44,7 @@ public abstract class DirChmod extends RExternalBuiltinNode.Arg2 {
     static {
         Casts casts = new Casts(DirChmod.class);
         casts.arg(0, "dir").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
-        casts.arg(1).asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg(1).asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index c074b2217e..8ef4e9fb59 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -86,11 +86,11 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
     static {
         Casts casts = new Casts(Rprof.class);
         casts.arg(0, "filename").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
-        casts.arg(1, "append_mode").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg(1, "append_mode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         casts.arg(2, "dinterval").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
-        casts.arg(3, "mem_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
-        casts.arg(4, "gc_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
-        casts.arg(5, "line_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg(3, "mem_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+        casts.arg(4, "gc_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+        casts.arg(5, "line_profiling").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         casts.arg(6, "numfiles").asIntegerVector().findFirst().mustBe(gte(0));
         casts.arg(7, "bufsize").asIntegerVector().findFirst().mustBe(gte(0));
     }
@@ -165,8 +165,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
 
     private static String getPath(RSyntaxElement node) {
         Source source = node.getSourceSection().getSource();
-        String path = RSource.getPath(source);
-        return path;
+        return RSource.getPath(source);
     }
 
     private static final class ProfileThread extends Thread {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 1e068b47c7..142900be4e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -105,7 +105,7 @@ public abstract class Combine extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Combine.class);
-        casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
     public abstract Object executeCombine(Object value, Object recursive);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
index c426cb80a7..e9daf68f71 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
@@ -56,7 +56,7 @@ public abstract class IsUnsorted extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(IsUnsorted.class);
-        casts.arg("strictly").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).mustNotBeNA().map(toBoolean());
+        casts.arg("strictly").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
index b55927dda5..92e5e4f943 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -38,6 +39,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -50,42 +52,51 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 // TODO interpret "type" and "allowNA" arguments
 @RBuiltin(name = "nchar", kind = INTERNAL, parameterNames = {"x", "type", "allowNA", "keepNA"}, behavior = PURE)
 public abstract class NChar extends RBuiltinNode {
+    private static final String[] TYPES = new String[]{"bytes", "chars", "width"};
+    private static final int TYPE_BYTES = 0;
+    private static final int TYPE_CHARS = 1;
+    private static final int TYPE_WIDTH = 2;
 
     static {
         Casts casts = new Casts(NChar.class);
         casts.arg("x").allowNull().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false));
-        casts.arg("type").asStringVector().findFirst();
-        casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_TRUE).map(toBoolean());
-        casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+        casts.arg("type").asStringVector().findFirst().mustBe(lengthGt(0));
+        casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+        casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
     }
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RIntVector nchar(RNull value, String type, boolean allowNA, boolean keepNA) {
+    protected RIntVector nchar(RNull value, String type, byte allowNA, boolean keepNA) {
         return RDataFactory.createEmptyIntVector();
     }
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RIntVector ncharInt(RAbstractIntVector vector, String type, boolean allowNA, boolean keepNA,
+    protected RIntVector ncharInt(RAbstractIntVector vector, String type, byte allowNA, boolean keepNAIn,
                     @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
                     @Cached("createBinaryProfile()") ConditionProfile nullDimNamesProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile keepNAProfile,
                     @Cached("create()") GetDimAttributeNode getDimNode,
                     @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
                     @Cached("create()") GetDimNamesAttributeNode getDimNamesNode,
                     @Cached("create()") GetNamesAttributeNode getNamesNode) {
+        convertType(type);
+        boolean keepNA = keepNAProfile.profile(keepNAIn);
         int len = vector.getLength();
         int[] result = new int[len];
+        boolean isComplete = true;
         loopProfile.profileCounted(len);
         for (int i = 0; loopProfile.inject(i < len); i++) {
             int x = vector.getDataAt(i);
             if (x == RRuntime.INT_NA) {
-                result[i] = 2;
+                result[i] = keepNA ? RRuntime.INT_NA : 2;
+                isComplete = !keepNA;
             } else {
                 result[i] = (int) (Math.log10(x) + 1); // not the fastest one
             }
         }
-        RIntVector resultVector = RDataFactory.createIntVector(result, true, getDimNode.getDimensions(vector), getNamesNode.getNames(vector));
+        RIntVector resultVector = RDataFactory.createIntVector(result, isComplete, getDimNode.getDimensions(vector), getNamesNode.getNames(vector));
         RList dimNames = getDimNamesNode.getDimNames(vector);
         if (nullDimNamesProfile.profile(dimNames != null)) {
             setDimNamesNode.setDimNames(resultVector, dimNames);
@@ -95,24 +106,44 @@ public abstract class NChar extends RBuiltinNode {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RIntVector nchar(RAbstractStringVector vector, String type, boolean allowNA, boolean keepNA,
+    protected RIntVector nchar(RAbstractStringVector vector, String type, byte allowNA, boolean keepNAIn,
                     @Cached("createCountingProfile()") LoopConditionProfile loopProfile,
                     @Cached("createBinaryProfile()") ConditionProfile nullDimNamesProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile keepNAProfile,
                     @Cached("create()") GetDimAttributeNode getDimNode,
                     @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
                     @Cached("create()") GetDimNamesAttributeNode getDimNamesNode,
                     @Cached("create()") GetNamesAttributeNode getNamesNode) {
+        convertType(type);
+        boolean keepNA = keepNAProfile.profile(keepNAIn);
         int len = vector.getLength();
         int[] result = new int[len];
+        boolean isComplete = true;
         loopProfile.profileCounted(len);
         for (int i = 0; loopProfile.inject(i < len); i++) {
-            result[i] = vector.getDataAt(i).length();
+            String item = vector.getDataAt(i);
+            if (RRuntime.isNA(item)) {
+                result[i] = keepNA ? RRuntime.INT_NA : 2;
+                isComplete = !keepNA;
+            } else {
+                result[i] = item.length();
+            }
         }
-        RIntVector resultVector = RDataFactory.createIntVector(result, true, getDimNode.getDimensions(vector), getNamesNode.getNames(vector));
+        RIntVector resultVector = RDataFactory.createIntVector(result, isComplete, getDimNode.getDimensions(vector), getNamesNode.getNames(vector));
         RList dimNames = getDimNamesNode.getDimNames(vector);
         if (nullDimNamesProfile.profile(dimNames != null)) {
             setDimNamesNode.setDimNames(resultVector, dimNames);
         }
         return resultVector;
     }
+
+    private int convertType(String type) {
+        // The string in type is matched partially e.g. 'c' is 'chars', but 'charsxyz' is invalid
+        for (int i = 0; i < TYPES.length; i++) {
+            if (type.length() <= TYPES[i].length() && TYPES[i].startsWith(type)) {
+                return i;
+            }
+        }
+        throw error(Message.INVALID_ARGUMENT, "type");
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index bfd884b2fb..ee7883c4a4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -41,7 +41,7 @@ public abstract class NZChar extends RBuiltinNode {
     static {
         Casts casts = new Casts(NZChar.class);
         casts.arg("x").asStringVector();
-        casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+        casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean(false));
     }
 
     private static byte isNonZeroLength(String s) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index 5e62c37d0e..97359fc05e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -151,7 +151,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
     static {
         Casts casts = new Casts(Order.class);
         casts.arg("na.last").mustBe(numericValue(), INVALID_LOGICAL, "na.last").asLogicalVector().findFirst();
-        casts.arg("decreasing").mustBe(numericValue(), INVALID_LOGICAL, "decreasing").asLogicalVector().findFirst().map(toBoolean());
+        casts.arg("decreasing").defaultError(INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
     private int cmp(Object v, int i, int j, boolean naLast) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index 40d444302f..c696b7bd65 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -80,7 +81,7 @@ public abstract class Quantifier extends RBuiltinNode {
 
     protected static Casts createCasts(Class<? extends Quantifier> extCls) {
         Casts casts = new Casts(extCls);
-        casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         return casts;
     }
 
@@ -122,8 +123,9 @@ public abstract class Quantifier extends RBuiltinNode {
     }
 
     @Specialization(replaces = "opCachedLength")
-    protected byte op(RArgsValuesAndNames args, boolean naRm) {
-        boolean profiledNaRm = naRm;
+    protected byte op(RArgsValuesAndNames args, boolean naRm,
+                    @Cached("createBinaryProfile()") ConditionProfile naRmProfile) {
+        boolean profiledNaRm = naRmProfile.profile(naRm);
 
         byte result = RRuntime.asLogical(emptyVectorResult());
         for (Object argValue : args.getArguments()) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index b6ae842dc0..4d007a8406 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -119,9 +119,9 @@ public abstract class Scan extends RBuiltinNode {
 
         casts.arg("na.strings").mustBe(stringValue());
 
-        casts.arg("flush").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg("flush").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
 
-        casts.arg("fill").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg("fill").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
 
         casts.arg("strip.white").mustBe(logicalValue());
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
index bcb41b2534..bcc5478198 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
@@ -60,7 +60,7 @@ public abstract class Sum extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Sum.class);
-        casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+        casts.arg("na.rm").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 9fc4ac7073..da3d7e2cda 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -703,7 +703,11 @@ public final class CastBuilder {
         }
 
         public static MapByteToBoolean toBoolean() {
-            return MapByteToBoolean.INSTANCE;
+            return new MapByteToBoolean(true);
+        }
+
+        public static MapByteToBoolean toBoolean(boolean naReplacement) {
+            return new MapByteToBoolean(naReplacement);
         }
 
         public static MapDoubleToInt doubleToInt() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java
index 6c10646f38..1f0aa72e47 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Mapper.java
@@ -59,11 +59,10 @@ public abstract class Mapper<T, R> {
     }
 
     public static final class MapByteToBoolean extends Mapper<Byte, Boolean> {
+        public final boolean naReplacement;
 
-        public static final MapByteToBoolean INSTANCE = new MapByteToBoolean();
-
-        private MapByteToBoolean() {
-
+        public MapByteToBoolean(boolean naReplacement) {
+            this.naReplacement = naReplacement;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 5a8ee47be9..d00f5c16cb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -595,7 +595,7 @@ public final class PipelineToCastNode {
 
         @Override
         public ValuePredicateArgumentMapper<Object, Object> visit(MapByteToBoolean mapper, ValuePredicateArgumentMapper<Object, Object> previous) {
-            return ValuePredicateArgumentMapper.fromLambda(x -> RRuntime.fromLogical((Byte) x));
+            return ValuePredicateArgumentMapper.fromLambda(x -> RRuntime.fromLogical((Byte) x, mapper.naReplacement));
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java
index f3baa1bb85..4ab161a998 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java
@@ -65,7 +65,7 @@ public abstract class ValueForwardingNode extends CastNode {
 
     @Specialization(guards = "forwardingResult.isLogicalMappedToBoolean()")
     protected boolean mapLogicalToBoolean(byte x) {
-        return RRuntime.fromLogical(x);
+        return RRuntime.fromLogical(x, forwardingResult.getMapByteToBooleanNAMapping());
     }
 
     @Specialization(guards = "forwardingResult.isDoubleForwarded()")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java
index 353156736a..0058644d84 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java
@@ -82,7 +82,12 @@ public final class ForwardingAnalysisResult {
     }
 
     public boolean isLogicalMappedToBoolean() {
-        return !invalid && logicalForwarded.mapper == MapByteToBoolean.INSTANCE;
+        return !invalid && logicalForwarded.mapper instanceof MapByteToBoolean;
+    }
+
+    public boolean getMapByteToBooleanNAMapping() {
+        assert logicalForwarded.mapper instanceof MapByteToBoolean : "check isLogicalMappedToBoolean() before calling this method";
+        return ((MapByteToBoolean) logicalForwarded.mapper).naReplacement;
     }
 
     public boolean isDoubleForwarded() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index e2494cc17a..364e2d8484 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -11,6 +11,8 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import java.math.BigInteger;
+
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
@@ -39,7 +41,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
-import java.math.BigInteger;
 
 public class RRuntime {
 
@@ -276,6 +277,10 @@ public class RRuntime {
         return b == LOGICAL_TRUE;
     }
 
+    public static boolean fromLogical(byte b, boolean naValue) {
+        return naValue ? b != LOGICAL_FALSE : b == LOGICAL_TRUE;
+    }
+
     // conversions from logical
 
     public static int logical2intNoCheck(byte value) {
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 4e3506d9a4..1e38bd58c6 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
@@ -26842,6 +26842,10 @@ logical(0)
 #{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) }
 [1] TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted#Output.IgnoreErrorContext#
+#{ is.unsorted(c(1,2,2), strictly=NA) }
+Error in is.unsorted(x, strictly) : invalid 'strictly' argument
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isunsorted.testIsUnsorted#
 #{ is.unsorted(c(1,2,2,3), strictly=TRUE) }
 [1] TRUE
@@ -31908,6 +31912,10 @@ object "foo"
 #argv <- list(0L, 0L, 0L, FALSE, NULL, FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 <0 x 0 matrix>
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
+#max(c(1,NA,2), na.rm=NA)
+[1] 2
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #max(v<-42)
 [1] 42
@@ -32611,6 +32619,10 @@ list
 sys.call(1)
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
+#min(c(1,NA,2), na.rm=NA)
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ is.logical(min(TRUE)) }
 [1] FALSE
@@ -33969,6 +33981,26 @@ a     f g
 #{ nchar(c(10,130)) }
 [1] 2 3
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharKeepNA#
+#nchar(c('aasd', NA), keepNA=NA)
+[1]  4 NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharKeepNA#
+#nchar(c('aasd', NA, 'asdasd'), keepNA=TRUE)
+[1]  4 NA  6
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharTypeMatching#
+#nchar('aasd', type='')
+Error in nchar("aasd", type = "") : invalid 'type' argument
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharTypeMatching#
+#nchar('aasd', type='cha')
+[1] 4
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNCharTypeMatching#
+#nchar('aasd', type='charsxzy')
+Error in nchar("aasd", type = "charsxzy") : invalid 'type' argument
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar1#
 #argv <- list('DtTmCl> format(.leap.seconds)         # all 24 leap seconds in your timezone', 'c', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] 76
@@ -33985,9 +34017,14 @@ a     f g
 #argv <- list(character(0), 'c', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13#
-#argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\'Terry\', \'Therneau\', role = \'aut\',\n\t             email = \'therneau@mayo.edu\'),\n             person(\'Beth\', \'Atkinson\', role = \'aut\',\t\n\t             email = \'atkinson@mayo.edu\'),\n             person(\'Brian\', \'Ripley\', role = c(\'aut\', \'trl\', \'cre\'),\n                    email = \'ripley@stats.ox.ac.uk\',\n\t\t   comment = \'author of R port\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\n  Beth Atkinson [aut],\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
-Error in argv[[4]] : subscript out of bounds
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13#Ignored.Unimplemented#
+#argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\'Terry\', \'Therneau\', role = \'aut\',\n\t             email = \'therneau@mayo.edu\'),\n             person(\'Beth\', \'Atkinson\', role = \'aut\',\t\n\t             email = \'atkinson@mayo.edu\'),\n             person(\'Brian\', \'Ripley\', role = c(\'aut\', \'trl\', \'cre\'),\n                    email = \'ripley@stats.ox.ac.uk\',\n\t\t   comment = \'author of R port\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\n  Beth Atkinson [aut],\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
+    Package    Priority     Version        Date   Authors@R Description
+          5          11           5          10         345          43
+      Title     Depends    Suggests     License    LazyData ByteCompile
+         22          41           8          13           3           3
+       Note    Packaged      Author  Maintainer
+         84          31          94          36
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar2#
 #argv <- list(c('\'a\'', '\'b\'', NA, NA, NA, '\'f\'', '\'g\'', '\'h\'', '\'i\'', '\'j\'', '\'k\'', '\'l\''), 'w', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
@@ -34136,6 +34173,10 @@ Warning messages:
 #argv <- structure(list(x = structure(c(0, 3313, 2963, 3175, 3339,     2762, 3276, 2610, 4485, 2977, 3030, 4532, 2753, 3949, 2865,     2282, 2179, 3000, 817, 3927, 1991, 3313, 0, 1318, 1326, 1294,     1498, 2218, 803, 1172, 2018, 1490, 1305, 645, 636, 521, 1014,     1365, 1033, 1460, 2868, 1802, 2963, 1318, 0, 204, 583, 206,     966, 677, 2256, 597, 172, 2084, 690, 1558, 1011, 925, 747,     285, 1511, 1616, 1175, 3175, 1326, 204, 0, 460, 409, 1136,     747, 2224, 714, 330, 2052, 739, 1550, 1059, 1077, 977, 280,     1662, 1786, 1381, 3339, 1294, 583, 460, 0, 785, 1545, 853,     2047, 1115, 731, 1827, 789, 1347, 1101, 1209, 1160, 340,     1794, 2196, 1588, 2762, 1498, 206, 409, 785, 0, 760, 1662,     2436, 460, 269, 2290, 714, 1764, 1035, 911, 583, 465, 1497,     1403, 937, 3276, 2218, 966, 1136, 1545, 760, 0, 1418, 3196,     460, 269, 2971, 1458, 2498, 1778, 1537, 1104, 1176, 2050,     650, 1455, 2610, 803, 677, 747, 853, 1662, 1418, 0, 1975,     1118, 895, 1936, 158, 1439, 425, 328, 591, 513, 995, 2068,     1019, 4485, 1172, 2256, 2224, 2047, 2436, 3196, 1975, 0,     2897, 2428, 676, 1817, 698, 1693, 2185, 2565, 1971, 2631,     3886, 2974, 2977, 2018, 597, 714, 1115, 460, 460, 1118, 2897,     0, 550, 2671, 1159, 2198, 1479, 1238, 805, 877, 1751, 949,     1155, 3030, 1490, 172, 330, 731, 269, 269, 895, 2428, 550,     0, 2280, 863, 1730, 1183, 1098, 851, 457, 1683, 1500, 1205,     4532, 1305, 2084, 2052, 1827, 2290, 2971, 1936, 676, 2671,     2280, 0, 1178, 668, 1762, 2250, 2507, 1799, 2700, 3231, 2937,     2753, 645, 690, 739, 789, 714, 1458, 158, 1817, 1159, 863,     1178, 0, 1281, 320, 328, 724, 471, 1048, 2108, 1157, 3949,     636, 1558, 1550, 1347, 1764, 2498, 1439, 698, 2198, 1730,     668, 1281, 0, 1157, 1724, 2010, 1273, 2097, 3188, 2409, 2865,     521, 1011, 1059, 1101, 1035, 1778, 425, 1693, 1479, 1183,     1762, 320, 1157, 0, 618, 1109, 792, 1011, 2428, 1363, 2282,     1014, 925, 1077, 1209, 911, 1537, 328, 2185, 1238, 1098,     2250, 328, 1724, 618, 0, 331, 856, 586, 2187, 898, 2179,     1365, 747, 977, 1160, 583, 1104, 591, 2565, 805, 851, 2507,     724, 2010, 1109, 331, 0, 821, 946, 1754, 428, 3000, 1033,     285, 280, 340, 465, 1176, 513, 1971, 877, 457, 1799, 471,     1273, 792, 856, 821, 0, 1476, 1827, 1249, 817, 1460, 1511,     1662, 1794, 1497, 2050, 995, 2631, 1751, 1683, 2700, 1048,     2097, 1011, 586, 946, 1476, 0, 2707, 1209, 3927, 2868, 1616,     1786, 2196, 1403, 650, 2068, 3886, 949, 1500, 3231, 2108,     3188, 2428, 2187, 1754, 1827, 2707, 0, 2105, 1991, 1802,     1175, 1381, 1588, 937, 1455, 1019, 2974, 1155, 1205, 2937,     1157, 2409, 1363, 898, 428, 1249, 1209, 2105, 0), .Dim = c(21L,     21L), .Dimnames = list(c('Athens', 'Barcelona', 'Brussels',     'Calais', 'Cherbourg', 'Cologne', 'Copenhagen', 'Geneva',     'Gibraltar', 'Hamburg', 'Hook of Holland', 'Lisbon', 'Lyons',     'Madrid', 'Marseilles', 'Milan', 'Munich', 'Paris', 'Rome',     'Stockholm', 'Vienna'), c('Athens', 'Barcelona', 'Brussels',     'Calais', 'Cherbourg', 'Cologne', 'Copenhagen', 'Geneva',     'Gibraltar', 'Hamburg', 'Hook of Holland', 'Lisbon', 'Lyons',     'Madrid', 'Marseilles', 'Milan', 'Munich', 'Paris', 'Rome',     'Stockholm', 'Vienna')))), .Names = 'x');do.call('NROW', argv)
 [1] 21
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests#
+#nzchar(c('aasd', NA), keepNA=NA)
+[1] TRUE TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.keepNATests#
 #nzchar(c('asdasd', NA), keepNA=FALSE)
 [1] TRUE TRUE
@@ -39279,6 +39320,11 @@ $ts.eps
 #order(c('40 50', '405', '40 51', '4028', '40 20', '40 30', '404'))
 [1] 5 6 1 3 4 7 2
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_order.testOrder#
+#order(c(1,2,0), decreasing=NA)
+Error in order(c(1, 2, 0), decreasing = NA) :
+  'decreasing' must be TRUE or FALSE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_order.testOrder#
 #{ order() }
 NULL
@@ -63844,6 +63890,10 @@ Warning message:
 In sum(seq.int(from = 1, by = 1, length.out = 1e+05)) :
   integer overflow - use sum(as.numeric(.))
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testSum#
+#sum(c(1,2,NA,3), na.rm=NA)
+[1] 6
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sum.testSum#
 #sum(v <- 42)
 [1] 42
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java
index be6652d29a..52fa1f06fb 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isunsorted.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -98,5 +98,6 @@ public class TestBuiltin_isunsorted extends TestBase {
         assertEval("{ is.unsorted(c(1,2,2,3), strictly=TRUE) }");
         assertEval("{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=FALSE) }");
         assertEval("{ is.unsorted(c(1+1i,2+1i,2+1i), strictly=TRUE) }");
+        assertEval(Output.IgnoreErrorContext, "{ is.unsorted(c(1,2,2), strictly=NA) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
index 592a227d53..9d88cf794b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
@@ -219,5 +219,7 @@ public class TestBuiltin_max extends TestBase {
         assertEval("{ max(as.double(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
+
+        assertEval("max(c(1,NA,2), na.rm=NA)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
index 6611a99ccc..c8c5ab5a20 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
@@ -178,5 +178,7 @@ public class TestBuiltin_min extends TestBase {
         assertEval("{ min(as.double(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.integer(NA), na.rm=TRUE) }");
         assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ min(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
+
+        assertEval("min(c(1,NA,2), na.rm=NA)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
index a55986b741..661b52abaa 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -74,7 +74,9 @@ public class TestBuiltin_nchar extends TestBase {
 
     @Test
     public void testnchar13() {
-        assertEval("argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\\\'Terry\\\', \\\'Therneau\\\', role = \\\'aut\\\',\\n\\t             email = \\\'therneau@mayo.edu\\\'),\\n             person(\\\'Beth\\\', \\\'Atkinson\\\', role = \\\'aut\\\',\\t\\n\\t             email = \\\'atkinson@mayo.edu\\\'),\\n             person(\\\'Brian\\\', \\\'Ripley\\\', role = c(\\\'aut\\\', \\\'trl\\\', \\\'cre\\\'),\\n                    email = \\\'ripley@stats.ox.ac.uk\\\',\\n\\t\\t   comment = \\\'author of R port\\\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\\n  Beth Atkinson [aut],\\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        // allowNA == TRUE is not implemented
+        assertEval(Ignored.Unimplemented,
+                        "argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\\\'Terry\\\', \\\'Therneau\\\', role = \\\'aut\\\',\\n\\t             email = \\\'therneau@mayo.edu\\\'),\\n             person(\\\'Beth\\\', \\\'Atkinson\\\', role = \\\'aut\\\',\\t\\n\\t             email = \\\'atkinson@mayo.edu\\\'),\\n             person(\\\'Brian\\\', \\\'Ripley\\\', role = c(\\\'aut\\\', \\\'trl\\\', \\\'cre\\\'),\\n                    email = \\\'ripley@stats.ox.ac.uk\\\',\\n\\t\\t   comment = \\\'author of R port\\\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\\n  Beth Atkinson [aut],\\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
@@ -84,7 +86,19 @@ public class TestBuiltin_nchar extends TestBase {
         assertEval("{ nchar(c(10,130)) }");
         assertEval("{ .Internal(nchar(c(10,130), 'chars', FALSE, FALSE)) }");
         assertEval("{ .Internal(nchar('ff', 'chars', FALSE, FALSE)) }");
-
         assertEval("v <- c(a=1,b=1234,c='ff',d='gg'); dim(v) <- c(foo=2,bar=2); dimnames(v) <- list(a=c('foo', 'bar'), n=c('f','g')); nchar(v)");
     }
+
+    @Test
+    public void testNCharKeepNA() {
+        assertEval("nchar(c('aasd', NA), keepNA=NA)");
+        assertEval("nchar(c('aasd', NA, 'asdasd'), keepNA=TRUE)");
+    }
+
+    @Test
+    public void testNCharTypeMatching() {
+        assertEval("nchar('aasd', type='cha')");
+        assertEval("nchar('aasd', type='charsxzy')");
+        assertEval("nchar('aasd', type='')");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
index c432329425..980d16177b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -76,6 +76,7 @@ public class TestBuiltin_nzchar extends TestBase {
     public void keepNATests() {
         assertEval("nzchar(c('asdasd', NA), keepNA=TRUE)");
         assertEval("nzchar(c('asdasd', NA), keepNA=FALSE)");
+        assertEval("nzchar(c('aasd', NA), keepNA=NA)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java
index 0ae5ec00e3..c9fd1e66c5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_order.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -162,5 +162,7 @@ public class TestBuiltin_order extends TestBase {
         assertEval("{ order(c(0/0, -1/0, 2), na.last=NA) }");
 
         assertEval("order(c('40 50', '405', '40 51', '4028', '40 20', '40 30', '404'))");
+
+        assertEval("order(c(1,2,0), decreasing=NA)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java
index af45e08505..6fb525be17 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java
@@ -178,6 +178,7 @@ public class TestBuiltin_sum extends TestBase {
         assertEval("{ sum(1+1i,2,NA, na.rm=TRUE) }");
 
         assertEval("sum(v <- 42)");
+        assertEval("sum(c(1,2,NA,3), na.rm=NA)");
     }
 
     @Test
-- 
GitLab


From 36e7264f01a57a19ede428897795b4530a81a007 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Mon, 27 Feb 2017 10:07:48 +0100
Subject: [PATCH 089/402] Fixed cast pipelines of builtins 'remove' till
 'strtrim'.

---
 .../builtin/base/DatePOSIXFunctions.java      |   7 +-
 .../nodes/builtin/base/LoadSaveFunctions.java |  16 +-
 .../r/nodes/builtin/base/RepeatInternal.java  |  47 ++++
 .../r/nodes/builtin/base/RepeatLength.java    |   5 +-
 .../truffle/r/nodes/builtin/base/Rm.java      |  10 -
 .../r/nodes/builtin/base/RowsumFunctions.java |   9 +-
 .../truffle/r/nodes/builtin/base/Sample.java  |  25 +--
 .../truffle/r/nodes/builtin/base/Sample2.java |   4 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |  10 +-
 .../builtin/base/SerializeFunctions.java      |  12 +-
 .../r/nodes/builtin/base/SetS4Object.java     |   2 +-
 .../r/nodes/builtin/base/SortFunctions.java   |  20 +-
 .../truffle/r/nodes/builtin/base/Strrep.java  |  17 +-
 .../truffle/r/nodes/builtin/base/Strtrim.java |   3 +-
 .../r/nodes/builtin/base/TraceFunctions.java  |   2 +-
 .../builtin/base/infix/RepeatBuiltin.java     |   5 +
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 202 ++++++++++++++++++
 .../r/test/builtins/TestBuiltin_psort.java    |  10 +-
 .../r/test/builtins/TestBuiltin_qsort.java    |  15 +-
 .../r/test/builtins/TestBuiltin_rep.java      |   6 +
 .../r/test/builtins/TestBuiltin_repint.java   |  13 ++
 .../r/test/builtins/TestBuiltin_rowsum.java   |  21 +-
 .../r/test/builtins/TestBuiltin_sample.java   |   5 +
 .../r/test/builtins/TestBuiltin_sample2.java  |   3 +-
 .../r/test/builtins/TestBuiltin_scan.java     |  15 ++
 .../builtins/TestBuiltin_setS4Object.java     |   1 +
 .../r/test/builtins/TestBuiltin_sort.java     |   6 +-
 .../r/test/builtins/TestBuiltin_strptime.java |  10 +-
 .../r/test/builtins/TestBuiltin_strrep.java   |  13 +-
 .../r/test/builtins/TestBuiltin_strtrim.java  |   8 +-
 .../r/test/builtins/TestBuiltin_tracemem.java |   3 +-
 32 files changed, 467 insertions(+), 61 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
index be7cba0797..c33f2d9649 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
@@ -393,9 +394,9 @@ public class DatePOSIXFunctions {
 
         static {
             Casts casts = new Casts(StrPTime.class);
-            casts.arg("x").mapNull(emptyStringVector()).asStringVector();
-            casts.arg("format").mapNull(emptyStringVector()).asStringVector();
-            casts.arg("tz").mapNull(emptyStringVector()).asStringVector();
+            casts.arg("x").mapNull(emptyStringVector()).mustBe(missingValue().not()).asStringVector();
+            casts.arg("format").mapNull(emptyStringVector()).mustBe(missingValue().not()).asStringVector();
+            casts.arg("tz").mapNull(emptyStringVector()).mustBe(missingValue().not()).asStringVector();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
index bec48dd87d..027d33bbf8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
@@ -13,7 +13,6 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
@@ -28,7 +27,6 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -36,7 +34,6 @@ import com.oracle.truffle.r.nodes.builtin.base.SerializeFunctions.Adapter;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSerialize;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -197,14 +194,14 @@ public class LoadSaveFunctions {
             Casts casts = new Casts(SaveToConn.class);
             casts.arg("list").mustBe(stringValue()).asStringVector();
             ConnectionFunctions.CastsHelper.connection(casts);
-            casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL);
-            casts.arg("version").allowNull().mustBe(integerValue());
+            casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL).asLogicalVector().findFirst().map(toBoolean());
+            casts.arg("version").allowNull().asIntegerVector().findFirstOrNull();
             casts.arg("environment").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
             casts.arg("eval.promises").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
-        protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, int con, byte asciiLogical, @SuppressWarnings("unused") RNull version, REnvironment envir, boolean evalPromises,
+        protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, int con, boolean ascii, @SuppressWarnings("unused") RNull version, REnvironment envir, boolean evalPromises,
                         @Cached("new()") PromiseCheckHelperNode promiseHelper) {
             RPairList prev = null;
             Object toSave = RNull.instance;
@@ -226,7 +223,6 @@ public class LoadSaveFunctions {
                 }
                 prev = pl;
             }
-            boolean ascii = RRuntime.fromLogical(asciiLogical);
             doSaveConn(toSave, RConnection.fromIndex(con), ascii);
             return RNull.instance;
         }
@@ -248,9 +244,9 @@ public class LoadSaveFunctions {
         }
 
         @SuppressWarnings("unused")
-        @Fallback
-        protected Object saveToConn(Object list, Object con, Object ascii, Object version, Object envir, Object evaPromises) {
-            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+        @Specialization
+        protected Object saveToConn(VirtualFrame frame, RAbstractStringVector list, int con, boolean ascii, int version, REnvironment envir, boolean evalPromises) {
+            throw error(RError.Message.INVALID_ARG_TYPE, 5); // [TODO] implement "version" support
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
index 41e4ed34b5..a9a9c80e8a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
@@ -35,6 +35,8 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -42,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
@@ -137,6 +140,50 @@ public abstract class RepeatInternal extends RBuiltinNode {
         return repInt(value, times, byte[]::new, (array, pos, val, index) -> array[pos] = val.getDataAt(index).getValue(), (array, complete) -> RDataFactory.createRawVector(array));
     }
 
+    @Specialization
+    protected RComplexVector repComplex(RAbstractComplexVector value, RAbstractIntVector times) {
+        int timesLength = times.getLength();
+        int valueLength = value.getLength();
+        double[] resultArray;
+        if (timesOneProfile.profile(timesLength == 1)) {
+            int timesValue = times.getDataAt(0);
+            if (timesValue < 0) {
+                throw error(RError.Message.INVALID_VALUE, "times");
+            }
+            resultArray = new double[(timesValue * valueLength) << 1];
+            int pos = 0;
+            for (int i = 0; i < timesValue; i++) {
+                for (int j = 0; j < valueLength; j++) {
+                    RComplex complex = value.getDataAt(j);
+                    resultArray[pos++] = complex.getRealPart();
+                    resultArray[pos++] = complex.getImaginaryPart();
+                }
+            }
+        } else if (timesLength == valueLength) {
+            int count = 0;
+            for (int i = 0; i < timesLength; i++) {
+                int data = times.getDataAt(i);
+                if (data < 0) {
+                    throw error(RError.Message.INVALID_VALUE, "times");
+                }
+                count += data;
+            }
+            resultArray = new double[count << 1];
+            int pos = 0;
+            for (int i = 0; i < valueLength; i++) {
+                int num = times.getDataAt(i);
+                RComplex complex = value.getDataAt(i);
+                for (int j = 0; j < num; j++) {
+                    resultArray[pos++] = complex.getRealPart();
+                    resultArray[pos++] = complex.getImaginaryPart();
+                }
+            }
+        } else {
+            throw error(RError.Message.INVALID_VALUE, "times");
+        }
+        return RDataFactory.createComplexVector(resultArray, value.isComplete());
+    }
+
     @Specialization
     protected RList repList(RList value, int times) {
         int oldLength = value.getLength();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
index 2b6a4d9387..da12e4f3b1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
@@ -43,7 +43,7 @@ public abstract class RepeatLength extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(RepeatLength.class);
-        casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR);
+        casts.arg("x").allowNull().mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE_NO_VECTOR);
         // with default error message, SHOW_CALLER does not work
         casts.arg("length.out").defaultError(RError.Message.INVALID_VALUE, "length.out").mustNotBeNull().asIntegerVector().mustBe(size(1)).findFirst().mustBe(notIntNA());
     }
@@ -51,6 +51,9 @@ public abstract class RepeatLength extends RBuiltinNode {
     @Specialization
     @SuppressWarnings("unused")
     protected RNull repLen(RNull value, int length) {
+        if (length != 0) {
+            RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_REPLICATE_NULL);
+        }
         return RNull.instance;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
index d1378ebf1b..b3176f58ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
@@ -36,13 +36,11 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -64,14 +62,6 @@ public abstract class Rm extends RBuiltinNode {
         casts.arg("inherits").mustBe(numericValue(), INVALID_ARGUMENT, "inherits").asLogicalVector().findFirst().map(toBoolean());
     }
 
-    // this specialization is for internal use only
-    // TODO: what internal use? Does it still apply?
-    @Specialization
-    protected Object rm(VirtualFrame frame, String name, @SuppressWarnings("unused") RMissing envir, @SuppressWarnings("unused") boolean inherits) {
-        removeFromFrame(frame, name);
-        return RNull.instance;
-    }
-
     @Specialization
     @TruffleBoundary
     protected Object rm(RAbstractStringVector list, REnvironment envir, @SuppressWarnings("unused") boolean inherits) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
index b7db4f9029..6a8df0334b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
@@ -12,8 +12,12 @@
 
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.and;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
@@ -29,6 +33,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -54,9 +59,9 @@ public class RowsumFunctions {
             Casts casts = new Casts(Rowsum.class);
             casts.arg("x").mustBe(integerValue().or(doubleValue()), RError.Message.ROWSUM_NON_NUMERIC);
 
-            casts.arg("g").asVector();
+            casts.arg("g").mustNotBeMissing().mustBe(and(not(nullValue()), not(instanceOf(RFunction.class)))).asVector();
 
-            casts.arg("uniqueg").asVector();
+            casts.arg("uniqueg").mustNotBeMissing().mustBe(and(not(nullValue()), not(instanceOf(RFunction.class)))).asVector();
 
             casts.arg("snarm").asLogicalVector().findFirst().mustNotBeNA(RError.Message.INVALID_LOGICAL).map(toBoolean());
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
index c58dd93629..fd7cbae8c1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
@@ -24,6 +24,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.isFinite;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustBe;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
@@ -43,9 +44,9 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.rng.RRNG;
 
 @RBuiltin(name = "sample", kind = INTERNAL, parameterNames = {"x", "size", "replace", "prob"}, behavior = MODIFIES_STATE)
@@ -54,13 +55,13 @@ public abstract class Sample extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Sample.class);
-        casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).mustNotBeNA(VECTOR_SIZE_NA_NAN).mapIf(doubleValue(),
+        casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).mustBe(integerValue().or(doubleValue())).mustNotBeNA(VECTOR_SIZE_NA_NAN).mapIf(doubleValue(),
                         chain(asDoubleVector()).with(findFirst().doubleElement()).with(mustBe(isFinite(), VECTOR_SIZE_NA_NAN)).with(
                                         mustBe(lt(4.5e15), VECTOR_SIZE_TOO_LARGE)).end()).asIntegerVector().findFirst().mustBe(gte0());
-        casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().mustNotBeNA(
-                        INVALID_ARGUMENT, "size").mustBe(gte0(), INVALID_ARGUMENT, "size");
+        casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue()).or(stringValue())).asIntegerVector().findFirst().mustNotBeNA(INVALID_ARGUMENT, "size").mustBe(
+                        gte0(), INVALID_ARGUMENT, "size");
         casts.arg("replace").mustBe(integerValue().or(doubleValue()).or(logicalValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustNotBeNA().map(toBoolean());
-        casts.arg("prob").asDoubleVector();
+        casts.arg("prob").mustNotBeMissing().mustBe(doubleValue().or(nullValue())).asDoubleVector();
     }
 
     // Validation that correlates two or more argument values (note: positiveness of prob is checked
@@ -70,20 +71,20 @@ public abstract class Sample extends RBuiltinNode {
         return !isRepeatable && size > x;
     }
 
-    protected static boolean invalidProb(final int x, final RDoubleVector prob) {
+    protected static boolean invalidProb(final int x, final RAbstractDoubleVector prob) {
         return prob.getLength() != x;
     }
 
     @Specialization(guards = "invalidProb(x, prob)")
     @SuppressWarnings("unused")
-    protected RIntVector doSampleInvalidProb(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) {
+    protected RIntVector doSampleInvalidProb(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) {
         CompilerDirectives.transferToInterpreter();
         throw error(RError.Message.INCORRECT_NUM_PROB);
     }
 
     @Specialization(guards = "largerPopulation(x, size, isRepeatable)")
     @SuppressWarnings("unused")
-    protected RIntVector doSampleLargerPopulation(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) {
+    protected RIntVector doSampleLargerPopulation(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) {
         CompilerDirectives.transferToInterpreter();
         throw error(RError.Message.SAMPLE_LARGER_THAN_POPULATION);
     }
@@ -99,10 +100,10 @@ public abstract class Sample extends RBuiltinNode {
 
     @Specialization(guards = {"!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "isRepeatable"})
     @TruffleBoundary
-    protected RIntVector doSampleWithReplacement(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) {
+    protected RIntVector doSampleWithReplacement(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) {
         // The following code is transcribed from GNU R src/main/random.c lines 493-501 in
         // function do_sample.
-        double[] probArray = prob.getDataCopy();
+        double[] probArray = prob.materialize().getDataCopy();
         fixupProbability(probArray, x, size, isRepeatable);
         int nc = 0;
         for (double aProb : probArray) {
@@ -120,8 +121,8 @@ public abstract class Sample extends RBuiltinNode {
 
     @Specialization(guards = {"!invalidProb(x, prob)", "!largerPopulation(x, size, isRepeatable)", "!isRepeatable"})
     @TruffleBoundary
-    protected RIntVector doSampleNoReplacement(final int x, final int size, final boolean isRepeatable, final RDoubleVector prob) {
-        double[] probArray = prob.getDataCopy();
+    protected RIntVector doSampleNoReplacement(final int x, final int size, final boolean isRepeatable, final RAbstractDoubleVector prob) {
+        double[] probArray = prob.materialize().getDataCopy();
         fixupProbability(probArray, x, size, isRepeatable);
         return RDataFactory.createIntVector(probSampleWithoutReplace(x, probArray, size), RDataFactory.COMPLETE_VECTOR);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
index 42488c4dbb..e5ce462981 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
@@ -43,8 +43,8 @@ public abstract class Sample2 extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Sample2.class);
-        casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).allowNull().mustBe(integerValue().or(doubleValue())).mustNotBeNA(INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(
-                        gte(0.0)).mustBe(isFinite());
+        casts.arg("x").defaultError(INVALID_FIRST_ARGUMENT).mustBe(integerValue().or(doubleValue())).mustNotBeNA(
+                        INVALID_FIRST_ARGUMENT).asDoubleVector().findFirst().mustBe(gte(0.0)).mustBe(isFinite());
         casts.arg("size").defaultError(INVALID_ARGUMENT, "size").mustBe(integerValue().or(doubleValue())).asIntegerVector().findFirst().mustNotBeNA(INVALID_ARGUMENT,
                         "size").mustBe(gte0(), INVALID_ARGUMENT, "size");
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index b6ae842dc0..e7feb53dc4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -14,10 +14,13 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.charAt0;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.length;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthLte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
@@ -44,6 +47,7 @@ import com.oracle.truffle.r.runtime.conn.StdConnections;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogical;
@@ -102,13 +106,13 @@ public abstract class Scan extends RBuiltinNode {
         Casts casts = new Casts(Scan.class);
         casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
 
-        casts.arg("what").asVector();
+        casts.arg("what").mustNotBeMissing().mustBe(nullValue().not()).mustBe(instanceOf(RFunction.class).not()).asVector();
 
         casts.arg("nmax").asIntegerVector().findFirst(0).replaceNA(0).mapIf(lt(0), constant(0));
 
-        casts.arg("sep").allowNull().mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value");
+        casts.arg("sep").mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().findFirst("").mustBe(lengthLte(1), RError.Message.MUST_BE_ONE_BYTE, "'sep' value");
 
-        casts.arg("dec").defaultError(RError.Message.INVALID_DECIMAL_SEP).allowNull().mustBe(stringValue()).asStringVector().findFirst(".").mustBe(length(1),
+        casts.arg("dec").defaultError(RError.Message.INVALID_DECIMAL_SEP).mapNull(constant(".")).mustBe(stringValue()).asStringVector().findFirst(".").mustBe(length(1),
                         RError.Message.MUST_BE_ONE_BYTE, "'sep' value");
 
         casts.arg("quote").defaultError(RError.Message.INVALID_QUOTE_SYMBOL).mapNull(constant("")).mustBe(stringValue()).asStringVector().findFirst("");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
index 16de9b7570..7ae7101b3d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
@@ -115,9 +115,11 @@ public class SerializeFunctions {
 
         static {
             Casts casts = new Casts(SerializeToConn.class);
+            casts.arg("object").mustNotBeMissing();
             connection(casts);
-            casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL);
-            casts.arg("version").allowNull().mustBe(integerValue());
+            casts.arg("ascii").mustBe(logicalValue(), RError.Message.ASCII_NOT_LOGICAL).asLogicalVector().findFirst();
+            casts.arg("version").allowNull().mustBe(integerValue()).asIntegerVector().findFirst();
+            casts.arg("refhook").mustNotBeMissing();
         }
 
         @Specialization
@@ -132,6 +134,12 @@ public class SerializeFunctions {
             }
             return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook);
         }
+
+        @Specialization
+        protected Object doSerializeToConn(Object object, int conn, byte asciiLogical, int version, Object refhook) {
+            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 4); // [TODO] implement
+                                                                                // "version" support
+        }
     }
 
     @RBuiltin(name = "unserialize", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
index 93fa6d8ce7..c590cebea8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
@@ -46,7 +46,7 @@ public abstract class SetS4Object extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(SetS4Object.class);
-        casts.arg("object").asAttributable(true, true, true);
+        casts.arg("object").mustNotBeMissing().asAttributable(true, true, true);
         casts.arg("flag").asLogicalVector().mustBe(singleElement(), RError.Message.INVALID_ARGUMENT, "flag").findFirst().map(toBoolean());
         // "complete" can be a vector, unlike "flag"
         casts.arg("complete").asIntegerVector().findFirst(RError.Message.INVALID_ARGUMENT, "complete");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index b5e9e5689a..370208bd12 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -23,9 +23,12 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL;
+import static com.oracle.truffle.r.runtime.RError.Message.RAW_SORT;
 import static com.oracle.truffle.r.runtime.RError.Message.ONLY_ATOMIC_CAN_BE_SORTED;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -46,8 +49,10 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -59,7 +64,8 @@ public class SortFunctions {
 
     private abstract static class Adapter extends RBuiltinNode {
         protected static void addCastForX(Casts casts) {
-            casts.arg("x").allowNull().mustBe(abstractVectorValue(), ONLY_ATOMIC_CAN_BE_SORTED);
+            casts.arg("x").allowNull().mustBe(rawValue().not(), RAW_SORT).mustBe(instanceOf(RAbstractListVector.class).not(), ONLY_ATOMIC_CAN_BE_SORTED).mustBe(
+                            abstractVectorValue(), ONLY_ATOMIC_CAN_BE_SORTED);
         }
 
         protected static void addCastForDecreasing(Casts casts) {
@@ -175,6 +181,18 @@ public class SortFunctions {
         protected RLogicalVector sort(RAbstractLogicalVector vec, boolean decreasing) {
             return jdkSort(vec, decreasing);
         }
+
+        @Specialization
+        protected RLogicalVector sort(RAbstractComplexVector vec, boolean decreasing) {
+            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1); // [TODO] implement
+                                                                                // complex sort
+        }
+
+        @Specialization
+        protected RNull sort(RNull vec, boolean decreasing) {
+            return RNull.instance;
+        }
+
     }
 
     @RBuiltin(name = "qsort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
index 262d39af1b..969121a265 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -43,8 +44,8 @@ public abstract class Strrep extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Strrep.class);
-        casts.arg("x").asStringVector();
-        casts.arg("times").asIntegerVector();
+        casts.arg("x").mustNotBeMissing().asStringVector();
+        casts.arg("times").mustNotBeMissing().asIntegerVector();
     }
 
     @Specialization
@@ -89,6 +90,18 @@ public abstract class Strrep extends RBuiltinNode {
         return result;
     }
 
+    @Specialization
+    protected Object strrep(RNull xVec, RAbstractIntVector timesVec) {
+        return RDataFactory.createEmptyStringVector(); // GnuR fails with segfault; return value
+                                                       // adheres to non-internal strrep() result
+    }
+
+    @Specialization
+    protected Object strrep(RAbstractStringVector xVec, RNull timesVec) {
+        return RDataFactory.createEmptyStringVector(); // GnuR - infinite loop; return value adheres
+                                                       // to non-internal strrep() result
+    }
+
     @TruffleBoundary
     private static void copyNames(RAbstractStringVector xVec, RStringVector result) {
         result.copyNamesFrom(xVec);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
index 66943ed06e..b80c706e89 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
@@ -12,6 +12,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -39,7 +40,7 @@ public abstract class Strtrim extends RBuiltinNode {
     static {
         Casts casts = new Casts(Strtrim.class);
         casts.arg("x").defaultError(Message.REQUIRES_CHAR_VECTOR, "strtrim()").mustBe(stringValue()).asStringVector(true, true, true);
-        casts.arg("width").asIntegerVector();
+        casts.arg("width").mustNotBeMissing().mustBe(nullValue().not()).asIntegerVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
index c14e83f92a..c5d7ba1322 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
@@ -255,7 +255,7 @@ public class TraceFunctions {
 
         static {
             Casts casts = new Casts(Retracemem.class);
-            casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").allowNullAndMissing().mustBe(stringValue());
+            casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").allowNullAndMissing().mustBe(stringValue()).asStringVector().findFirst();
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java
index 5b612ffdcf..46239fcbf5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java
@@ -33,6 +33,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "repeat", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
 public abstract class RepeatBuiltin extends RBuiltinNode {
+
+    static {
+        Casts.noCasts(RepeatBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 09e7edf54a..fa016d322e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -839,7 +839,8 @@ public final class RError extends RuntimeException {
         UNSUPPORTED_ENCODING_CONVERSION("unsupported conversion from '%s' to '%s'"),
         UNABLE_TO_RESOLVE("unable to resolve '%s'"),
         LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul"),
-        UNSUPPORTED_URL_METHOD("method = \"%s\" is not supported");
+        UNSUPPORTED_URL_METHOD("method = \"%s\" is not supported"),
+        CANNOT_REPLICATE_NULL("cannot replicate NULL to a non-zero length");
 
         public final String message;
         final boolean hasArgs;
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 88bd852e6c..99020f648a 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
@@ -41405,6 +41405,18 @@ Evaluation  city centre   suburbs
 Warning message:
 NaNs produced
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testArgsCasts#
+#{ .Internal(psort(as.raw(c(0x44,0x40)), FALSE)) }
+Error: raw vectors cannot be sorted
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testArgsCasts#
+#{ .Internal(sort(NULL, FALSE)) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testArgsCasts#
+#{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }
+Error: only atomic vectors can be sorted
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_psort.testpsort1#
 #argv <- list(7:8, 1:2); .Internal(psort(argv[[1]], argv[[2]]))
 [1] 7 8
@@ -41709,6 +41721,18 @@ Error in qr.coef(x, 1:2) : right-hand side should have 10 not 2 rows
 [19,] -0.195065684  0.49023013
 [20,]  0.262976528 -0.17049944
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testArgsCasts#Output.IgnoreErrorMessage#
+#{ .Internal(qsort(as.raw(c(0x44,0x40)), FALSE)) }
+Error: argument is not a numeric vector
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testArgsCasts#
+#{ .Internal(sort(NULL, FALSE)) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testArgsCasts#
+#{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }
+Error: only atomic vectors can be sorted
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_qsort.testqsort1#
 #argv <- list(3L, FALSE); .Internal(qsort(argv[[1]], argv[[2]]))
 [1] 3
@@ -43830,6 +43854,14 @@ Levels: a b
 [1] a b a a b a a b a
 Levels: a b
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRepLenNull#
+#rep_len(NULL,0)
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRepLenNull#
+#rep_len(NULL,2)
+Error in rep_len(NULL, 2) : cannot replicate NULL to a non-zero length
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testrep1#
 #argv <- list(NA, 7); .Internal(rep_len(argv[[1]], argv[[2]]))
 [1] NA NA NA NA NA NA NA
@@ -44219,6 +44251,10 @@ character(0)
 #{ rep.int(7, "7") }
 [1] 7 7 7 7 7 7 7
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
+#{ rep.int(7, -4)  }
+Error in rep.int(7, -4) : invalid 'times' value
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
 #{ rep.int(7, NA)  }
 Error in rep.int(7, NA) : invalid 'times' value
@@ -44255,6 +44291,14 @@ Error in rep.int(c(1, 2, 3), c(2, 8)) : invalid 'times' value
 #{ rep.int(c(1,2,3),c(2,8,3)) }
  [1] 1 1 2 2 2 2 2 2 2 2 3 3 3
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
+#{ rep.int(c(7,1), c(1,-4))  }
+Error in rep.int(c(7, 1), c(1, -4)) : invalid 'times' value
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#
+#{ rep.int(c(7,1), c(1,4,5))  }
+Error in rep.int(c(7, 1), c(1, 4, 5)) : invalid 'times' value
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepInt#Output.IgnoreErrorContext#
 #{ rep.int(function() 42, 7) }
 Error in rep.int(function() 42, 7) :
@@ -44268,6 +44312,30 @@ Error in rep.int(function() 42, 7) :
 #{ rep_int(7, function() 42) }
 Error: could not find function "rep_int"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex#
+#{ rep.int(c(1+2i,100-400i,20+30i), c(3,-7)) }
+Error in rep.int(c(1 + (0+2i), 100 - (0+400i), 20 + (0+30i)), c(3, -7)) :
+  invalid 'times' value
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex#
+#{ rep.int(c(1+2i,100-400i,20+30i), c(3,7)) }
+Error in rep.int(c(1 + (0+2i), 100 - (0+400i), 20 + (0+30i)), c(3, 7)) :
+  invalid 'times' value
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex#
+#{ rep.int(c(1+2i,100-400i,20+30i), c(3,7,2)) }
+ [1]   1+  2i   1+  2i   1+  2i 100-400i 100-400i 100-400i 100-400i 100-400i
+ [9] 100-400i 100-400i  20+ 30i  20+ 30i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex#
+#{ rep.int(c(1+2i,20+30i,100-400i), -3) }
+Error in rep.int(c(1 + (0+2i), 20 + (0+30i), 100 - (0+400i)), -3) :
+  invalid 'times' value
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testRepIntComplex#
+#{ rep.int(c(1+2i,20+30i,100-400i), 2) }
+[1]   1+  2i  20+ 30i 100-400i   1+  2i  20+ 30i 100-400i
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testrepint1#
 #argv <- list(1, 6); .Internal(rep.int(argv[[1]], argv[[2]]))
 [1] 1 1 1 1 1 1
@@ -44953,6 +45021,39 @@ numeric(0)
 #argv <- structure(list(x = structure(list(x = 3:4), .Names = 'x',     row.names = c(NA, -2L), class = 'data.frame')), .Names = 'x');do.call('row.names.data.frame', argv)
 [1] "1" "2"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" } else { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug))) }
+Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" } else { { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); } }
+Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage#
+#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug)))
+Error in .Internal(rowsum_matrix(x, , ug, FALSE, as.character(ug))) :
+  argument 2 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage#
+#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, , FALSE,as.character(ug)))
+Error in .Internal(rowsum_matrix(x, g, , FALSE, as.character(ug))) :
+  argument 3 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage#
+#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, NULL, FALSE,as.character(ug)))
+Error: unimplemented type 'NULL' in 'HashTableSetup'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage#
+#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, print, FALSE, as.character(ug)))
+Error: unimplemented type 'closure' in 'HashTableSetup'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#
+#x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, ug, FALSE, as.character(ug)))
+  [,1] [,2]
+1    6   16
+2    6   16
+3    3    8
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testrowsum1#
 #argv <- list(structure(1:12, .Dim = 3:4), c('Y', 'X', 'Y'), c('X', 'Y'), FALSE, c('X', 'Y')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
   [,1] [,2] [,3] [,4]
@@ -45121,10 +45222,30 @@ Error: invalid first argument
 #set.seed(42); .Internal(sample(4.5e20, 4.5e20, FALSE, NULL))
 Error: vector size specified is too large
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorMessage#
+#set.seed(42); .Internal(sample(5,6,T,))
+Error in .Internal(sample(5, 6, T, )) : argument 4 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
+#set.seed(42); .Internal(sample(5,6,T,NULL))
+[1] 5 5 2 5 4 3
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#Output.IgnoreErrorMessage#
+#set.seed(42); .Internal(sample(5,6,T,seq(1.2,3)))
+Error: incorrect number of probabilities
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
 #set.seed(42); .Internal(sample(NA, NA, FALSE, NULL))
 Error: invalid first argument
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
+#set.seed(42); .Internal(sample(NULL, NULL, F, NULL))
+Error: invalid first argument
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
+#set.seed(42); .Internal(sample(NULL, NULL, F, seq(1.2,3)))
+Error: invalid first argument
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testArgsCasts#
 #set.seed(42); .Internal(sample(NaN, NaN, FALSE, NULL))
 Error: vector size cannot be NA/NaN
@@ -45360,6 +45481,10 @@ Error: invalid first argument
  [1] 3794143200 1186759075 2661629063 3054987943 2724864852 1898476583
  [7] 3876537848 1917352029 4057178109 1970042664
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample2.testSample2#
+#set.seed(42);  .Internal(sample2(NULL,3))
+Error: invalid first argument
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sample2.testSample2#
 #set.seed(42);  x <- .Internal(sample2(10L, 3L)); y <- .Internal(sample2(10L, 3L)); list(x, y); 
 [[1]]
@@ -45400,6 +45525,27 @@ attr(,"scaled:scale")
 [1] 0.3602647 0.2569776 0.2098340 0.2739593 0.2779866 0.2412907 0.3059602
 [8] 0.3354207 0.3088318
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts#Output.IgnoreErrorContext#
+#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, , 2, ' ', '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) }
+Error in .Internal(scan(con, , 2, " ", ".", "\"", 0, 3, "NA", F, F, F,  :
+  argument 2 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts#
+#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, 1L, 2, NULL, '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) }
+[1] 1 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts#
+#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, NULL, 2, ' ', '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) }
+Error: invalid 'what' argument
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts#
+#{ con<-textConnection(c("1 2 3", "4 5 6")); .Internal(scan(con, print, 2, ' ', '.', '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) }
+Error: invalid 'what' argument
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testArgsCasts#
+#{ con<-textConnection(c("1.5 2.89 3", "4 5 6")); .Internal(scan(con, 1.2, 2, ' ', NULL, '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) }
+[1] 1.50 2.89
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#
 #{ con<-textConnection(c("'foo'")); scan(con, what=list("")) }
 Read 1 record
@@ -59043,6 +59189,10 @@ integer(0)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_setHook.testsetHook1#Ignored.SideEffects#
 #argv <- structure(list(hookName = 'UserHook::stats4::onUnload',     value = function(pkgname, ...) cat('onUnload', sQuote(pkgname),         'B', '\n')), .Names = c('hookName', 'value'));do.call('setHook', argv)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object#
+#{ x<-42; asS4(, TRUE, 1)) }
+Error: unexpected ')' in "{ x<-42; asS4(, TRUE, 1))"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testSetS4Object#
 #{ x<-42; asS4(x, "TRUE") }
 [1] 42
@@ -59931,6 +60081,14 @@ In sinpi(argv[[1]]) : NaNs produced
 [4,] -0.6666667  1.3333333   -2  2.6666667 -1.3333333
 [5,]  0.3333333 -0.6666667    1 -1.3333333  1.6666667
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts#
+#{ .Internal(sort(NULL, FALSE)) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts#
+#{ .Internal(sort(as.raw(c(0x44,0x40)), FALSE)) }
+Error: raw vectors cannot be sorted
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts#
 #{ .Internal(sort(c(1L,10L,2L), 'not-numeric')) }
 Error: 'decreasing' must be TRUE or FALSE
@@ -59939,6 +60097,10 @@ Error: 'decreasing' must be TRUE or FALSE
 #{ .Internal(sort(c(1L,10L,2L), NULL)) }
 Error: 'decreasing' must be TRUE or FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testArgsCasts#
+#{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }
+Error: only atomic vectors can be sorted
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testSort#
 #{ sort(3:1, index.return=TRUE) }
 $x
@@ -61542,6 +61704,18 @@ B FALSE TRUE
 [2,]    1
 [3,]    2
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#
+#{ .Internal(strptime('','',) }
+Error: unexpected '}' in "{ .Internal(strptime('','',) }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#
+#{ .Internal(strptime('',,'') }
+Error: unexpected '}' in "{ .Internal(strptime('',,'') }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#
+#{ .Internal(strptime(,'','') }
+Error: unexpected '}' in "{ .Internal(strptime(,'','') }"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime1#
 #argv <- list('2008-04-22 09:45', '%Y-%m-%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]]))
 [1] "2008-04-22 GMT"
@@ -61608,6 +61782,22 @@ character(0)
 [1] "1890-01-01 GMT" "1891-01-01 GMT" "1892-01-01 GMT" "1893-01-01 GMT"
 [5] "1894-01-01 GMT" "1895-01-01 GMT"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep('aa', NULL) } }
+Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep('aa', NULL) }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep(NULL, 5) } }
+Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep(NULL, 5) }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
+#{ .Internal(strrep('', ) }
+Error: unexpected '}' in "{ .Internal(strrep('', ) }"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
+#{ .Internal(strrep(, '') }
+Error: unexpected '}' in "{ .Internal(strrep(, '') }"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testStrrep#
 #{ strrep("ABC", 2) }
 [1] "ABCABC"
@@ -62078,6 +62268,14 @@ character(0)
 #argv <- list(character(0), 8L); .Internal(strtoi(argv[[1]], argv[[2]]))
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.testArgsCasts#Output.IgnoreErrorContext#
+#.Internal(strtrim('abc', ))
+Error in .Internal(strtrim("abc", )) : argument 2 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.testArgsCasts#
+#.Internal(strtrim('abc', NULL))
+Error: invalid 'width' argument
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strtrim.teststrtrim#
 #v <- c('a', 'fooooo', 'bbbbbb', 'cccccccccc', 'dd', NA); names(v) <- as.character(1:6); strtrim(v, c(2, 5))
       1       2       3       4       5       6
@@ -65775,6 +65973,10 @@ tracemem[0x7f878bbeec90 -> 0x7f878bbeeb28]:
 tracemem[<0x7faf1a058090> -> 0x7faf191a98a8]:
 tracemem[0x7faf191a98a8 -> 0x7faf191a98e0]:
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.retracemem#Output.ContainsReferences#
+#x<-1:10; retracemem(x, c("first", "second")) 
+tracemem[first -> 0x1d805c0]:
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors#Output.ContainsReferences#
 #v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84
 [1] "<0x7ff2cd448c90>"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java
index 3052a9db90..ae148fb1ac 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_psort.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -92,4 +92,12 @@ public class TestBuiltin_psort extends TestBase {
     public void testpsort14() {
         assertEval("argv <- list(c(-1.36919169254062, -0.667819876370237, -0.253162069270378, -0.0834190388782434, -0.00786394222146348, 0.0246733498130512, 0.0730305465518564, 0.0881443844426084, 0.170711734013213, 0.552921941721332), c(1L, 3L, 4L, 5L, 6L, 7L, 8L, 10L)); .Internal(psort(argv[[1]], argv[[2]]))");
     }
+
+    @Test
+    public void testArgsCasts() {
+        assertEval("{ .Internal(psort(as.raw(c(0x44,0x40)), FALSE)) }"); // Only numeric vectors can
+                                                                         // be sorted
+        assertEval("{ .Internal(sort(NULL, FALSE)) }");
+        assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java
index 2f586449ad..f9676194a0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_qsort.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -82,4 +82,17 @@ public class TestBuiltin_qsort extends TestBase {
     public void testqsort13() {
         assertEval("argv <- list(c(63, 187, 64, 188), FALSE); .Internal(qsort(argv[[1]], argv[[2]]))");
     }
+
+    @Test
+    public void testArgsCasts() {
+        // GnuR "qsort" outputs
+        // "Error: argument is not a numeric vector"
+        // for the raw vector while both "sort" and "qsort" in GnuR output
+        // "Error: raw vectors cannot be sorted"
+        // We share the same Casts adapter for all "sort","psort" and "qsort"
+        // so prefixing with ignore the error message here for now.
+        assertEval(Output.IgnoreErrorMessage, "{ .Internal(qsort(as.raw(c(0x44,0x40)), FALSE)) }");
+        assertEval("{ .Internal(sort(NULL, FALSE)) }");
+        assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
index b8e0d6b946..b5dbe71e52 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
@@ -112,6 +112,12 @@ public class TestBuiltin_rep extends TestBase {
         assertEval("argv <- list(FALSE, 1L); .Internal(rep_len(argv[[1]], argv[[2]]))");
     }
 
+    @Test
+    public void testRepLenNull() {
+        assertEval("rep_len(NULL,0)");
+        assertEval("rep_len(NULL,2)");
+    }
+
     @Test
     public void testrep21() {
         assertEval("argv <- structure(list(1:5, each = 2), .Names = c('', 'each'));do.call('rep', argv)");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
index 7a99ff8e09..c6a77e41ad 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
@@ -173,5 +173,18 @@ public class TestBuiltin_repint extends TestBase {
         assertEval("{ rep.int(7, c(7, 42)) }");
         assertEval("{ rep_int(7, function() 42) }");
         assertEval("{ rep.int(7, NA)  }");
+        assertEval("{ rep.int(7, -4)  }");
+        assertEval("{ rep.int(c(7,1), c(1,-4))  }");
+        assertEval("{ rep.int(c(7,1), c(1,4,5))  }");
     }
+
+    @Test
+    public void testRepIntComplex() {
+        assertEval("{ rep.int(c(1+2i,20+30i,100-400i), 2) }");
+        assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,7,2)) }");
+        assertEval("{ rep.int(c(1+2i,20+30i,100-400i), -3) }");
+        assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,7)) }");
+        assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,-7)) }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java
index 9e5d90ea94..7179dd4688 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -58,4 +58,23 @@ public class TestBuiltin_rowsum extends TestBase {
     public void testrowsum8() {
         assertEval("argv <- list(structure(c(1.33333333333333, -1.33333333333333, 1, 1.33333333333333, -2, 0.666666666666667, -0.666666666666667, 0.666666666666667, -0.666666666666667), .Dim = c(9L, 1L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9'), 'x')), structure(c(1, 1, 2, 2, 2, 2, 3, 4, 5), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9')), c(1, 2, 3, 4, 5), FALSE, c('1', '2', '3', '4', '5')); .Internal(rowsum_matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
+
+    @Test
+    public void testRowsumArgCoverage() {
+        assertEval("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, ug, FALSE, as.character(ug)))");
+        // 2nd parm function => GnuR Error: segfault
+        assertEvalFastR("{ x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); }",
+                        "cat(\"Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\"");
+        // 3rd parm is function => GnuR Error: "Error: unimplemented type 'closure' in
+        // 'HashTableSetup'"
+        assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, print, FALSE, as.character(ug)))");
+        // 2nd parm NULL => GnuR Error: segfault\n" +
+        assertEvalFastR("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug)))",
+                        "cat(\"Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\"");
+        // 3rd parm NULL => GnuR Error: Error: unimplemented type 'NULL' in 'HashTableSetup'
+        assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, NULL, FALSE,as.character(ug)))");
+        assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug)))");
+        assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, , FALSE,as.character(ug)))");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
index 1531169e52..e15202aaa8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
@@ -81,6 +81,11 @@ public class TestBuiltin_sample extends TestBase {
         assertEval("set.seed(42); .Internal(sample(4.5e20, 4.5e20, FALSE, NULL))");
         assertEval("set.seed(42); .Internal(sample(NA, NA, FALSE, NULL))");
         assertEval("set.seed(42); .Internal(sample(NaN, NaN, FALSE, NULL))");
+        assertEval("set.seed(42); .Internal(sample(NULL, NULL, F, NULL))");
+        assertEval("set.seed(42); .Internal(sample(NULL, NULL, F, seq(1.2,3)))");
+        assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(5,6,T,))");
+        assertEval("set.seed(42); .Internal(sample(5,6,T,NULL))");
+        assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(5,6,T,seq(1.2,3)))");
         // Note: we treat Infinity in NaN check
         assertEval(Output.IgnoreErrorMessage, "set.seed(42); .Internal(sample(1/0, 1, FALSE, NULL))");
         // size
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java
index 36d5e2badf..bd9ea049bb 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample2.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@ public class TestBuiltin_sample2 extends TestBase {
         assertEval("set.seed(42);  x <- .Internal(sample2(10L, 3L)); y <- .Internal(sample2(10L, 3L)); list(x, y); ");
         // test with n > MAX_INT
         assertEval("set.seed(42);  .Internal(sample2(4147483647, 10))");
+        assertEval("set.seed(42);  .Internal(sample2(NULL,3))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
index 7856a43ce5..7f9cf822a1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
@@ -49,4 +49,19 @@ public class TestBuiltin_scan extends TestBase {
         assertEval("{ con<-textConnection(c(\"'foo'\")); scan(con, what=list(\"\")) }");
         assertEval("{ con<-textConnection(c(\"bar 'foo'\")); scan(con, what=list(\"\")) }");
     }
+
+    @Test
+    public void testArgsCasts() {
+        // Empty 2nd 'what' parameter
+        assertEval(Output.IgnoreErrorContext, "{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, , 2, ' ', '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }");
+        // NULL 2nd 'what' parameter
+        assertEval("{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, NULL, 2, ' ', '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }");
+        // function passed as 2nd 'what' parameter
+        assertEval("{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, print, 2, ' ', '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }");
+        // NULL 4th 'sep' parameter
+        assertEval("{ con<-textConnection(c(\"1 2 3\", \"4 5 6\")); .Internal(scan(con, 1L, 2, NULL, '.', '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }");
+        // NULL 5th 'dec' parameter
+        assertEval("{ con<-textConnection(c(\"1.5 2.89 3\", \"4 5 6\")); .Internal(scan(con, 1.2, 2, ' ', NULL, '\"', 0, 3, \"NA\", F, F, F, T, T, '', '#', T, 'utf8', F)) }");
+
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java
index e12192437a..e74b1ef0db 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java
@@ -107,5 +107,6 @@ public class TestBuiltin_setS4Object extends TestBase {
         assertEval("{ x<-42; asS4(x, TRUE, \"1\") }");
         assertEval("{ x<-42; asS4(x, TRUE, logical()) }");
         assertEval("{ x<-42; asS4(x, TRUE, c(1,2)) }");
+        assertEval("{ x<-42; asS4(, TRUE, 1)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java
index e3e5bf0fb2..96970b11a2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -125,5 +125,9 @@ public class TestBuiltin_sort extends TestBase {
     public void testArgsCasts() {
         assertEval("{ .Internal(sort(c(1L,10L,2L), 'not-numeric')) }");
         assertEval("{ .Internal(sort(c(1L,10L,2L), NULL)) }");
+        assertEval("{ .Internal(sort(as.raw(c(0x44,0x40)), FALSE)) }"); // Only numeric vectors can
+                                                                        // be sorted
+        assertEval("{ .Internal(sort(NULL, FALSE)) }");
+        assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java
index 326baff3c4..0c3fa4db12 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -66,4 +66,12 @@ public class TestBuiltin_strptime extends TestBase {
     public void teststrptime10() {
         assertEval("argv <- list(c('1937/01/01', '1916/01/01', '1913/01/01', '1927/01/01', '1947/01/01', '1913/01/01', '1917/01/01', '1923/01/01', '1921/01/01', '1926/01/01', '1920/01/01', '1915/01/01', '1914/01/01', '1914/01/01', '1914/01/01', '1919/01/01', '1948/01/01', '1911/01/01', '1909/01/01', '1913/01/01', '1925/01/01', '1926/01/01', '1910/01/01', '1917/01/01', '1936/01/01', '1938/01/01', '1960/01/01', '1915/01/01', '1919/01/01', '1924/01/01', '1914/01/01', '1905/01/01', '1921/01/01', '1929/01/01', '1926/01/01', '1921/01/01', '1908/01/01', '1928/01/01', '1919/01/01', '1921/01/01', '1925/01/01', '1934/01/01', '1927/01/01', '1928/01/01', '1934/01/01', '1922/01/01', '1923/01/01', '1915/01/01', '1934/01/01', '1925/01/01', '1922/01/01', '1930/01/01', '1924/01/01', '1923/01/01', '1919/01/01', '1932/01/01', '1930/01/01', '1923/01/01', '1930/01/01', '1922/01/01', '1919/01/01', '1932/01/01', '1939/01/01', '1923/01/01', '1920/01/01', '1919/01/01', '1952/01/01', '1927/01/01', '1924/01/01', '1919/01/01', '1925/01/01', '1945/01/01', '1916/01/01', '1943/01/01', '1920/01/01', '1920/01/01', '1931/01/01', '1924/01/01', '1919/01/01', '1926/01/01', '1920/01/01', '1952/01/01', '1919/01/01', '1930/01/01', '1925/01/01', '1924/01/01', '1926/01/01', '1918/01/01', '1922/01/01', '1921/01/01', '1925/01/01', '1928/01/01', '1925/01/01', '1929/01/01', '1933/01/01', '1947/01/01', '1950/01/01', '1945/01/01', '1924/01/01', '1939/01/01', '1924/01/01', '1933/01/01', '1928/01/01'), '%Y/%m/%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]]))");
     }
+
+    @Test
+    public void testArgsCasts() {
+        assertEval("{ .Internal(strptime(,'','') }");
+        assertEval("{ .Internal(strptime('',,'') }");
+        assertEval("{ .Internal(strptime('','',) }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java
index 61cf4022fe..818a0413bd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,4 +34,15 @@ public class TestBuiltin_strrep extends TestBase {
         assertEval("{ strrep(c(\"A\", \"B\", \"C\"), 1 : 3) }");
         assertEval("{ strrep(\"X\", 1 : 5) }");
     }
+
+    @Test
+    public void testArgsCasts() {
+        // GnuR fails with segfault
+        assertEvalFastR("{ .Internal(strrep(NULL, 5) }", "cat(\"character(0)\")");
+        // GnuR - infinite loop
+        assertEvalFastR("{ .Internal(strrep('aa', NULL) }", "cat(\"character(0)\")");
+        assertEval("{ .Internal(strrep(, '') }");
+        assertEval("{ .Internal(strrep('', ) }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java
index 00fc2dc521..6746ef0f15 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strtrim.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -57,4 +57,10 @@ public class TestBuiltin_strtrim extends TestBase {
         assertEval("v <- c('a', 'fooooo', 'bbbbbb', 'cccccccccc', 'dd', NA); names(v) <- as.character(1:6); strtrim(v, c(2L, 5L))");
         assertEval("v <- c('a', 'fooooo', 'bbbbbb', 'cccccccccc', 'dd', NA); names(v) <- as.character(1:6); strtrim(v, c(2, 5))");
     }
+
+    @Test
+    public void testArgsCasts() {
+        assertEval(".Internal(strtrim('abc', NULL))");
+        assertEval(Output.IgnoreErrorContext, ".Internal(strtrim('abc', ))");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java
index 7b4e4e6f41..dbe3342863 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,5 +54,6 @@ public class TestBuiltin_tracemem extends TestBase {
         // intended semantics of retracemem is not clear, this tests what is definitely intended:
         // retracemem starts tracing of its first argument
         assertEval(Output.ContainsReferences, "v <- c(1,10,100); tracemem(v); x <- v[-1]; retracemem(x, retracemem(v)); u <- x; u[[1]] <- 42;");
+        assertEval(Output.ContainsReferences, "x<-1:10; retracemem(x, c(\"first\", \"second\")) ");
     }
 }
-- 
GitLab


From 40c69cae0d11da6d34842919630981b7645458d0 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 2 Mar 2017 15:57:24 +0100
Subject: [PATCH 090/402] handle non-FunctionDefinitionNode in Body

---
 .../oracle/truffle/r/nodes/builtin/base/Body.java | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
index 53812789a2..47bfc87caf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
@@ -25,7 +25,10 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
@@ -41,9 +44,15 @@ public abstract class Body extends RBuiltinNode {
     }
 
     @Specialization
-    protected Object doBody(RFunction fun) {
-        FunctionDefinitionNode fdn = (FunctionDefinitionNode) fun.getRootNode();
-        return RASTUtils.createLanguageElement(fdn.getBody());
+    protected Object doBody(RFunction fun,
+                    @Cached("createBinaryProfile()") ConditionProfile profile) {
+        RootNode root = fun.getRootNode();
+        if (profile.profile(root instanceof FunctionDefinitionNode)) {
+            FunctionDefinitionNode fdn = (FunctionDefinitionNode) root;
+            return RASTUtils.createLanguageElement(fdn.getBody());
+        } else {
+            return RNull.instance;
+        }
     }
 
     @Specialization(guards = "!isRFunction(fun)")
-- 
GitLab


From 8dbd2e765c7d47c217533df71636247aac23ceb5 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 2 Mar 2017 10:17:23 +0100
Subject: [PATCH 091/402] remove special handling of @<- and slot<- in
 replacements

---
 .../r/nodes/builtin/base/BasePackage.java     |   3 +
 .../r/nodes/builtin/base/UpdateSlot.java      | 146 ++++++++----------
 .../nodes/builtin/fastr/FastRSlotAssign.java  |  78 ++++++++++
 .../builtin/methods/R/methods_overrides.R     |  26 ++++
 .../r/nodes/access/UpdateSlotNode.java        |  12 +-
 .../r/nodes/control/ReplacementNode.java      |  67 ++++----
 .../r/nodes/unary/GetNonSharedNode.java       |  19 +--
 .../com/oracle/truffle/r/runtime/RError.java  |   1 +
 .../truffle/r/runtime/data/RPromise.java      |  23 ++-
 9 files changed, 241 insertions(+), 134 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java
 create mode 100644 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index f3119ba912..987209e766 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -99,6 +99,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSource;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSourceNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfo;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfoNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRSlotAssign;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRSlotAssignNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTrace;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTraceNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfAttr;
@@ -375,6 +377,7 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRProfAttr.class, FastRStatsFactory.FastRProfAttrNodeGen::create);
         add(FastRProfTypecounts.class, FastRStatsFactory.FastRProfTypecountsNodeGen::create);
         add(FastRProfFuncounts.class, FastRStatsFactory.FastRProfFuncountsNodeGen::create);
+        add(FastRSlotAssign.class, FastRSlotAssignNodeGen::create);
         add(FastRSyntaxTree.class, FastRSyntaxTreeNodeGen::create);
         add(FastRThrowIt.class, FastRThrowItNodeGen::create);
         add(FastRTrace.Trace.class, FastRTraceFactory.TraceNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
index 97584d822e..684d9ce1e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
@@ -22,14 +22,12 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.UpdateSlotNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
-import com.oracle.truffle.r.nodes.function.RCallNode;
-import com.oracle.truffle.r.nodes.function.WrapArgumentNode;
 import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RCaller;
@@ -38,105 +36,91 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "@<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, nonEvalArgs = 1, behavior = COMPLEX)
 public abstract class UpdateSlot extends RBuiltinNode {
 
-    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("cl", "name", "valueClass");
-
-    @CompilationFinal private RFunction checkSlotAssignFunction;
-    @Child private ClassHierarchyNode objClassHierarchy;
-    @Child private ClassHierarchyNode valClassHierarchy;
     @Child private UpdateSlotNode updateSlotNode = com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen.create();
-    @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment");
-    @Child private CallRFunctionNode checkAtAssignmentCall;
-    private final ConditionProfile cached = ConditionProfile.createBinaryProfile();
 
     static {
         Casts casts = new Casts(UpdateSlot.class);
         casts.arg(0).asAttributable(true, true, true);
     }
 
-    protected String getName(Object nameObj) {
-        assert nameObj instanceof RPromise;
-        Object rep = ((RPromise) nameObj).getRep();
-        if (rep instanceof WrapArgumentNode) {
-            rep = ((WrapArgumentNode) rep).getOperand();
-        }
-        if (rep instanceof ConstantNode) {
-            Object val = ((ConstantNode) rep).getValue();
-            if (val instanceof String) {
-                return (String) val;
-            }
-            if (val instanceof RSymbol) {
-                return ((RSymbol) val).getName();
+    protected String getName(RPromise nameObj) {
+        Closure closure = nameObj.getClosure();
+        if (closure.asSymbol() != null) {
+            return closure.asSymbol();
+        } else if (closure.asStringConstant() != null) {
+            return closure.asStringConstant();
+        } else {
+            CompilerDirectives.transferToInterpreter();
+            RSyntaxElement element = closure.getExpr().asRSyntaxNode();
+            assert !(element instanceof RSyntaxLookup);
+            if (element instanceof RSyntaxConstant) {
+                throw error(RError.Message.SLOT_INVALID_TYPE, Predef.typeName().apply(((RSyntaxConstant) element).getValue()));
+            } else {
+                throw error(RError.Message.SLOT_INVALID_TYPE, "language");
             }
-        } else if (rep instanceof ReadVariableNode) {
-            return ((ReadVariableNode) rep).getIdentifier();
-        } else if (rep instanceof RCallNode) {
-            throw error(RError.Message.SLOT_INVALID_TYPE, "language");
         }
-        // TODO: this is not quite correct, but I wonder if we even reach here (can also be
-        // augmented on demand)
-        throw error(RError.Message.SLOT_INVALID_TYPE, nameObj.getClass().toString());
     }
 
-    private void checkSlotAssign(VirtualFrame frame, Object object, String name, Object value) {
-        // TODO: optimize using a mechanism similar to overrides?
-        if (checkSlotAssignFunction == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame);
-        }
-        if (checkAtAssignmentCall == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget()));
-        }
-        if (objClassHierarchy == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
-        }
-        if (valClassHierarchy == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
-        }
-        RStringVector objClass = objClassHierarchy.execute(object);
-        RStringVector valClass = valClassHierarchy.execute(value);
-        RFunction currentFunction = (RFunction) checkAtAssignmentFind.execute(frame);
-        if (cached.profile(currentFunction == checkSlotAssignFunction)) {
-            // TODO: technically, someone could override checkAtAssignment function and access the
-            // caller, but it's rather unlikely
-            checkAtAssignmentCall.execute(frame, checkSlotAssignFunction, RCaller.create(frame, getOriginalCall()), null, new Object[]{objClass, name, valClass}, SIGNATURE,
-                            checkSlotAssignFunction.getEnclosingFrame(), null);
-        } else {
-            // slow path
-            RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, objClass, name, valClass);
-        }
-    }
+    public static final class CheckSlotAssignNode extends RBaseNode {
 
-    /*
-     * Motivation for cached version is that in the operator form (foo@bar<-baz), the name is an
-     * interned string which allows us to avoid longer lookup
-     */
-    @Specialization(guards = "sameName(nameObj, nameObjCached)")
-    protected Object updateSlotCached(VirtualFrame frame, Object object, @SuppressWarnings("unused") Object nameObj, Object value, @SuppressWarnings("unused") @Cached("nameObj") Object nameObjCached,
-                    @Cached("getName(nameObjCached)") String name) {
-        checkSlotAssign(frame, object, name, value);
-        return updateSlotNode.executeUpdate(object, name, value);
+        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("cl", "name", "valueClass");
+
+        @CompilationFinal private RFunction checkSlotAssignFunction;
+        @Child private ClassHierarchyNode objClassHierarchy;
+        @Child private ClassHierarchyNode valClassHierarchy;
+        @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment");
+        @Child private CallRFunctionNode checkAtAssignmentCall;
+
+        private final ConditionProfile cached = ConditionProfile.createBinaryProfile();
+
+        public void execute(VirtualFrame frame, Object object, String name, Object value) {
+            if (checkSlotAssignFunction == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                checkSlotAssignFunction = (RFunction) checkAtAssignmentFind.execute(frame);
+            }
+            if (checkAtAssignmentCall == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                checkAtAssignmentCall = insert(CallRFunctionNode.create(checkSlotAssignFunction.getTarget()));
+            }
+            if (objClassHierarchy == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                objClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
+            }
+            if (valClassHierarchy == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                valClassHierarchy = insert(ClassHierarchyNodeGen.create(true, false));
+            }
+            RStringVector objClass = objClassHierarchy.execute(object);
+            RStringVector valClass = valClassHierarchy.execute(value);
+            RFunction currentFunction = (RFunction) checkAtAssignmentFind.execute(frame);
+            if (cached.profile(currentFunction == checkSlotAssignFunction)) {
+                // TODO: technically, someone could override checkAtAssignment function and access
+                // the caller, but it's rather unlikely
+                checkAtAssignmentCall.execute(frame, checkSlotAssignFunction, RCaller.createInvalid(frame), null, new Object[]{objClass, name, valClass}, SIGNATURE,
+                                checkSlotAssignFunction.getEnclosingFrame(), null);
+            } else {
+                // slow path
+                RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.createInvalid(frame), null, objClass, name, valClass);
+            }
+        }
     }
 
-    @Specialization(replaces = "updateSlotCached")
-    protected Object updateSlot(VirtualFrame frame, Object object, Object nameObj, Object value) {
+    @Specialization
+    protected Object updateSlot(VirtualFrame frame, Object object, RPromise nameObj, Object value,
+                    @Cached("new()") CheckSlotAssignNode check) {
         String name = getName(nameObj);
-        checkSlotAssign(frame, object, name, value);
+        check.execute(frame, object, name, value);
         return updateSlotNode.executeUpdate(object, name, value);
     }
-
-    protected boolean sameName(Object nameObj, Object nameObjCached) {
-        assert nameObj instanceof RPromise;
-        assert nameObjCached instanceof RPromise;
-        return ((RPromise) nameObj).getRep() == ((RPromise) nameObjCached).getRep();
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java
new file mode 100644
index 0000000000..4bf687e14f
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.fastr;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.runtime.RVisibility.ON;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.access.UpdateSlotNode;
+import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.UpdateAttr.InternStringNode;
+import com.oracle.truffle.r.nodes.builtin.base.UpdateAttrNodeGen.InternStringNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.UpdateSlot.CheckSlotAssignNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RMissing;
+
+@RBuiltin(name = ".fastr.methods.slotassign", visibility = ON, kind = PRIMITIVE, parameterNames = {"object", "name", "check", "value"}, behavior = COMPLEX)
+public abstract class FastRSlotAssign extends RBuiltinNode {
+
+    static {
+        Casts casts = new Casts(FastRSlotAssign.class);
+        casts.arg("object").mustNotBeNull();
+        casts.arg("name").defaultError(Message.SLOT_INVALID_TYPE_OR_LEN).mustNotBeMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        casts.arg("check").mustNotBeMissing().asLogicalVector().findFirst().mustNotBeNA(Message.NA_UNEXP).map(toBoolean());
+        casts.arg("value").mustNotBeMissing();
+    }
+
+    @Child private InternStringNode intern = InternStringNodeGen.create();
+    @Child private UpdateSlotNode updateSlotNode = UpdateSlotNodeGen.create();
+
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_TRUE, RMissing.instance};
+    }
+
+    @Specialization(guards = "check")
+    public Object assign(VirtualFrame frame, Object object, String name, @SuppressWarnings("unused") boolean check, Object value,
+                    @Cached("new()") CheckSlotAssignNode checkNode) {
+        String interned = intern.execute(name);
+        checkNode.execute(frame, object, interned, value);
+        return updateSlotNode.executeUpdate(object, interned, value);
+    }
+
+    @Specialization(guards = "!check")
+    public Object assign(Object object, String name, @SuppressWarnings("unused") boolean check, Object value) {
+        String interned = intern.execute(name);
+        return updateSlotNode.executeUpdate(object, interned, value);
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R
new file mode 100644
index 0000000000..99c947a62d
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R
@@ -0,0 +1,26 @@
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+eval(expression({
+# this function is replaced with a primitive because it is expected to
+# modify its argument in-place, which can clash with argument refcount handling
+`slot<-` <- .fastr.methods.slotassign
+}), asNamespace("methods"))
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java
index 4cd1ffa866..59d8ab2c49 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java
@@ -15,7 +15,6 @@ package com.oracle.truffle.r.nodes.access;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.runtime.RCaller;
@@ -32,6 +31,8 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class UpdateSlotNode extends RBaseNode {
 
+    private static final String SET_DATA_PART = "setDataPart";
+
     public abstract Object executeUpdate(Object object, String name, Object value);
 
     protected SetAttributeNode createAttrUpdate() {
@@ -56,12 +57,9 @@ public abstract class UpdateSlotNode extends RBaseNode {
     protected Object updateSlotS4Data(RAttributable object, @SuppressWarnings("unused") String name, Object value) {
         // TODO: any way to cache it or use a mechanism similar to overrides?
         REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods");
-        String identifier = "setDataPart";
-        Object f = methodsNamespace.findFunction(identifier);
-        RFunction dataPart = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(identifier, f);
-        return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), null, object,
-                        prepareValue(value),
-                        RRuntime.LOGICAL_TRUE);
+        Object f = methodsNamespace.findFunction(SET_DATA_PART);
+        RFunction dataPart = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(SET_DATA_PART, f);
+        return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.createInvalid(null), null, object, prepareValue(value), RRuntime.LOGICAL_TRUE);
     }
 
     protected boolean isData(String name) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index a6bb499839..13c607e358 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -80,8 +80,12 @@ abstract class ReplacementNode extends OperatorNode {
         }
     }
 
-    private static String getTargetTmpName(int tempNamesStartIndex) {
-        return "*tmp*" + tempNamesStartIndex;
+    private static String getTargetTemp(int index) {
+        return "*tmp*" + index;
+    }
+
+    private static String getRHSTemp(int index) {
+        return "*rhs*" + index;
     }
 
     private static boolean hasOnlySpecialCalls(List<RSyntaxCall> calls) {
@@ -133,11 +137,6 @@ abstract class ReplacementNode extends OperatorNode {
         if (syntaxLHS instanceof RSyntaxLookup) {
             RSyntaxLookup lookupLHS = (RSyntaxLookup) syntaxLHS;
             String symbol = lookupLHS.getIdentifier();
-            if ("slot".equals(symbol) || "@".equals(symbol)) {
-                // this is pretty gross, but at this point seems like the only way to get setClass
-                // to work properly
-                argNodes[0] = new GetNonSharedNode.GetNonSharedSyntaxNode(argNodes[0].asRNode());
-            }
             newSyntaxLHS = builder.lookup(lookupLHS.getLazySourceSection(), symbol + "<-", true);
         } else {
             // data types (and lengths) are verified in isNamespaceLookupCall
@@ -171,8 +170,8 @@ abstract class ReplacementNode extends OperatorNode {
             super(source, operator, lhs);
             this.rhs = rhs;
 
-            this.storeRhs = WriteVariableNode.createAnonymous("*rhs*" + tempNamesStartIndex, WriteVariableNode.Mode.INVISIBLE, rhs);
-            this.removeRhs = RemoveAndAnswerNode.create("*rhs*" + tempNamesStartIndex);
+            this.storeRhs = WriteVariableNode.createAnonymous(getRHSTemp(tempNamesStartIndex), WriteVariableNode.Mode.INVISIBLE, rhs);
+            this.removeRhs = RemoveAndAnswerNode.create(getRHSTemp(tempNamesStartIndex));
         }
 
         @Override
@@ -243,7 +242,7 @@ abstract class ReplacementNode extends OperatorNode {
                 extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext);
                 ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException();
             }
-            this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create("*rhs*" + tempNamesStartIndex), calls.get(0), codeBuilderContext);
+            this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create(getRHSTemp(tempNamesStartIndex)), calls.get(0), codeBuilderContext);
             this.replaceCall.setPropagateFullCallNeededException();
         }
 
@@ -341,10 +340,9 @@ abstract class ReplacementNode extends OperatorNode {
      */
     private static final class GenericReplacementNode extends ReplacementWithRhsNode {
 
-        @Child private WriteVariableNode targetTmpWrite;
         @Child private RemoveAndAnswerNode targetTmpRemove;
 
-        @Children private final RNode[] updates;
+        @Children private final WriteVariableNode[] updates;
 
         GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, boolean isSuper,
                         int tempNamesStartIndex) {
@@ -353,8 +351,11 @@ abstract class ReplacementNode extends OperatorNode {
              * When there are more than two function calls in LHS, then we save some function calls
              * by saving the intermediate results into temporary variables and reusing them.
              */
-            List<RNode> instructions = new ArrayList<>();
+            List<WriteVariableNode> instructions = new ArrayList<>();
             CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + calls.size() + 1);
+
+            int targetIndex = tempNamesStartIndex;
+            instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(target, calls.get(calls.size() - 1))));
             /*
              * Create the calls that extract inner components - only needed for complex replacements
              * like "a(b(x)) <- z" (where we would extract "b(x)"). The extracted values are saved
@@ -362,35 +363,49 @@ abstract class ReplacementNode extends OperatorNode {
              * + calls.size()-1), the first such temporary variable holds the "target" of the
              * replacement, 'x' in our example (the assignment from 'x' is not done in this loop).
              */
-            for (int i = calls.size() - 1, tmpIndex = 0; i >= 1; i--, tmpIndex++) {
-                ReadVariableNode newFirstArg = ReadVariableNode.create("*tmp*" + (tempNamesStartIndex + tmpIndex));
-                RNode update = createSpecialFunctionQuery(calls.get(i), newFirstArg, codeBuilderContext);
-                instructions.add(WriteVariableNode.createAnonymous("*tmp*" + (tempNamesStartIndex + tmpIndex + 1), WriteVariableNode.Mode.INVISIBLE, update));
+            for (int i = calls.size() - 1; i >= 1; i--) {
+                ReadVariableNode newFirstArg = ReadVariableNode.create(getTargetTemp(targetIndex));
+                RNode extract = createSpecialFunctionQuery(calls.get(i), newFirstArg, codeBuilderContext);
+                instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(++targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(extract, calls.get(i - 1))));
             }
             /*
              * Create the update calls, for "a(b(x)) <- z", this would be `a<-` and `b<-`, the
-             * intermediate results are stored to temporary variables *tmpr*{index}.
+             * intermediate results are stored to temporary variables *rhs*{index}.
              */
+            int replacementIndex = tempNamesStartIndex;
             for (int i = 0; i < calls.size(); i++) {
-                int tmpIndex = tempNamesStartIndex + calls.size() - i - 1;
-                String tmprName = i == 0 ? ("*rhs*" + tempNamesStartIndex) : ("*tmpr*" + (tempNamesStartIndex + i - 1));
-                RNode update = createFunctionUpdate(source, ReadVariableNode.create("*tmp*" + tmpIndex), ReadVariableNode.create(tmprName), calls.get(i), codeBuilderContext);
+                RNode update = createFunctionUpdate(source, ReadVariableNode.create(getTargetTemp(targetIndex--)), ReadVariableNode.create(getRHSTemp(replacementIndex)), calls.get(i),
+                                codeBuilderContext);
                 if (i < calls.size() - 1) {
-                    instructions.add(WriteVariableNode.createAnonymous("*tmpr*" + (tempNamesStartIndex + i), WriteVariableNode.Mode.INVISIBLE, update));
+                    instructions.add(WriteVariableNode.createAnonymous(getRHSTemp(++replacementIndex), WriteVariableNode.Mode.INVISIBLE, update));
                 } else {
                     instructions.add(WriteVariableNode.createAnonymous(targetVarName, WriteVariableNode.Mode.REGULAR, update, isSuper));
                 }
             }
 
-            this.updates = instructions.toArray(new RNode[instructions.size()]);
-            this.targetTmpWrite = WriteVariableNode.createAnonymous(getTargetTmpName(tempNamesStartIndex), WriteVariableNode.Mode.INVISIBLE, target);
-            this.targetTmpRemove = RemoveAndAnswerNode.create(getTargetTmpName(tempNamesStartIndex));
+            this.updates = instructions.toArray(new WriteVariableNode[instructions.size()]);
+            this.targetTmpRemove = RemoveAndAnswerNode.create(getTargetTemp(tempNamesStartIndex));
+        }
+
+        /*
+         * This is complicated, but at this point seems like the only way to get setClass to work
+         * properly. the underlying problem is that slot<- and @<- modify shared values, whereas,
+         * e.g., [[<- does not.
+         */
+        private static RNode wrapForSlotUpdate(RNode target, RSyntaxCall call) {
+            RSyntaxElement syntaxLHS = call.getSyntaxLHS();
+            if (syntaxLHS instanceof RSyntaxLookup) {
+                String symbol = ((RSyntaxLookup) syntaxLHS).getIdentifier();
+                if ("slot".equals(symbol) || "@".equals(symbol)) {
+                    return new GetNonSharedNode.GetNonSharedSyntaxNode(target);
+                }
+            }
+            return target;
         }
 
         @Override
         @ExplodeLoop
         protected void executeReplacement(VirtualFrame frame) {
-            targetTmpWrite.execute(frame);
             for (RNode update : updates) {
                 update.execute(frame);
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
index deef4720e1..9e70abd646 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/GetNonSharedNode.java
@@ -27,8 +27,6 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -36,7 +34,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public abstract class GetNonSharedNode extends Node {
 
-    public static final class GetNonSharedSyntaxNode extends RNode implements RSyntaxNode {
+    public static final class GetNonSharedSyntaxNode extends RNode {
 
         @Child private RNode delegate;
         @Child private GetNonSharedNode nonShared = GetNonSharedNodeGen.create();
@@ -54,21 +52,6 @@ public abstract class GetNonSharedNode extends Node {
         protected RSyntaxNode getRSyntaxNode() {
             return delegate.asRSyntaxNode();
         }
-
-        @Override
-        public void setSourceSection(SourceSection sourceSection) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public SourceSection getLazySourceSection() {
-            return RSyntaxNode.INTERNAL;
-        }
-
-        @Override
-        public SourceSection getSourceSection() {
-            return RSyntaxNode.INTERNAL;
-        }
     }
 
     public abstract Object execute(Object value);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 09e7edf54a..202c03d2ce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -750,6 +750,7 @@ public final class RError extends RuntimeException {
         SLOT_NON_S4("trying to get slot \"%s\" from an object (class \"%s\") that is not an S4 object "),
         SLOT_CANNOT_GET("cannot get a slot (\"%s\") from an object of type \"%s\""),
         SLOT_NONE("no slot of name \"%s\" for this object of class \"%s\""),
+        SLOT_INVALID_TYPE_OR_LEN("invalid type or length for slot name"),
         S4OBJECT_NX_ENVIRONMENT("S4 object does not extend class \"environment\""),
         NOT_A_SLOT("'%s' is not a slot in class ”%s”"),
         NS_ALREADY_REG("namespace already registered"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
index 3e4b0807dd..24a4df04d6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,10 @@ import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 
 /**
@@ -445,14 +447,27 @@ public class RPromise implements RTypedValue {
 
         private final RBaseNode expr;
         private final String symbol;
+        private final String stringConstant;
 
         private Closure(RBaseNode expr) {
             this.expr = expr;
             if (expr.asRSyntaxNode() instanceof RSyntaxLookup) {
-                this.symbol = ((RSyntaxLookup) expr.asRSyntaxNode()).getIdentifier();
+                this.symbol = ((RSyntaxLookup) expr.asRSyntaxNode()).getIdentifier().intern();
             } else {
                 this.symbol = null;
             }
+            if (expr.asRSyntaxNode() instanceof RSyntaxConstant) {
+                Object constant = ((RSyntaxConstant) expr.asRSyntaxNode()).getValue();
+                if (constant instanceof String) {
+                    this.stringConstant = (String) constant;
+                } else if (constant instanceof RAbstractStringVector && ((RAbstractStringVector) constant).getLength() == 1) {
+                    this.stringConstant = ((RAbstractStringVector) constant).getDataAt(0);
+                } else {
+                    this.stringConstant = null;
+                }
+            } else {
+                this.stringConstant = null;
+            }
         }
 
         public static Closure create(RBaseNode expr) {
@@ -491,6 +506,10 @@ public class RPromise implements RTypedValue {
         public String asSymbol() {
             return symbol;
         }
+
+        public String asStringConstant() {
+            return stringConstant;
+        }
     }
 
     @Override
-- 
GitLab


From 52ae0d4521244ca9ccfc227a81a3f0f1a0628ac7 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 2 Mar 2017 16:10:21 +0100
Subject: [PATCH 092/402] Fixed unit test issue: Used the system temp path in a
 test case which is different for other platforms. Sorry for that.

---
 .../truffle/r/test/ExpectedTestOutput.test    | 24 +++---
 .../builtins/TestBuiltin_fifoConnection.java  | 78 -------------------
 .../r/test/library/base/TestConnections.java  |  6 ++
 3 files changed, 17 insertions(+), 91 deletions(-)
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java

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 cadb9c5fd9..905c96ba42 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
@@ -21071,19 +21071,6 @@ Levels: c f h k m n p x
 [1000] 1
 Levels: 0 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenInexisting#
-#capabilities("fifo")
-fifo
-TRUE
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fifoConnection.testFifoOpenInexisting#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
-#{ zz <- fifo("/tmp/pipe3408688236", "r", blocking = TRUE); close(zz); }
-Error in fifo("/tmp/pipe3408688236", "r", blocking = TRUE) :
-  cannot open the connection
-In addition: Warning message:
-In fifo("/tmp/pipe3408688236", "r", blocking = TRUE) :
-  cannot open fifo '/tmp/pipe3408688236'
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_fileaccess.testfileaccess1#
 #argv <- list(character(0), 0); .Internal(file.access(argv[[1]], argv[[2]]))
 integer(0)
@@ -73691,6 +73678,17 @@ Error in file("", "w+", encoding = "___inexistingCharSet___") :
 #{ wline <- 'Hellö'; fin <- file('', 'w+', encoding = 'UTF-8'); writeLines(wline, fin); seek(fin, 0); rline <- readLines(fin, 1); close(fin); c(wline, rline, wline == rline) }
 [1] "Hellö" "Hellö" "TRUE"
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testFifoOpenInexisting#
+#capabilities("fifo")
+fifo
+TRUE
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testFifoOpenInexisting#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+#{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }
+Error in fifo(fn, "r", blocking = TRUE) : cannot open the connection
+In addition: Warning message:
+In fifo(fn, "r", blocking = TRUE) : cannot open fifo '___fifo_2367253765'
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileOpenRaw#
 #{ zz <- file("gzipped_____5137528280012599068___.gz", "r", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }
 Error in readBin(zz, raw(), 4) : can only read from a binary connection
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
deleted file mode 100644
index 106799d228..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fifoConnection.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.builtins;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.AfterClass;
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-// Checkstyle: stop line length check
-public class TestBuiltin_fifoConnection extends TestBase {
-
-    private static List<Path> TEMP_FIFOS = new ArrayList<>();
-
-    @BeforeClass
-    public static void setup() {
-        Path path = Paths.get(System.getProperty("java.io.tmpdir"));
-        TEMP_FIFOS.add(path.resolve("pipe3408688236"));
-        TEMP_FIFOS.add(path.resolve("pipe4039819292"));
-    }
-
-    @Test
-    public void testFifoOpenInexisting() {
-        assertEval("capabilities(\"fifo\")");
-
-        Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\", blocking = TRUE); close(zz); }");
-    }
-
-    @Test(timeout = 100)
-    @Ignore
-    public void testFifoOpenNonBlocking() {
-        Assert.assertFalse(Files.exists(TEMP_FIFOS.get(0)));
-        assertEval(Ignored.ImplementationError, "{ zz <- fifo(\"" + TEMP_FIFOS.get(0) + "\", \"r\"); close(zz); }");
-    }
-
-    @AfterClass
-    public static void cleanup() {
-        for (Path p : TEMP_FIFOS) {
-            try {
-                Files.delete(p);
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-    }
-
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index c4cfaa4a57..4bae7a3225 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -234,6 +234,12 @@ public class TestConnections extends TestRBase {
         assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
     }
 
+    @Test
+    public void testFifoOpenInexisting() {
+        assertEval("capabilities(\"fifo\")");
+        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }");
+    }
+
     private static final String[] LVAL = arr("T", "F");
 
     private static String[] arr(String... args) {
-- 
GitLab


From f1353570f0c1e8d86c5e0542d4efff6319391c86 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 28 Feb 2017 11:06:45 -0800
Subject: [PATCH 093/402] [GR-3076] Fix dimnames vector completeness with
 NA_character_ in c/rbind

---
 .../truffle/r/nodes/builtin/base/Bind.java    | 30 ++++++++++++-------
 .../truffle/r/test/ExpectedTestOutput.test    |  6 ++++
 .../r/test/builtins/TestBuiltin_cbind.java    |  1 +
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 14584bfb60..4f6dba39bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -111,6 +111,7 @@ public abstract class Bind extends RBaseNode {
     private final ConditionProfile emptyVectorProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile allEmptyVectorProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile nonNullNames = BranchProfile.create();
+    private final ConditionProfile dimNamesInComplete = ConditionProfile.createBinaryProfile();
     private final NACheck naCheck = NACheck.create();
     protected final ValueProfile resultProfile = ValueProfile.createClassProfile();
     protected final ValueProfile vectorProfile = ValueProfile.createClassProfile();
@@ -200,11 +201,11 @@ public abstract class Bind extends RBaseNode {
         }
 
         if (type == BindType.cbind) {
-            return genericCBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, naCheck.neverSeenNA(), deparseLevel, setDimNode,
-                            getDimNamesNode, getNamesNode);
+            return genericCBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, deparseLevel, setDimNode, getDimNamesNode,
+                            getNamesNode);
         } else {
-            return genericRBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, naCheck.neverSeenNA(), deparseLevel, setDimNode,
-                            getDimNamesNode, getNamesNode);
+            return genericRBind(promiseArgs, vectors, resultVec, resultDimensions, bindDims, rowsAndColumnsNotEqual, allEmpty, vecNames, deparseLevel, setDimNode, getDimNamesNode,
+                            getNamesNode);
         }
     }
 
@@ -472,8 +473,8 @@ public abstract class Bind extends RBaseNode {
     }
 
     public RVector<?> genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, RVector<?> result, int[] resultDimensions, int[] secondDims, boolean rowsAndColumnsNotEqual,
-                    boolean allEmpty, String[] vecNames, boolean vecNamesComplete, int deparseLevel,
-                    SetDimAttributeNode setDimNode, GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) {
+                    boolean allEmpty, String[] vecNames, int deparseLevel, SetDimAttributeNode setDimNode,
+                    GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) {
 
         int ind = 0;
         Object rowDimResultNames = RNull.instance;
@@ -516,7 +517,7 @@ public abstract class Bind extends RBaseNode {
                 }
             }
         }
-        Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, vecNamesComplete);
+        Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, dimResultNamesComplete(colDimNamesArray));
         setDimNode.setDimensions(result, resultDimensions);
         if (needsDimNames.profile(allEmpty || rowDimResultNames != RNull.instance || colDimResultNames != RNull.instance)) {
             setDimNames(result, RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames}));
@@ -626,8 +627,8 @@ public abstract class Bind extends RBaseNode {
     }
 
     public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, RVector<?> result, int[] resultDimensions, int[] firstDims, boolean rowsAndColumnsNotEqual,
-                    boolean allEmpty, String[] vecNames, boolean vecNamesComplete, int deparseLevel,
-                    SetDimAttributeNode setDimNode, GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) {
+                    boolean allEmpty, String[] vecNames, int deparseLevel, SetDimAttributeNode setDimNode,
+                    GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) {
 
         Object colDimResultNames = RNull.instance;
         String[] rowDimNamesArray = new String[resultDimensions[0]];
@@ -676,7 +677,7 @@ public abstract class Bind extends RBaseNode {
             dstRowInd += firstDims[i];
 
         }
-        Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, vecNamesComplete);
+        Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, dimResultNamesComplete(rowDimNamesArray));
         setDimNode.setDimensions(result, resultDimensions);
         if (needsDimNames.profile(allEmpty || rowDimResultNames != RNull.instance || colDimResultNames != RNull.instance)) {
             setDimNames(result, RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames}));
@@ -684,6 +685,15 @@ public abstract class Bind extends RBaseNode {
         return result;
     }
 
+    private boolean dimResultNamesComplete(String[] rowDimNamesArray) {
+        for (String s : rowDimNamesArray) {
+            if (dimNamesInComplete.profile(s == RRuntime.STRING_NA)) {
+                return RDataFactory.INCOMPLETE_VECTOR;
+            }
+        }
+        return RDataFactory.COMPLETE_VECTOR;
+    }
+
     private void setDimNames(RVector<?> result, RList dimNames) {
         if (setDimNamesNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
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 905c96ba42..518a18ac1c 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
@@ -11984,6 +11984,12 @@ c 2
   a  c
 1 7 42
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testCbind#
+#{x <- numeric(); y <- matrix(2,2); dimnames(y) <- list(c(NA_character_,NA_character_), c(NA_character_)); rbind(x, y) }
+     <NA>
+<NA>    2
+<NA>    2
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testDimnames#
 #{ attributes(cbind(1L)) }
 $dim
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
index d39f463f15..cccb74db2a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
@@ -62,6 +62,7 @@ public class TestBuiltin_cbind extends TestBase {
         assertEval("{ cbind(c(1,c=2)) }");
         assertEval("{ v<-c(b=1, c=2); cbind(v) }");
         assertEval("{ cbind(matrix(1:4, nrow=2, dimnames=list(c('a', 'b'), c('x', 'y')))) }");
+        assertEval("{x <- numeric(); y <- matrix(2,2); dimnames(y) <- list(c(NA_character_,NA_character_), c(NA_character_)); rbind(x, y) }");
 
         assertEval("{ cbind(a=c(1,2), b=c(3,4)) }");
         assertEval("{ cbind(a=c(x=1,y=2), b=c(3,4)) }");
-- 
GitLab


From 28c1cd09641cd653848abd4eac99bd4e47209158 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 1 Mar 2017 12:05:07 -0800
Subject: [PATCH 094/402] [GR-3088] Fix dropped tests4/vanilla package tests.

---
 .../tests4/tests4/tests/allocation0.R         |  10 ++
 .../tests4/tests4/tests}/allocation1.R        |   2 +
 .../tests4/tests4/tests}/allocation10.R       |   6 +-
 .../tests4/tests4/tests}/allocation2.R        |   4 +-
 .../tests4/tests4/tests}/allocation3.R        |   4 +-
 .../tests4/tests4/tests}/allocation4.R        |   4 +-
 .../tests4/tests4/tests}/allocation5.R        |   4 +-
 .../tests4/tests4/tests}/allocation6.R        |   4 +-
 .../tests4/tests4/tests}/allocation7.R        |   6 +-
 .../tests4/tests4/tests}/allocation8.R        |   6 +-
 .../tests4/tests4/tests}/allocation9.R        |   7 +-
 .../tests4/tests4/tests/conversions.R         |   8 ++
 .../packages/tests4/tests4/tests/inspect.R    |   7 +
 .../tests4/tests4/tests/methods0.R.bug        |  15 ++
 .../packages/tests4/tests4/tests}/methods1.R  |   5 +-
 .../packages/tests4/tests4/tests}/methods2.R  |   5 +-
 .../packages/tests4/tests4/tests}/methods3.R  |   4 +-
 .../packages/tests4/tests4/tests}/methods4.R  |   7 +-
 .../packages/tests4/tests4/tests}/methods5.R  |   5 +-
 .../packages/tests4/tests4/tests/slotAccess.R |  25 ++++
 .../packages/tests4/tests4/tests/slotUpdate.R |  12 ++
 .../tests4/tests4/tests}/slot_access1.R       |   2 +
 .../packages/tests4/tests4/tests/stdgeneric.R |   8 ++
 .../packages/vanilla/vanilla/tests/vanilla.R  |   5 +
 .../r/install.packages.R                      |   4 +
 .../com/oracle/truffle/r/test/S4/TestS4.java  | 129 ------------------
 mx.fastr/mx_fastr_pkgs.py                     |  32 +++--
 27 files changed, 170 insertions(+), 160 deletions(-)
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation1.R (80%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation10.R (88%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation2.R (62%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation3.R (65%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation4.R (77%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation5.R (74%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation6.R (74%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation7.R (86%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation8.R (84%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/allocation9.R (85%)
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/methods1.R (78%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/methods2.R (84%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/methods3.R (73%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/methods4.R (64%)
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/methods5.R (84%)
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R
 rename {com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R => com.oracle.truffle.r.test.native/packages/tests4/tests4/tests}/slot_access1.R (80%)
 create mode 100644 com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R
 create mode 100644 com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java

diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R
new file mode 100644
index 0000000000..eac4f00e64
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation0.R
@@ -0,0 +1,10 @@
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+new("numeric")
+setClass("foo", representation(j="numeric")); new("foo", j=42)
+setClass("foo", representation(j="numeric")); typeof(new("foo", j=42))
+
+setClass("foo", representation(j="numeric")); getClass("foo")
+
+setClass("foo"); setClass("bar", representation(j = "numeric"), contains = "foo"); is.null(getClass("foo")@prototype)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation1.R
similarity index 80%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation1.R
index 0a76366e67..2f308efe17 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation1.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation1.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setClass("Person", representation(name = "character", age = "numeric"))
 setClass("Employee", representation(boss = "Person"), contains = "Person")
 print(new("Person", name = "Hadley", age = 31))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation10.R
similarity index 88%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation10.R
index d3c9441b27..eb3b1bf628 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation10.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation10.R
@@ -1,4 +1,6 @@
 # test from Hadley Wickham's book
+stopifnot(require(methods))
+stopifnot(require(tests4))
 
 check_person <- function(object) {
   errors <- character()
@@ -13,11 +15,11 @@ check_person <- function(object) {
     msg <- paste("Name is length ", length_name, ".  Should be 1", sep = "")
     errors <- c(errors, msg)
   }
-  
+
   if (length(errors) == 0) TRUE else errors
 }
 setClass("Person", representation(name = "character", age = "numeric"), validity = check_person)
 
 hadley <- new("Person", name = "Hadley", age = 31)
 hadley@age <- 1:10
-print(validObject(hadley))
+try(validObject(hadley))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation2.R
similarity index 62%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation2.R
index e933ae2143..05ba0ae214 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation2.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation2.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
+stopifnot(require(methods))
+stopifnot(require(tests4))
 
 setClass("Person", representation(name = "character", age = "numeric"))
 setClass("Employee", representation(boss = "Person"), contains = "Person")
-print(new("Person", name = "Hadley", age = "thirty"))
+try(new("Person", name = "Hadley", age = "thirty"))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation3.R
similarity index 65%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation3.R
index c1c253979c..6f596d9969 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation3.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation3.R
@@ -1,6 +1,8 @@
 # IgnoreErrorContext
 # test from Hadley Wickham's book
+stopifnot(require(methods))
+stopifnot(require(tests4))
 
 setClass("Person", representation(name = "character", age = "numeric"))
 setClass("Employee", representation(boss = "Person"), contains = "Person")
-print(new("Person", name = "Hadley", sex = "male"))
+try(new("Person", name = "Hadley", sex = "male"))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation4.R
similarity index 77%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation4.R
index 8d44cf9f27..0270df7258 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation4.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation4.R
@@ -1,6 +1,8 @@
 # test from Hadley Wickham's book
+stopifnot(require(methods))
+stopifnot(require(tests4))
 
 setClass("Person", representation(name = "character", age = "numeric"))
 setClass("Employee", representation(boss = "Person"), contains = "Person")
 hadley <- new("Person", name = "Hadley")
-print(hadley@age)
+hadley@age
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R
similarity index 74%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R
index 193c85cf14..998abefbd1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation5.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R
@@ -1,6 +1,8 @@
 # test from Hadley Wickham's book
+stopifnot(require(methods))
+stopifnot(require(tests4))
 
 setClass("Person", representation(name = "character", age = "numeric"))
 setClass("Employee", representation(boss = "Person"), contains = "Person")
 hadley <- new("Person", name = "Hadley")
-print(slot(hadley, "age"))
+slot(hadley, "age")
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation6.R
similarity index 74%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation6.R
index 54b498d595..e131736c5a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation6.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation6.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setClass("Person", representation(name = "character", age = "numeric"), prototype(name = NA_character_, age = NA_real_))
 hadley <- new("Person", name = "Hadley")
-print(hadley@age)
+hadley@age
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation7.R
similarity index 86%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation7.R
index bb07265572..13b4379185 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation7.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation7.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 check_person <- function(object) {
   errors <- character()
   length_age <- length(object@age)
@@ -13,9 +15,9 @@ check_person <- function(object) {
     msg <- paste("Name is length ", length_name, ".  Should be 1", sep = "")
     errors <- c(errors, msg)
   }
-  
+
   if (length(errors) == 0) TRUE else errors
 }
 setClass("Person", representation(name = "character", age = "numeric"), validity = check_person)
 
-print(new("Person", name = "Hadley"))
+try(new("Person", name = "Hadley"))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation8.R
similarity index 84%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation8.R
index 75c2b63b39..c0d0057cf1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation8.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation8.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 check_person <- function(object) {
   errors <- character()
   length_age <- length(object@age)
@@ -13,9 +15,9 @@ check_person <- function(object) {
     msg <- paste("Name is length ", length_name, ".  Should be 1", sep = "")
     errors <- c(errors, msg)
   }
-  
+
   if (length(errors) == 0) TRUE else errors
 }
 setClass("Person", representation(name = "character", age = "numeric"), validity = check_person)
 
-print(new("Person", name = "Hadley", age = 1:10))
+try(new("Person", name = "Hadley", age = 1:10))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation9.R
similarity index 85%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation9.R
index 8aa98b2467..3d6e712d4e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/allocation9.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation9.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 check_person <- function(object) {
   errors <- character()
   length_age <- length(object@age)
@@ -13,10 +15,9 @@ check_person <- function(object) {
     msg <- paste("Name is length ", length_name, ".  Should be 1", sep = "")
     errors <- c(errors, msg)
   }
-  
+
   if (length(errors) == 0) TRUE else errors
 }
 setClass("Person", representation(name = "character", age = "numeric"), validity = check_person)
 
-print(new("Person", name = "Hadley", age = 31))
-
+new("Person", name = "Hadley", age = 31)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R
new file mode 100644
index 0000000000..6881b18794
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/conversions.R
@@ -0,0 +1,8 @@
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+x<-42; isS4(x)
+x<-42; y<-asS4(x); isS4(y)
+isS4(NULL)
+asS4(NULL); isS4(NULL)
+asS4(7:42)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R
new file mode 100644
index 0000000000..a3af8df2ad
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/inspect.R
@@ -0,0 +1,7 @@
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+tests4:::inspect.vehicle(new("Car"), new("Inspector"))
+tests4:::inspect.vehicle(new("Truck"), new("Inspector"))
+tests4:::inspect.vehicle(new("Car"), new("StateInspector"))
+tests4:::inspect.vehicle(new("Truck"), new("StateInspector"))
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug
new file mode 100644
index 0000000000..53b1e01861
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods0.R.bug
@@ -0,0 +1,15 @@
+# this has differences that the fuzzy compare cannot cope with
+
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res
+gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res
+
+gen<-function(object) 0; setGeneric("gen"); setClass("foo", representation(d="numeric")); setMethod("gen", signature(object="foo"), function(object) object@d); res<-print(gen(new("foo", d=42))); removeGeneric("gen"); res
+
+setClass("foo", representation(d="numeric")); setClass("bar",  contains="foo"); setGeneric("gen", function(o) standardGeneric("gen")); setMethod("gen", signature(o="foo"), function(o) "FOO"); setMethod("gen", signature(o="bar"), function(o) "BAR"); res<-print(c(gen(new("foo", d=7)), gen(new("bar", d=42)))); removeGeneric("gen"); res
+
+setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res
+
+setClass("foo"); setMethod("diag<-", "foo", function(x, value) 42); removeMethod("diag<-", "foo"); removeGeneric("diag<-"); removeClass("foo")
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R
similarity index 78%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R
index 24dde5f0df..1a1b75d9c5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods1.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setGeneric("sides", function(object) {
   standardGeneric("sides")
 })
@@ -19,5 +21,6 @@ setMethod("sides", signature("Square"),   function(object) 4)
 # setMethod("sides", signature("Circle"),   function(object) Inf)
 
 res<-print(showMethods("sides"))
-removeGeneric("sides")
+# BUG ALERT:In FastR without the "print" the result from removeGeneric (TRUE) is not printed.
+print(removeGeneric("sides"))
 print(res)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R
similarity index 84%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R
index 8afba8e7e9..9fdf38279f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods2.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setGeneric("sides", function(object) {
   standardGeneric("sides")
 })
@@ -19,5 +21,6 @@ setMethod("sides", signature("Square"),   function(object) 4)
 setMethod("sides", signature("Circle"),   function(object) Inf)
 
 res<-print(showMethods(class = "Polygon"))
-removeGeneric("sides")
+# BUG print should not be necessary
+print(removeGeneric("sides"))
 print(res)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods3.R
similarity index 73%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods3.R
index a944995797..d8d792ffab 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods3.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods3.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setGeneric("sides", valueClass = "numeric", function(object) {
   standardGeneric("sides")
 })
@@ -11,4 +13,4 @@ setClass("Square", contains = "Polygon")
 # setClass("Circle", contains = "Shape")
 
 setMethod("sides", signature("Triangle"), function(object) "three")
-tryCatch({sides(new("Triangle"))}, error = function(e) { removeGeneric("sides"); stop(e) })
+try(tryCatch({sides(new("Triangle"))}, error = function(e) { removeGeneric("sides"); stop(e) }))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R
similarity index 64%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R
index a18ecd900b..6f75874a4a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods4.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R
@@ -1,14 +1,17 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setClass("A")
 setClass("A1", contains = "A")
 setClass("A2", contains = "A1")
 setClass("A3", contains = "A2")
 
-setGeneric("foo", function(a, b) standardGeneric("foo")) 
+setGeneric("foo", function(a, b) standardGeneric("foo"))
 setMethod("foo", signature("A1", "A2"), function(a, b) "1-2")
 setMethod("foo", signature("A2", "A1"), function(a, b) "2-1")
 
 res<-print(foo(new("A2"), new("A2")))
-removeGeneric("foo")
+# BUG print shoukld not be necessary
+print(removeGeneric("foo"))
 print(res)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R
similarity index 84%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R
index 69b502a7d2..e8e93ff718 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/methods5.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book (slightly augmented)
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setClass("Vehicle")
 setClass("Truck", contains = "Vehicle")
 setClass("Car", contains = "Vehicle")
@@ -26,4 +28,5 @@ setMethod("inspect.vehicle",
  })
 
 inspect.vehicle(new("Car"), new("Inspector"))
-removeGeneric("inspect.vehicle");
+# BUG print should not be necessary
+print(removeGeneric("inspect.vehicle"))
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R
new file mode 100644
index 0000000000..f4c92749c7
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotAccess.R
@@ -0,0 +1,25 @@
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+`@`(getClass("ClassUnionRepresentation"), "virtual")
+`@`(getClass("ClassUnionRepresentation"), "virtual")
+try(`@`(getClass("ClassUnionRepresentation"), c("virtual", "foo")))
+getClass("ClassUnionRepresentation")@virtual
+getClass("ClassUnionRepresentation")@.S3Class
+c(42)@.Data
+x<-42; `@`(x, ".Data")
+x<-42; `@`(x, .Data)
+x<-42; slot(x, ".Data")
+setClass("foo", contains="numeric"); x<-new("foo"); res<-x@.Data; removeClass("foo"); res
+setClass("foo", contains="numeric"); x<-new("foo"); res<-slot(x, ".Data"); removeClass("foo"); res
+try(getClass("ClassUnionRepresentation")@foo)
+try(c(42)@foo)
+x<-42; attr(x, "foo")<-7; try(x@foo)
+x<-42; attr(x, "foo")<-7; slot(x, "foo")
+x<-c(42); class(x)<-"bar"; try(x@foo)
+x<-getClass("ClassUnionRepresentation"); slot(x, "virtual")
+x<-getClass("ClassUnionRepresentation"); try( slot(x, virtual))
+x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo
+x<-NULL; try(`@`(x, foo))
+x<-NULL; try(x@foo)
+x<-paste0(".", "Data"); y<-42; slot(y, x)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R
new file mode 100644
index 0000000000..f10261b057
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slotUpdate.R
@@ -0,0 +1,12 @@
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+x<-getClass("ClassUnionRepresentation"); x@virtual<-TRUE; x@virtual
+x<-getClass("ClassUnionRepresentation"); slot(x, "virtual", check=TRUE)<-TRUE; x@virtual
+x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x
+
+x<-function() 42; attr(x, "foo")<-7; try(y@foo<-42)
+x<-function() 42; attr(x, "foo")<-7; try(slot(y, "foo")<-42)
+x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); try(y@foo<-42)
+x<-NULL; try(`@<-`(x, foo, "bar"))
+x<-NULL; try(x@foo<-"bar")
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slot_access1.R
similarity index 80%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R
rename to com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slot_access1.R
index a1743cc28a..a0160b4bb9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/slot_access1.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/slot_access1.R
@@ -1,5 +1,7 @@
 # test from Hadley Wickham's book
 
+stopifnot(require(methods))
+stopifnot(require(tests4))
 setClass("Person", representation(name = "character", age = "numeric"), prototype(name = NA_character_, age = NA_real_))
 hadley <- new("Person", name = "Hadley")
 print(getSlots("Person"))
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R
new file mode 100644
index 0000000000..0293d84577
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/stdgeneric.R
@@ -0,0 +1,8 @@
+stopifnot(require(methods))
+stopifnot(require(tests4))
+
+try(standardGeneric(42))
+try(standardGeneric(character()))
+try(standardGeneric(""))
+try(standardGeneric("foo", 42))
+x<-42; class(x)<-character(); try(standardGeneric("foo", x))
diff --git a/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R b/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R
new file mode 100644
index 0000000000..e9992f04c4
--- /dev/null
+++ b/com.oracle.truffle.r.test.native/packages/vanilla/vanilla/tests/vanilla.R
@@ -0,0 +1,5 @@
+stopifnot(require(vanilla))
+
+vanilla()
+functionTest(c(1,2,3,4,5,6),8:10)
+r<-42; vanilla::foo(r)<-7; r
diff --git a/com.oracle.truffle.r.test.packages/r/install.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R
index 397c82bec3..2695cf973f 100644
--- a/com.oracle.truffle.r.test.packages/r/install.packages.R
+++ b/com.oracle.truffle.r.test.packages/r/install.packages.R
@@ -260,6 +260,10 @@ set.repos <- function() {
 	repos <- character()
 	needCran <- F
 	if ("BIOC" %in% repo.list) {
+		# source("http://bioconductor.org/biocLite.R")
+		# repos["BIOC"] <- biocinstallRepos()[1]
+		# above is correct but provokes bug:
+		# Error in read.table():  more columns than column names
 		repos["BIOC"] <- "https://bioconductor.org/packages/3.4/bioc"
 		needCran <- T
 	}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
deleted file mode 100644
index 01287bcef7..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.test.S4;
-
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestRBase;
-
-// Checkstyle: stop LineLength
-
-/**
- * Tests for the S4 object model implementation.
- */
-public class TestS4 extends TestRBase {
-    @Test
-    public void testSlotAccess() {
-        assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), virtual) }");
-        assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), \"virtual\") }");
-        assertEval(Output.IgnoreErrorContext, "{ `@`(getClass(\"ClassUnionRepresentation\"), c(\"virtual\", \"foo\")) }");
-        assertEval("{ getClass(\"ClassUnionRepresentation\")@virtual }");
-        assertEval("{ getClass(\"ClassUnionRepresentation\")@.S3Class }");
-        assertEval("{ c(42)@.Data }");
-        assertEval("{ x<-42; `@`(x, \".Data\") }");
-        assertEval("{ x<-42; `@`(x, .Data) }");
-        assertEval("{ x<-42; slot(x, \".Data\") }");
-        assertEval("{ setClass(\"foo\", contains=\"numeric\"); x<-new(\"foo\"); res<-x@.Data; removeClass(\"foo\"); res }");
-        assertEval("{ setClass(\"foo\", contains=\"numeric\"); x<-new(\"foo\"); res<-slot(x, \".Data\"); removeClass(\"foo\"); res }");
-        assertEval(Output.IgnoreErrorContext, "{ getClass(\"ClassUnionRepresentation\")@foo }");
-        assertEval(Output.IgnoreErrorContext, "{ c(42)@foo }");
-        assertEval(Output.IgnoreErrorContext, " { x<-42; attr(x, \"foo\")<-7; x@foo }");
-        assertEval("{ x<-42; attr(x, \"foo\")<-7; slot(x, \"foo\") }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-c(42); class(x)<-\"bar\"; x@foo }");
-        assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, \"virtual\") }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, virtual) }");
-        assertEval("{ x<-function() 42; attr(x, \"foo\")<-7; y<-asS4(x); y@foo }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@`(x, foo) }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo }");
-        assertEval("{ x<-paste0(\".\", \"Data\"); y<-42; slot(y, x) }");
-    }
-
-    @Test
-    public void testSlotUpdate() {
-        assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); x@virtual<-TRUE; x@virtual }");
-        assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, \"virtual\", check=TRUE)<-TRUE; x@virtual }");
-        assertEval("{ x<-initialize@valueClass; initialize@valueClass<-\"foo\"; initialize@valueClass<-x }");
-
-        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y@foo<-42 }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; slot(y, \"foo\")<-42 }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y<-asS4(x); y@foo<-42 }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@<-`(x, foo, \"bar\") }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo<-\"bar\" }");
-
-    }
-
-    @Test
-    public void testConversions() {
-        assertEval("{ x<-42; isS4(x) }");
-        assertEval("{ x<-42; y<-asS4(x); isS4(y) }");
-        assertEval("{ isS4(NULL) }");
-        assertEval("{ asS4(NULL); isS4(NULL) }");
-        assertEval("{  asS4(7:42) }");
-    }
-
-    @Test
-    public void testAllocation() {
-        assertEval("{ new(\"numeric\") }");
-        assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j=42) }");
-        assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); typeof(new(\"foo\", j=42)) }");
-    }
-
-    @Test
-    public void testClassCreation() {
-        // output slightly different from GNU R even though we use R's "show" method to print it
-        assertEval(Ignored.OutputFormatting, "{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }");
-
-        assertEval("{ setClass(\"foo\"); setClass(\"bar\", representation(j = \"numeric\"), contains = \"foo\"); is.null(getClass(\"foo\")@prototype) }");
-    }
-
-    @Test
-    public void testMethods() {
-        // output slightly different from GNU R even though we use R's "show" method to print it
-        assertEval(Ignored.OutputFormatting, "{ setGeneric(\"gen\", function(object) standardGeneric(\"gen\")); res<-print(gen); removeGeneric(\"gen\"); res }");
-        assertEval(Ignored.OutputFormatting, "{ gen<-function(object) 0; setGeneric(\"gen\"); res<-print(gen); removeGeneric(\"gen\"); res }");
-
-        assertEval("{ gen<-function(object) 0; setGeneric(\"gen\"); setClass(\"foo\", representation(d=\"numeric\")); setMethod(\"gen\", signature(object=\"foo\"), function(object) object@d); res<-print(gen(new(\"foo\", d=42))); removeGeneric(\"gen\"); res }");
-
-        assertEval("{ setClass(\"foo\", representation(d=\"numeric\")); setClass(\"bar\",  contains=\"foo\"); setGeneric(\"gen\", function(o) standardGeneric(\"gen\")); setMethod(\"gen\", signature(o=\"foo\"), function(o) \"FOO\"); setMethod(\"gen\", signature(o=\"bar\"), function(o) \"BAR\"); res<-print(c(gen(new(\"foo\", d=7)), gen(new(\"bar\", d=42)))); removeGeneric(\"gen\"); res }");
-
-        assertEval("{ setGeneric(\"gen\", function(o) standardGeneric(\"gen\")); res<-print(setGeneric(\"gen\", function(o) standardGeneric(\"gen\"))); removeGeneric(\"gen\"); res }");
-
-        assertEval("{ setClass(\"foo\"); setMethod(\"diag<-\", \"foo\", function(x, value) 42); removeMethod(\"diag<-\", \"foo\"); removeGeneric(\"diag<-\"); removeClass(\"foo\") }");
-
-    }
-
-    @Test
-    public void testStdGeneric() {
-        assertEval("{ standardGeneric(42) }");
-        assertEval("{ standardGeneric(character()) }");
-        assertEval("{ standardGeneric(\"\") }");
-        // FastR produces better error contexts
-        assertEval(Output.IgnoreErrorContext, "{ standardGeneric(\"foo\", 42) }");
-        assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
-    }
-
-    @Override
-    public String getTestDir() {
-        return "S4";
-    }
-}
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index 6261292563..f45348f89c 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -297,12 +297,9 @@ def _get_test_outputs(rvm, pkg_name, test_info):
             test_info[pkg_name] = TestStatus()
         for f in files:
             ext = os.path.splitext(f)[1]
-            if f == 'test_time' or ext == '.R' or ext == '.Rin' or ext == '.prev':
-                continue
             # suppress .pdf's for now (we can't compare them)
-            if ext == '.pdf':
-                continue
-            if ext == '.save':
+            ignore = ['.R', '.Rin', '.prev', '.bug', '.pdf', '.save']
+            if f == 'test_time' or ext in ignore:
                 continue
             status = "OK"
             if ext == '.fail':
@@ -451,7 +448,13 @@ def _find_start(content):
     for i in range(len(content)):
         line = content[i]
         if marker in line:
-            return i + 1
+            # skip blank lines
+            j = i + 1
+            while j < len(content):
+                line = content[j].strip()
+                if len(line) > 0:
+                    return j
+                j = j + 1
     return None
 
 def _find_end(content):
@@ -484,7 +487,7 @@ def _fuzzy_compare(gnur_content, fastr_content):
     fastr_len = len(fastr_content)
     if not gnur_start or not gnur_end or not fastr_start:
         return -1
-    gnur_i = gnur_start + 1 # Gnu has extra empty line
+    gnur_i = gnur_start
     fastr_i = fastr_start
     result = 0
     while gnur_i < gnur_end:
@@ -510,6 +513,9 @@ def _fuzzy_compare(gnur_content, fastr_content):
                     # skip until lines match (or not)
                     gnur_i = gnur_i + 1
                     fastr_i = fastr_i + 1
+                    if gnur_i == gnur_end - 1:
+                        # at end (there is always a blank line)
+                        break
                     ni = -1
                     while gnur_i < gnur_end:
                         ni = _find_line(gnur_content[gnur_i], fastr_content, fastr_i)
@@ -523,16 +529,20 @@ def _fuzzy_compare(gnur_content, fastr_content):
                         result = 1
                         break
             else:
-                # genuine difference
-                result = 1
-                break
+                # genuine difference (modulo whitespace)
+                if not _ignore_whitespace(gnur_line, fastr_line):
+                    result = 1
+                    break
         gnur_i = gnur_i + 1
         fastr_i = fastr_i + 1
     return result
 
+def _ignore_whitespace(gnur_line, fastr_line):
+    return gnur_line.translate(None, ' \t') == fastr_line.translate(None, ' \t')
+
 def pkgtest_cmp(args):
     with open(args[0]) as f:
         gnur_content = f.readlines()
     with open(args[1]) as f:
         fastr_content = f.readlines()
-    _fuzzy_compare(gnur_content, fastr_content)
+    return _fuzzy_compare(gnur_content, fastr_content)
-- 
GitLab


From d0c5f1026b2e869c91e2f1a935c6d4d18f429327 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 3 Mar 2017 13:24:32 +0100
Subject: [PATCH 095/402] add visibleExecute functions to PeekLocalVariable and
 RCallBaseNodeWrapper

---
 .../function/RCallBaseNodeWrapperFactory.java |  15 +-
 .../r/nodes/function/RCallSpecialNode.java    |  15 +
 .../truffle/r/test/ExpectedTestOutput.test    | 407 +-----------------
 .../r/test/builtins/TestBuiltin_body.java     |   4 +-
 .../builtins/TestBuiltin_lockEnvironment.java |   4 +-
 .../r/test/builtins/TestBuiltin_nchar.java    |   4 +-
 .../r/test/functions/TestFunctions.java       |   5 +
 7 files changed, 43 insertions(+), 411 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
index 6f6b94ab22..70d38d3f29 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,19 @@ public class RCallBaseNodeWrapperFactory implements InstrumentableFactory<RCallB
             }
         }
 
+        @Override
+        public Object visibleExecute(VirtualFrame frame) {
+            try {
+                probeNode.onEnter(frame);
+                Object returnValue = delegate.visibleExecute(frame);
+                probeNode.onReturnValue(frame, returnValue);
+                return returnValue;
+            } catch (Throwable t) {
+                probeNode.onReturnExceptional(frame, t);
+                throw t;
+            }
+        }
+
         @Override
         public Object execute(VirtualFrame frame, Object function) {
             try {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
index 838dd57a2d..a23f58a4a2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
@@ -58,6 +58,8 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup {
     private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile();
     private final ValueProfile valueProfile = ValueProfile.createClassProfile();
 
+    @Child private SetVisibilityNode visibility;
+
     PeekLocalVariableNode(String name) {
         this.read = LocalReadVariableNode.create(name, false);
     }
@@ -78,6 +80,19 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup {
         return valueProfile.profile(value);
     }
 
+    @Override
+    public Object visibleExecute(VirtualFrame frame) {
+        try {
+            return execute(frame);
+        } finally {
+            if (visibility == null) {
+                CompilerDirectives.transferToInterpreter();
+                visibility = insert(SetVisibilityNode.create());
+            }
+            visibility.execute(frame, true);
+        }
+    }
+
     @Override
     public void setSourceSection(SourceSection source) {
         // nothing to do
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 518a18ac1c..e1ec10e788 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
@@ -1,406 +1,3 @@
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation1.R") }
-An object of class "Person"
-Slot "name":
-[1] "Hadley"
-
-Slot "age":
-[1] 31
-
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation10.R") }
-Error in validObject(hadley) :
-  invalid class “Person” object: Age is length 10.  Should be 1
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation2.R") }
-Error in validObject(.Object) :
-  invalid class “Person” object: invalid object for slot "age" in class "Person": got class "character", should be or extend class "numeric"
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#Output.IgnoreErrorContext#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation3.R") }
-Error in initialize(value, ...) :
-  invalid name for slot of class “Person”: sex
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation4.R") }
-numeric(0)
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation5.R") }
-numeric(0)
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation6.R") }
-[1] NA
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation7.R") }
-Error in validObject(.Object) :
-  invalid class “Person” object: Age is length 0.  Should be 1
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation8.R") }
-Error in validObject(.Object) :
-  invalid class “Person” object: Age is length 10.  Should be 1
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/allocation9.R") }
-An object of class "Person"
-Slot "name":
-[1] "Hadley"
-
-Slot "age":
-[1] 31
-
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods1.R") }
-Function: sides (package .GlobalEnv)
-object="Polygon"
-object="Square"
-object="Triangle"
-
-description       class        mode        text      opened    can read
-   "stdout"  "terminal"         "w"      "text"    "opened"        "no"
-  can write
-      "yes"
-description       class        mode        text      opened    can read
-   "stdout"  "terminal"         "w"      "text"    "opened"        "no"
-  can write
-      "yes"
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods2.R") }
-Function: sides (package .GlobalEnv)
-object="Polygon"
-
-description       class        mode        text      opened    can read
-   "stdout"  "terminal"         "w"      "text"    "opened"        "no"
-  can write
-      "yes"
-description       class        mode        text      opened    can read
-   "stdout"  "terminal"         "w"      "text"    "opened"        "no"
-  can write
-      "yes"
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods3.R") }
-Error in .valueClassTest(ans, "numeric", "sides") :
-  invalid value from generic function ‘sides’, class “character”, expected “numeric”
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods4.R") }
-Note: method with signature ‘A2#A1’ chosen for function ‘foo’,
- target signature ‘A2#A2’.
- "A1#A2" would also be valid
-[1] "2-1"
-[1] "2-1"
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/methods5.R") }
-[1] "Looking for rust"
-character(0)
-[1] "Checking seat belts"
-
-##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/slot_access1.R") }
-       name         age
-"character"   "numeric"
-
-##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
-#{ new("numeric") }
-numeric(0)
-
-##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
-#{ setClass("foo", representation(j="numeric")); new("foo", j=42) }
-An object of class "foo"
-Slot "j":
-[1] 42
-
-
-##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
-#{ setClass("foo", representation(j="numeric")); typeof(new("foo", j=42)) }
-[1] "S4"
-
-##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#
-#{ setClass("foo"); setClass("bar", representation(j = "numeric"), contains = "foo"); is.null(getClass("foo")@prototype) }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#Ignored.OutputFormatting#
-#{ setClass("foo", representation(j="numeric")); getClass("foo") }
-Class "foo" [in ".GlobalEnv"]
-
-Slots:
-
-Name:        j
-Class: numeric
-
-##com.oracle.truffle.r.test.S4.TestS4.testConversions#
-#{  asS4(7:42) }
- [1]  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-[26] 32 33 34 35 36 37 38 39 40 41 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testConversions#
-#{ asS4(NULL); isS4(NULL) }
-[1] TRUE
-
-##com.oracle.truffle.r.test.S4.TestS4.testConversions#
-#{ isS4(NULL) }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testConversions#
-#{ x<-42; isS4(x) }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testConversions#
-#{ x<-42; y<-asS4(x); isS4(y) }
-[1] TRUE
-
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
-#{ gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res }
-function (object)
-standardGeneric("gen")
-<environment: 0x7fe323e45660>
-attr(,"generic")
-[1] "gen"
-attr(,"generic")attr(,"package")
-[1] ".GlobalEnv"
-attr(,"package")
-[1] ".GlobalEnv"
-attr(,"group")
-list()
-attr(,"valueClass")
-character(0)
-attr(,"signature")
-[1] "object"
-attr(,"default")
-Method Definition (Class "derivedDefaultMethod"):
-
-function (object)
-0
-
-Signatures:
-        object
-target  "ANY"
-defined "ANY"
-attr(,"skeleton")
-(function (object)
-0)(object)
-attr(,"class")
-[1] "standardGeneric"
-attr(,"class")attr(,"package")
-[1] "methods"
-standardGeneric for "gen" defined from package ".GlobalEnv"
-
-function (object)
-standardGeneric("gen")
-<environment: 0x7fe323e45660>
-Methods may be defined for arguments: object
-Use  showMethods("gen")  for currently available ones.
-
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#
-#{ gen<-function(object) 0; setGeneric("gen"); setClass("foo", representation(d="numeric")); setMethod("gen", signature(object="foo"), function(object) object@d); res<-print(gen(new("foo", d=42))); removeGeneric("gen"); res }
-[1] 42
-[1] 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#
-#{ setClass("foo"); setMethod("diag<-", "foo", function(x, value) 42); removeMethod("diag<-", "foo"); removeGeneric("diag<-"); removeClass("foo") }
-Creating a generic function for ‘diag<-’ from package ‘base’ in the global environment
-[1] TRUE
-
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#
-#{ setClass("foo", representation(d="numeric")); setClass("bar",  contains="foo"); setGeneric("gen", function(o) standardGeneric("gen")); setMethod("gen", signature(o="foo"), function(o) "FOO"); setMethod("gen", signature(o="bar"), function(o) "BAR"); res<-print(c(gen(new("foo", d=7)), gen(new("bar", d=42)))); removeGeneric("gen"); res }
-[1] "FOO" "BAR"
-[1] "FOO" "BAR"
-
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#
-#{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res }
-[1] "gen"
-[1] "gen"
-
-##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
-#{ setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res }
-function(object) standardGeneric("gen")
-<environment: 0x7fba68bbb3c0>
-attr(,"generic")
-[1] "gen"
-attr(,"generic")attr(,"package")
-[1] ".GlobalEnv"
-attr(,"package")
-[1] ".GlobalEnv"
-attr(,"group")
-list()
-attr(,"valueClass")
-character(0)
-attr(,"signature")
-[1] "object"
-attr(,"default")
-`\001NULL\001`
-attr(,"skeleton")
-(function (object)
-stop("invalid call in method dispatch to 'gen' (no default method)",
-    domain = NA))(object)
-attr(,"class")
-[1] "standardGeneric"
-attr(,"class")attr(,"package")
-[1] "methods"
-standardGeneric for "gen" defined from package ".GlobalEnv"
-
-function (object)
-standardGeneric("gen")
-<environment: 0x7fba68bbb3c0>
-Methods may be defined for arguments: object
-Use  showMethods("gen")  for currently available ones.
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-# { x<-42; attr(x, "foo")<-7; x@foo }
-Error: trying to get slot "foo" from an object of a basic class ("numeric") with no slots
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ `@`(getClass("ClassUnionRepresentation"), "virtual") }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ `@`(getClass("ClassUnionRepresentation"), c("virtual", "foo")) }
-Error: invalid type or length for slot name
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ `@`(getClass("ClassUnionRepresentation"), virtual) }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ c(42)@.Data }
-[1] 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ c(42)@foo }
-Error: trying to get slot "foo" from an object of a basic class ("numeric") with no slots
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ getClass("ClassUnionRepresentation")@.S3Class }
-[1] "classRepresentation"
-attr(,"package")
-[1] "methods"
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ getClass("ClassUnionRepresentation")@foo }
-Error: no slot of name "foo" for this object of class "classRepresentation"
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ getClass("ClassUnionRepresentation")@virtual }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ setClass("foo", contains="numeric"); x<-new("foo"); res<-slot(x, ".Data"); removeClass("foo"); res }
-numeric(0)
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ setClass("foo", contains="numeric"); x<-new("foo"); res<-x@.Data; removeClass("foo"); res }
-numeric(0)
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-42; `@`(x, ".Data") }
-[1] 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-42; `@`(x, .Data) }
-[1] 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-42; attr(x, "foo")<-7; slot(x, "foo") }
-[1] 7
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-42; slot(x, ".Data") }
-[1] 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ x<-NULL; `@`(x, foo) }
-Error: trying to get slot "foo" from an object of a basic class ("NULL") with no slots
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ x<-NULL; x@foo }
-Error: trying to get slot "foo" from an object of a basic class ("NULL") with no slots
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ x<-c(42); class(x)<-"bar"; x@foo }
-Error: trying to get slot "foo" from an object (class "bar") that is not an S4 object
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo }
-[1] 7
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-getClass("ClassUnionRepresentation"); slot(x, "virtual") }
-[1] FALSE
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
-#{ x<-getClass("ClassUnionRepresentation"); slot(x, virtual) }
-Error in slot(x, virtual) : object 'virtual' not found
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ x<-paste0(".", "Data"); y<-42; slot(y, x) }
-[1] 42
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-NULL; `@<-`(x, foo, "bar") }
-Error in (function (cl, name, valueClass)  :
-  ‘foo’ is not a slot in class “NULL”
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-NULL; x@foo<-"bar" }
-Error in (function (cl, name, valueClass)  :
-  ‘foo’ is not a slot in class “NULL”
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-function() 42; attr(x, "foo")<-7; slot(y, "foo")<-42 }
-Error in slot(y, "foo") <- 42 : object 'y' not found
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo<-42 }
-Error in (function (cl, name, valueClass)  :
-  ‘foo’ is not a slot in class “function”
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-function() 42; attr(x, "foo")<-7; y@foo<-42 }
-Error in y@foo <- 42 : object 'y' not found
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
-#{ x<-getClass("ClassUnionRepresentation"); slot(x, "virtual", check=TRUE)<-TRUE; x@virtual }
-[1] TRUE
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
-#{ x<-getClass("ClassUnionRepresentation"); x@virtual<-TRUE; x@virtual }
-[1] TRUE
-
-##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
-#{ x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x }
-
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
-#{ standardGeneric("") }
-Error in standardGeneric("") :
-  argument to 'standardGeneric' must be a non-empty character string
-
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext#
-#{ standardGeneric("foo", 42) }
-Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
-
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
-#{ standardGeneric(42) }
-Error in standardGeneric(42) :
-  argument to 'standardGeneric' must be a non-empty character string
-
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
-#{ standardGeneric(character()) }
-Error in standardGeneric(character()) :
-  argument to 'standardGeneric' must be a non-empty character string
-
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext#
-#{ x<-42; class(x)<-character(); standardGeneric("foo", x) }
-Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Arg.testArg1#
 #argv <- list(1+2i);Arg(argv[[1]]);
 [1] 1.107149
@@ -72601,6 +72198,10 @@ function(x) x
 #{ sum }
 function (..., na.rm = FALSE)  .Primitive("sum")
 
+##com.oracle.truffle.r.test.functions.TestFunctions.testFunctionResultPrinting#
+#{ foo <- function() { x <- 1; return(x) }; foo() }
+[1] 1
+
 ##com.oracle.truffle.r.test.functions.TestFunctions.testInvocation#
 #{ f <- function(...) { args <- list(...) ; args$name } ; f(name = 42) }
 [1] 42
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java
index 07c7586fac..7abf3fc602 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_body.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -34,7 +34,7 @@ public class TestBuiltin_body extends TestBase {
 
     @Test
     public void testbody4() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('/')); .Internal(body(argv[[1]]))");
+        assertEval("argv <- list(.Primitive('/')); .Internal(body(argv[[1]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java
index 725d9b47df..46fe71dbd5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lockEnvironment.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@ public class TestBuiltin_lockEnvironment extends TestBase {
         assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, FALSE); e$b <- 123");
         assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, FALSE); e$a <- 123");
         assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$b <- 123");
-        assertEval(Ignored.MissingBuiltin, "e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123");
+        assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123");
         assertEval("e <- new.env(); e$a <- 'foo'; lockEnvironment(e, logical()); e$b <- 123");
         assertEval(Ignored.MissingBuiltin, "e <- new.env(); e$a <- 'foo'; lockEnvironment(e, logical()); e$a <- 123");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
index 661b52abaa..a62ed37731 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
@@ -74,9 +74,7 @@ public class TestBuiltin_nchar extends TestBase {
 
     @Test
     public void testnchar13() {
-        // allowNA == TRUE is not implemented
-        assertEval(Ignored.Unimplemented,
-                        "argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\\\'Terry\\\', \\\'Therneau\\\', role = \\\'aut\\\',\\n\\t             email = \\\'therneau@mayo.edu\\\'),\\n             person(\\\'Beth\\\', \\\'Atkinson\\\', role = \\\'aut\\\',\\t\\n\\t             email = \\\'atkinson@mayo.edu\\\'),\\n             person(\\\'Brian\\\', \\\'Ripley\\\', role = c(\\\'aut\\\', \\\'trl\\\', \\\'cre\\\'),\\n                    email = \\\'ripley@stats.ox.ac.uk\\\',\\n\\t\\t   comment = \\\'author of R port\\\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\\n  Beth Atkinson [aut],\\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        assertEval("argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\\\'Terry\\\', \\\'Therneau\\\', role = \\\'aut\\\',\\n\\t             email = \\\'therneau@mayo.edu\\\'),\\n             person(\\\'Beth\\\', \\\'Atkinson\\\', role = \\\'aut\\\',\\t\\n\\t             email = \\\'atkinson@mayo.edu\\\'),\\n             person(\\\'Brian\\\', \\\'Ripley\\\', role = c(\\\'aut\\\', \\\'trl\\\', \\\'cre\\\'),\\n                    email = \\\'ripley@stats.ox.ac.uk\\\',\\n\\t\\t   comment = \\\'author of R port\\\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\\n  Beth Atkinson [aut],\\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
index a1be9ab8d7..c2ad5d4250 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
@@ -374,6 +374,11 @@ public class TestFunctions extends TestBase {
         assertEval(Ignored.Unstable, "{ exists }");
     }
 
+    @Test
+    public void testFunctionResultPrinting() {
+        assertEval("{ foo <- function() { x <- 1; return(x) }; foo() }");
+    }
+
     @Test
     public void testIsPrimitive() {
         assertEval("{ is.primitive(is.primitive) }");
-- 
GitLab


From b056e1d3c07fad89fe5008fda756b4ed2ff5e4ed Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 3 Mar 2017 14:41:56 -0800
Subject: [PATCH 096/402] Revert tests4 after [GR-3100]

---
 .../packages/tests4/tests4/tests/methods1.R                    | 3 +--
 .../packages/tests4/tests4/tests/methods2.R                    | 3 +--
 .../packages/tests4/tests4/tests/methods4.R                    | 3 +--
 .../packages/tests4/tests4/tests/methods5.R                    | 3 +--
 mx.fastr/mx_fastr.py                                           | 2 +-
 5 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R
index 1a1b75d9c5..35c6b67058 100644
--- a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods1.R
@@ -21,6 +21,5 @@ setMethod("sides", signature("Square"),   function(object) 4)
 # setMethod("sides", signature("Circle"),   function(object) Inf)
 
 res<-print(showMethods("sides"))
-# BUG ALERT:In FastR without the "print" the result from removeGeneric (TRUE) is not printed.
-print(removeGeneric("sides"))
+removeGeneric("sides")
 print(res)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R
index 9fdf38279f..375a0a9b87 100644
--- a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods2.R
@@ -21,6 +21,5 @@ setMethod("sides", signature("Square"),   function(object) 4)
 setMethod("sides", signature("Circle"),   function(object) Inf)
 
 res<-print(showMethods(class = "Polygon"))
-# BUG print should not be necessary
-print(removeGeneric("sides"))
+removeGeneric("sides")
 print(res)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R
index 6f75874a4a..b9df6ef17f 100644
--- a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods4.R
@@ -12,6 +12,5 @@ setMethod("foo", signature("A1", "A2"), function(a, b) "1-2")
 setMethod("foo", signature("A2", "A1"), function(a, b) "2-1")
 
 res<-print(foo(new("A2"), new("A2")))
-# BUG print shoukld not be necessary
-print(removeGeneric("foo"))
+removeGeneric("foo")
 print(res)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R
index e8e93ff718..e51df55343 100644
--- a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/methods5.R
@@ -28,5 +28,4 @@ setMethod("inspect.vehicle",
  })
 
 inspect.vehicle(new("Car"), new("Inspector"))
-# BUG print should not be necessary
-print(removeGeneric("inspect.vehicle"))
+removeGeneric("inspect.vehicle")
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 4555be425a..b61e314d5c 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -404,7 +404,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'S4', 'rng', 'runtime.data']))
+    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data']))
 
 def _simple_unit_tests():
     return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
-- 
GitLab


From 742a96475fff285f03007feaee4cb1ff5e6692c3 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Mon, 6 Mar 2017 14:52:03 +0100
Subject: [PATCH 097/402] Eliminated null RCaller failure in tracing mode.

---
 .../oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
index 7b85116832..c7e0be6ae9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -148,7 +148,7 @@ public class TraceHandling {
         protected String getCallSource(VirtualFrame frame) {
             RCaller caller = RArguments.getCall(frame);
             String callString;
-            if (caller != null) {
+            if (caller != null && caller.isValidCaller()) {
                 callString = getCallerSource(caller);
             } else {
                 callString = "<no source>";
-- 
GitLab


From a1eef10e65cb12d047b27a33e5d5a1868b9b2c99 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 1 Mar 2017 18:30:43 +0100
Subject: [PATCH 098/402] Implemented a fast path for writing strings that are
 known to be terminated by a line feed. Improved implementation of file
 read-write access; appending was not implemented. However, currently
 experiencing some performance issues.

---
 .../r/runtime/conn/DelegateRConnection.java   |  50 ++++--
 .../conn/DelegateReadWriteRConnection.java    |  12 +-
 .../r/runtime/conn/FileConnections.java       | 143 ++++++++++++++----
 3 files changed, 161 insertions(+), 44 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 0139c2e9a7..2fb7e09f02 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -328,8 +328,22 @@ abstract class DelegateRConnection implements RConnection {
         return new String(chars, 0, j);
     }
 
+// @Override
+// public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+//
+//
+// // need to reset the stream decoder since position changed
+// reinitDecoder();
+// }
+//
+// protected abstract long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode)
+// throws IOException;
+
     /**
-     * Implements standard seeking behavior.
+     * Implements standard seeking behavior.<br>
+     * <p>
+     * <it>Standard</it> means that there is a shared cursor between reading and writing operations.
+     * </p>
      */
     public static long seek(SeekableByteChannel channel, long offset, SeekMode seekMode, @SuppressWarnings("unused") SeekRWMode seekRWMode) throws IOException {
         long position = channel.position();
@@ -365,13 +379,27 @@ abstract class DelegateRConnection implements RConnection {
     }
 
     public static boolean writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
-        boolean incomplete = false;
-        for (int i = 0; i < lines.getLength(); i++) {
-            final String line = lines.getDataAt(i);
-            incomplete = DelegateRConnection.writeStringHelper(out, line, false, encoding);
-            incomplete = DelegateRConnection.writeStringHelper(out, sep, false, encoding) || incomplete;
+        if (sep != null && sep.contains("\n")) {
+            // fast path: we know that the line is complete
+            final ByteBuffer nlBuf = ByteBuffer.wrap(sep.getBytes(encoding));
+            for (int i = 0; i < lines.getLength(); i++) {
+                final String line = lines.getDataAt(i);
+                final ByteBuffer buf = ByteBuffer.wrap(line.getBytes(encoding));
+                out.write(buf);
+                nlBuf.rewind();
+                out.write(nlBuf);
+            }
+            return false;
+        } else {
+            // slow path: we have to scan every string if it contains a newline
+            boolean incomplete = false;
+            for (int i = 0; i < lines.getLength(); i++) {
+                final String line = lines.getDataAt(i);
+                incomplete = DelegateRConnection.writeStringHelper(out, line, false, encoding);
+                incomplete = DelegateRConnection.writeStringHelper(out, sep, false, encoding) || incomplete;
+            }
+            return incomplete;
         }
-        return incomplete;
     }
 
     @Override
@@ -384,9 +412,13 @@ abstract class DelegateRConnection implements RConnection {
      */
     protected StreamDecoder getDecoder() throws IOException {
         if (decoder == null) {
-            CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
-            decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, -1);
+            initDecoder();
         }
         return decoder;
     }
+
+    private void initDecoder() throws IOException {
+        CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
+        decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, -1);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 011cf49d1b..7154492f4e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -51,10 +51,14 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
     @Override
     public int getc() throws IOException {
-        tmp.clear();
-        int nread = getChannel().read(tmp);
-        tmp.rewind();
-        return nread > 0 ? tmp.get() : -1;
+        if (isTextMode()) {
+            return getDecoder().read();
+        } else {
+            tmp.clear();
+            int nread = getChannel().read(tmp);
+            tmp.rewind();
+            return nread > 0 ? tmp.get() : -1;
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index a72e817ec1..db41550211 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -54,7 +54,6 @@ import com.oracle.truffle.r.runtime.TempPathName;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BasePathRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.OpenMode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class FileConnections {
@@ -140,8 +139,14 @@ public class FileConnections {
                 delegate = new FileWriteBinaryConnection(base, false);
                 break;
             case ReadWriteTrunc:
+                delegate = new FileReadWriteTextConnection(base);
+                break;
             case ReadWriteTruncBinary:
-                delegate = new FileReadWriteConnection(base);
+                delegate = new FileReadWriteBinaryConnection(base, false);
+                break;
+            case ReadAppend:
+            case ReadAppendBinary:
+                delegate = new FileReadWriteBinaryConnection(base, true);
                 break;
             default:
                 throw RError.nyi(RError.SHOW_CALLER2, "open mode: " + base.getOpenMode());
@@ -326,7 +331,94 @@ public class FileConnections {
 
     }
 
-    private static class FileReadWriteConnection extends DelegateReadWriteRConnection {
+    private static class FileReadWriteTextConnection extends DelegateReadWriteRConnection {
+
+        private final FileChannel channel;
+        private long readOffset;
+        private long writeOffset;
+        private SeekRWMode lastMode = SeekRWMode.READ;
+
+        FileReadWriteTextConnection(BasePathRConnection base) throws IOException {
+            super(base);
+            List<OpenOption> opts = new ArrayList<>();
+            opts.add(StandardOpenOption.READ);
+            opts.add(StandardOpenOption.WRITE);
+            opts.add(StandardOpenOption.CREATE);
+            opts.add(StandardOpenOption.TRUNCATE_EXISTING);
+            channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
+        }
+
+        @Override
+        public int getc() throws IOException {
+            channel.position(readOffset);
+            int value = super.getc();
+            if (value != -1) {
+                readOffset++;
+            }
+            return value;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return true;
+        }
+
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            long result = channel.position();
+            switch (seekMode) {
+                case ENQUIRE:
+                    return result;
+                case START:
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER, "seek mode");
+            }
+            switch (seekRWMode) {
+                case LAST:
+                    if (lastMode == SeekRWMode.READ) {
+                        readOffset = offset;
+                    } else {
+                        writeOffset = offset;
+                    }
+                    break;
+                case READ:
+                    readOffset = offset;
+                    break;
+                case WRITE:
+                    writeOffset = offset;
+                    break;
+            }
+            return result;
+        }
+
+        @Override
+        public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
+            channel.position(readOffset);
+            return super.readLines(n, warn, skipNul);
+        }
+
+        @Override
+        public void close() throws IOException {
+            channel.close();
+        }
+
+        @Override
+        public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+            channel.position(writeOffset);
+            super.writeLines(lines, sep, useBytes);
+            writeOffset = channel.position();
+            lastMode = SeekRWMode.WRITE;
+        }
+
+        @Override
+        public ByteChannel getChannel() {
+            return channel;
+        }
+
+    }
+
+    private static class FileReadWriteBinaryConnection extends DelegateReadWriteRConnection {
         /*
          * This is a minimal implementation to support one specific use in package installation.
          *
@@ -339,25 +431,20 @@ public class FileConnections {
         private long writeOffset;
         private SeekRWMode lastMode = SeekRWMode.READ;
 
-        FileReadWriteConnection(BasePathRConnection base) throws IOException {
+        FileReadWriteBinaryConnection(BasePathRConnection base, boolean append) throws IOException {
             super(base);
-            OpenMode openMode = base.getOpenMode();
-            String rafMode = null;
-            switch (openMode.abstractOpenMode) {
-                case ReadWriteTrunc:
-                case ReadWriteTruncBinary:
-                    rafMode = "rw";
-                    break;
-                default:
-                    throw RInternalError.shouldNotReachHere();
+            raf = new RandomAccessFile(base.path, "rw");
+            if (append) {
+                writeOffset = raf.length();
+            } else {
+                raf.setLength(0);
             }
-            raf = new RandomAccessFile(base.path, rafMode);
         }
 
         @Override
         public int getc() throws IOException {
-            raf.seek(readOffset);
-            int value = raf.read();
+            setPosition(readOffset);
+            int value = super.getc();
             if (value != -1) {
                 readOffset++;
             }
@@ -400,10 +487,16 @@ public class FileConnections {
 
         @Override
         public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
-            raf.seek(readOffset);
+            setPosition(readOffset);
             return super.readLines(n, warn, skipNul);
         }
 
+        private void setPosition(long pos) throws IOException {
+            if (raf.getFilePointer() != pos) {
+                raf.seek(pos);
+            }
+        }
+
         @Override
         public void close() throws IOException {
             raf.close();
@@ -411,24 +504,12 @@ public class FileConnections {
 
         @Override
         public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            raf.seek(writeOffset);
-            byte[] sepData = sep.getBytes(base.getEncoding());
-            for (int i = 0; i < lines.getLength(); i++) {
-                writeString(lines.getDataAt(i), false);
-                raf.write(sepData);
-            }
+            setPosition(writeOffset);
+            super.writeLines(lines, sep, useBytes);
             writeOffset = raf.getFilePointer();
             lastMode = SeekRWMode.WRITE;
         }
 
-        @Override
-        public void writeString(String s, boolean nl) throws IOException {
-            raf.write(s.getBytes(base.getEncoding()));
-            if (nl) {
-                raf.write(System.lineSeparator().getBytes(base.getEncoding()));
-            }
-        }
-
         @Override
         public ByteChannel getChannel() {
             return raf.getChannel();
-- 
GitLab


From 2d83cabfa3707c9876ee6c290f5123ca1e7b5a44 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 2 Mar 2017 15:55:55 +0100
Subject: [PATCH 099/402] Implemented internal function 'truncate'.

---
 .../r/nodes/builtin/base/BasePackage.java     |  1 +
 .../builtin/base/ConnectionFunctions.java     | 37 +++++++--
 .../com/oracle/truffle/r/runtime/RError.java  |  4 +
 .../r/runtime/conn/ConnectionSupport.java     | 15 ++++
 .../r/runtime/conn/DelegateRConnection.java   |  8 ++
 .../runtime/conn/DelegateReadRConnection.java |  5 ++
 .../r/runtime/conn/FileConnections.java       | 75 ++++++++++++++++---
 .../truffle/r/runtime/conn/RConnection.java   |  5 ++
 .../r/runtime/conn/RawConnections.java        |  9 +++
 .../conn/SeekableMemoryByteChannel.java       | 23 +++++-
 .../truffle/r/test/ExpectedTestOutput.test    | 40 ++++++++++
 .../r/test/library/base/TestConnections.java  | 10 +++
 12 files changed, 209 insertions(+), 23 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 987209e766..4d3905afb9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -266,6 +266,7 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.ReadChar.class, ConnectionFunctionsFactory.ReadCharNodeGen::create);
         add(ConnectionFunctions.ReadLines.class, ConnectionFunctionsFactory.ReadLinesNodeGen::create);
         add(ConnectionFunctions.Seek.class, ConnectionFunctionsFactory.SeekNodeGen::create);
+        add(ConnectionFunctions.Truncate.class, ConnectionFunctionsFactory.TruncateNodeGen::create);
         add(ConnectionFunctions.SocketConnection.class, ConnectionFunctionsFactory.SocketConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnection.class, ConnectionFunctionsFactory.RawConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnectionValue.class, ConnectionFunctionsFactory.RawConnectionValueNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 30aa8c4efb..785b4a0f00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -241,7 +241,7 @@ public abstract class ConnectionFunctions {
                 // ignore and try to open file
             } catch (IOException e) {
                 RError.warning(RError.SHOW_CALLER, RError.Message.UNABLE_TO_RESOLVE, e.getMessage());
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+                throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             }
 
             if (path.length() == 0) {
@@ -295,7 +295,7 @@ public abstract class ConnectionFunctions {
             } catch (IOException ex) {
                 throw reportError(description, ex);
             } catch (IllegalCharsetNameException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
+                throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
 
@@ -1258,10 +1258,10 @@ public abstract class ConnectionFunctions {
             try {
                 return new FifoRConnection(path, open, blocking, encoding).asVector();
             } catch (IOException ex) {
-                RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+                warning(RError.Message.CANNOT_OPEN_FIFO, path);
+                throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
+                throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -1284,10 +1284,10 @@ public abstract class ConnectionFunctions {
             try {
                 return new PipeRConnection(path, open, encoding).asVector();
             } catch (IOException ex) {
-                RError.warning(this, RError.Message.CANNOT_OPEN_FIFO, path);
-                throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_OPEN_CONNECTION);
+                warning(RError.Message.CANNOT_OPEN_FIFO, path);
+                throw error(RError.Message.CANNOT_OPEN_CONNECTION);
             } catch (IllegalCharsetNameException ex) {
-                throw RError.error(RError.SHOW_CALLER, RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
+                throw error(RError.Message.UNSUPPORTED_ENCODING_CONVERSION, encoding, "");
             }
         }
     }
@@ -1308,4 +1308,25 @@ public abstract class ConnectionFunctions {
             return RDataFactory.createLogicalVectorFromScalar(res);
         }
     }
+
+    @RBuiltin(name = "truncate", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
+    public abstract static class Truncate extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(Truncate.class);
+            CastsHelper.connection(casts);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected RNull truncate(int con) {
+
+            try {
+                RConnection.fromIndex(con).truncate();
+            } catch (IOException e) {
+                throw error(RError.Message.TRUNCATE_UNSUPPORTED_FOR_CONN, e.getMessage());
+            }
+            return RNull.instance;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 6e8c5a1207..c7757fbb17 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -842,6 +842,10 @@ public final class RError extends RuntimeException {
         LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul"),
         UNSUPPORTED_URL_METHOD("method = \"%s\" is not supported"),
         CANNOT_REPLICATE_NULL("cannot replicate NULL to a non-zero length");
+        TRUNCATE_ONLY_WRITE_CONNECTION("can only truncate connections open for writing"),
+        TRUNCATE_ONLY_OPEN_CONN("can only truncate an open connection"),
+        TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
+        TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 3e0941dce2..293e285677 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -482,6 +482,11 @@ public class ConnectionSupport {
         public ByteChannel getChannel() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
+
+        @Override
+        public void truncate() throws IOException {
+            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
+        }
     }
 
     /**
@@ -1031,6 +1036,16 @@ public class ConnectionSupport {
             return seekInternal(offset, seekMode, seekRWMode);
         }
 
+        @Override
+        public void truncate() throws IOException {
+            checkOpen();
+            if (!closed && opened) {
+                theConnection.truncate();
+            } else {
+                throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_ONLY_OPEN_CONN);
+            }
+        }
+
         /**
          * Returns {@code true} iff the last read operation was blocked or there is unflushed
          * output.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 2fb7e09f02..fe00520286 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -421,4 +421,12 @@ abstract class DelegateRConnection implements RConnection {
         CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
         decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, -1);
     }
+
+    @Override
+    public void truncate() throws IOException {
+        if (!isSeekable()) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_NOT_ENABLED);
+        }
+        throw RError.nyi(RError.SHOW_CALLER, "truncate");
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index 70a2bac8df..ceef89ca96 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -128,4 +128,9 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
         close();
     }
 
+    @Override
+    public void truncate() {
+        throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_ONLY_WRITE_CONNECTION);
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index db41550211..60639c774e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -324,11 +324,21 @@ public class FileConnections {
             return true;
         }
 
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            return DelegateRConnection.seek(channel, offset, seekMode, seekRWMode);
+        }
+
         @Override
         public ByteChannel getChannel() {
             return channel;
         }
 
+        @Override
+        public void truncate() throws IOException {
+            channel.truncate(0);
+        }
+
     }
 
     private static class FileReadWriteTextConnection extends DelegateReadWriteRConnection {
@@ -350,7 +360,7 @@ public class FileConnections {
 
         @Override
         public int getc() throws IOException {
-            channel.position(readOffset);
+            setReadPosition();
             int value = super.getc();
             if (value != -1) {
                 readOffset++;
@@ -394,7 +404,7 @@ public class FileConnections {
 
         @Override
         public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
-            channel.position(readOffset);
+            setReadPosition();
             return super.readLines(n, warn, skipNul);
         }
 
@@ -405,10 +415,9 @@ public class FileConnections {
 
         @Override
         public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            channel.position(writeOffset);
+            setWritePosition();
             super.writeLines(lines, sep, useBytes);
             writeOffset = channel.position();
-            lastMode = SeekRWMode.WRITE;
         }
 
         @Override
@@ -416,6 +425,29 @@ public class FileConnections {
             return channel;
         }
 
+        private void setReadPosition() throws IOException {
+            if (lastMode != SeekRWMode.READ) {
+                channel.position(readOffset);
+                lastMode = SeekRWMode.READ;
+            }
+        }
+
+        private void setWritePosition() throws IOException {
+            if (lastMode != SeekRWMode.WRITE) {
+                channel.position(writeOffset);
+                lastMode = SeekRWMode.WRITE;
+            }
+        }
+
+        @Override
+        public void truncate() throws IOException {
+            channel.truncate(writeOffset);
+            lastMode = SeekRWMode.WRITE;
+            // GnuR also freshly queries the file pointer. It may happen that the file pointer is
+            // different as expected.
+            writeOffset = channel.position();
+        }
+
     }
 
     private static class FileReadWriteBinaryConnection extends DelegateReadWriteRConnection {
@@ -443,7 +475,7 @@ public class FileConnections {
 
         @Override
         public int getc() throws IOException {
-            setPosition(readOffset);
+            setReadPosition();
             int value = super.getc();
             if (value != -1) {
                 readOffset++;
@@ -487,13 +519,21 @@ public class FileConnections {
 
         @Override
         public String[] readLines(int n, boolean warn, boolean skipNul) throws IOException {
-            setPosition(readOffset);
+            setReadPosition();
             return super.readLines(n, warn, skipNul);
         }
 
-        private void setPosition(long pos) throws IOException {
-            if (raf.getFilePointer() != pos) {
-                raf.seek(pos);
+        private void setReadPosition() throws IOException {
+            if (lastMode != SeekRWMode.READ) {
+                raf.seek(readOffset);
+                lastMode = SeekRWMode.READ;
+            }
+        }
+
+        private void setWritePosition() throws IOException {
+            if (lastMode != SeekRWMode.WRITE) {
+                raf.seek(writeOffset);
+                lastMode = SeekRWMode.WRITE;
             }
         }
 
@@ -504,10 +544,9 @@ public class FileConnections {
 
         @Override
         public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-            setPosition(writeOffset);
+            setWritePosition();
             super.writeLines(lines, sep, useBytes);
             writeOffset = raf.getFilePointer();
-            lastMode = SeekRWMode.WRITE;
         }
 
         @Override
@@ -515,6 +554,15 @@ public class FileConnections {
             return raf.getChannel();
         }
 
+        @Override
+        public void truncate() throws IOException {
+            raf.setLength(writeOffset);
+            lastMode = SeekRWMode.WRITE;
+            // GnuR also freshly queries the file pointer. It may happen that the file pointer is
+            // different as expected.
+            writeOffset = raf.getFilePointer();
+        }
+
     }
 
     private static class CompressedInputRConnection extends DelegateReadRConnection {
@@ -580,6 +628,11 @@ public class FileConnections {
         public ByteChannel getChannel() {
             return channel;
         }
+
+        @Override
+        public void truncate() throws IOException {
+            throw RError.nyi(RError.SHOW_CALLER, "truncating compressed file not");
+        }
     }
 
     private static class BZip2OutputRConnection extends CompressedOutputRConnection {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 341d12e3ba..e6a345e5a6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -217,5 +217,10 @@ public interface RConnection extends AutoCloseable {
      */
     boolean isOpen();
 
+    /**
+     * Truncates the connection (if possible).
+     */
+    void truncate() throws IOException;
+
     void pushBack(RAbstractStringVector lines, boolean addNewLine);
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 3213cfc97f..35b504eead 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -192,6 +192,11 @@ public class RawConnections {
         public boolean isSeekable() {
             return true;
         }
+
+        @Override
+        public void truncate() throws IOException {
+            channel.truncate(channel.position());
+        }
     }
 
     private static class RawReadWriteConnection extends DelegateReadWriteRConnection {
@@ -225,6 +230,10 @@ public class RawConnections {
             return true;
         }
 
+        @Override
+        public void truncate() throws IOException {
+            channel.truncate(channel.position());
+        }
     }
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
index c625c855a3..256b4e4a99 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -200,12 +200,27 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
 
     @Override
     public SeekableByteChannel truncate(long size) throws IOException {
+        if (size < 0) {
+            throw new IllegalArgumentException("'size' cannot be negative");
+        }
+
         // avoid security leak by nulling previous data
-        Arrays.fill(buf, (byte) 0);
+        final int from;
+        final int to;
+        if (size < endPos) {
+            from = (int) (size - offset);
+            to = (int) (endPos - offset);
+        } else {
+            to = (int) (size - offset);
+            from = (int) (endPos - offset);
+
+            // need to enlarge buffer
+            ensureCapacity(to);
+        }
+        Arrays.fill(buf, from, to, (byte) 0);
 
-        offset = 0;
-        position = 0;
-        endPos = 0;
+        position = Math.min(position, size);
+        endPos = size;
         return this;
     }
 
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 e1ec10e788..93ce805b06 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
@@ -73717,6 +73717,46 @@ Error in textConnection(NULL, "r") : invalid 'text' argument
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#fn <- '__tmp_77253842367367'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); close(zz); readLines(file(fn)); unlink(fn)
+[1] 22
+NULL
+character(0)
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#fn <- '__tmp_98723669834556'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); close(zz); zz <- file(fn, 'r'); truncate(zz); unlink(fn)
+Error in truncate.connection(zz) :
+  can only truncate connections open for writing
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#truncate(fifo('__fifo_872636743', 'w+')); unlink('__fifo_872636743')
+Error in truncate.connection(fifo("__fifo_872636743", "w+")) :
+  truncation not enabled for this connection
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#truncate(fifo('__fifo_982346798', 'r')); unlink('__fifo_982346798')
+Error in fifo("__fifo_982346798", "r") : cannot open the connection
+In addition: Warning message:
+In fifo("__fifo_982346798", "r") : cannot open fifo '__fifo_982346798'
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#truncate(pipe('ls'))
+Error in truncate.connection(pipe("ls")) :
+  can only truncate an open connection
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#zz <- file(''); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); flush(zz); readLines(zz)
+[1] 22
+NULL
+character(0)
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
+#zz <- rawConnection(raw(0), 'r+'); writeLines(c('hello', 'world'), zz); rawConnectionValue(zz); seek(zz, 5); truncate(zz); rawConnectionValue(zz); close(zz)
+ [1] 68 65 6c 6c 6f 0a 77 6f 72 6c 64 0a
+[1] 12
+NULL
+[1] 68 65 6c 6c 6f
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 4bae7a3225..6df0527db7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -240,6 +240,16 @@ public class TestConnections extends TestRBase {
         assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }");
     }
 
+    public void testTruncate() {
+        assertEval("truncate(pipe('ls'))");
+        assertEval("zz <- file(''); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); flush(zz); readLines(zz)");
+        assertEval("fn <- '__tmp_77253842367367'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); close(zz); readLines(file(fn)); unlink(fn)");
+        assertEval("fn <- '__tmp_98723669834556'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); close(zz); zz <- file(fn, 'r'); truncate(zz); unlink(fn)");
+        assertEval("zz <- rawConnection(raw(0), 'r+'); writeLines(c('hello', 'world'), zz); rawConnectionValue(zz); seek(zz, 5); truncate(zz); rawConnectionValue(zz); close(zz)");
+        assertEval("truncate(fifo('__fifo_872636743', 'w+')); unlink('__fifo_872636743')");
+        assertEval("truncate(fifo('__fifo_982346798', 'r')); unlink('__fifo_982346798')");
+    }
+
     private static final String[] LVAL = arr("T", "F");
 
     private static String[] arr(String... args) {
-- 
GitLab


From 2d6cdf76357706a9d919d80b422a0e6f9bfc6fa1 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 2 Mar 2017 18:27:21 +0100
Subject: [PATCH 100/402] Fixed issue with character-wise reading from a
 text-mode connection. Fixed issue when setting the r/w seek position in a
 binary-mode file connection.

---
 .../r/runtime/conn/DelegateRConnection.java   | 27 ++++--
 .../r/runtime/conn/FileConnections.java       | 83 +++++++++++++++++--
 .../truffle/r/test/ExpectedTestOutput.test    | 12 +--
 .../r/test/library/base/TestConnections.java  |  4 +-
 4 files changed, 105 insertions(+), 21 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index fe00520286..37fd174e7a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -101,7 +101,7 @@ abstract class DelegateRConnection implements RConnection {
         base.setIncomplete(false);
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
-        byte[] buffer = new byte[64];
+        char[] buffer = new char[64];
         int pushBack = 0;
         boolean nullRead = false;
         while (true) {
@@ -119,7 +119,7 @@ abstract class DelegateRConnection implements RConnection {
                      * GnuR says if non-blocking and in text mode, silently push back incomplete
                      * lines, otherwise keep data and output warning.
                      */
-                    final String incompleteFinalLine = new String(buffer, 0, totalRead, base.getEncoding());
+                    final String incompleteFinalLine = new String(buffer, 0, totalRead);
                     if (!base.isBlocking() && base.isTextMode()) {
                         base.pushBack(RDataFactory.createStringVector(incompleteFinalLine), false);
                         base.setIncomplete(true);
@@ -149,7 +149,7 @@ abstract class DelegateRConnection implements RConnection {
                 }
             }
             if (lineEnd) {
-                lines.add(new String(buffer, 0, totalRead, base.getEncoding()));
+                lines.add(new String(buffer, 0, totalRead));
                 if (n > 0 && lines.size() == n) {
                     break;
                 }
@@ -158,7 +158,7 @@ abstract class DelegateRConnection implements RConnection {
             } else {
                 if (!nullRead) {
                     buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
-                    buffer[totalRead++] = (byte) (ch & 0xFF);
+                    buffer[totalRead++] = (char) (ch & 0xFFFF);
                 }
                 if (skipNul) {
                     nullRead = false;
@@ -365,6 +365,19 @@ abstract class DelegateRConnection implements RConnection {
         return position;
     }
 
+    /**
+     * Enlarges the buffer if necessary.
+     */
+    private static char[] checkBuffer(char[] buffer, int n) {
+        if (n > buffer.length - 1) {
+            char[] newBuffer = new char[buffer.length + buffer.length / 2];
+            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
+            return newBuffer;
+        } else {
+            return buffer;
+        }
+    }
+
     /**
      * Enlarges the buffer if necessary.
      */
@@ -412,14 +425,14 @@ abstract class DelegateRConnection implements RConnection {
      */
     protected StreamDecoder getDecoder() throws IOException {
         if (decoder == null) {
-            initDecoder();
+            initDecoder(-1);
         }
         return decoder;
     }
 
-    private void initDecoder() throws IOException {
+    protected void initDecoder(int bufSize) throws IOException {
         CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
-        decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, -1);
+        decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, bufSize);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 60639c774e..dd879051c3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -31,8 +31,11 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.FileChannel;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetEncoder;
 import java.nio.file.OpenOption;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
@@ -344,6 +347,7 @@ public class FileConnections {
     private static class FileReadWriteTextConnection extends DelegateReadWriteRConnection {
 
         private final FileChannel channel;
+        private final CharsetEncoder encoder;
         private long readOffset;
         private long writeOffset;
         private SeekRWMode lastMode = SeekRWMode.READ;
@@ -356,6 +360,7 @@ public class FileConnections {
             opts.add(StandardOpenOption.CREATE);
             opts.add(StandardOpenOption.TRUNCATE_EXISTING);
             channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
+            encoder = base.getEncoding().newEncoder();
         }
 
         @Override
@@ -363,11 +368,18 @@ public class FileConnections {
             setReadPosition();
             int value = super.getc();
             if (value != -1) {
-                readOffset++;
+                readOffset += getNumBytes(value);
             }
             return value;
         }
 
+        private long getNumBytes(int value) throws CharacterCodingException {
+            // TODO We need to get the information about how much bytes have been consumed from the
+            // stream decoder. This is really bad!
+            ByteBuffer encode = encoder.encode(CharBuffer.wrap(new char[]{(char) value}));
+            return encode.position();
+        }
+
         @Override
         public boolean isSeekable() {
             return true;
@@ -375,10 +387,11 @@ public class FileConnections {
 
         @Override
         public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            long result = channel.position();
+            long result;
+            boolean set = true;
             switch (seekMode) {
                 case ENQUIRE:
-                    return result;
+                    set = false;
                 case START:
                     break;
                 default:
@@ -387,17 +400,31 @@ public class FileConnections {
             switch (seekRWMode) {
                 case LAST:
                     if (lastMode == SeekRWMode.READ) {
-                        readOffset = offset;
+                        result = readOffset;
+                        if (set) {
+                            readOffset = offset;
+                        }
                     } else {
-                        writeOffset = offset;
+                        result = writeOffset;
+                        if (set) {
+                            writeOffset = offset;
+                        }
                     }
                     break;
                 case READ:
-                    readOffset = offset;
+                    result = readOffset;
+                    if (set) {
+                        readOffset = offset;
+                    }
                     break;
                 case WRITE:
-                    writeOffset = offset;
+                    result = writeOffset;
+                    if (set) {
+                        writeOffset = offset;
+                    }
                     break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER, "seek mode");
             }
             return result;
         }
@@ -429,6 +456,9 @@ public class FileConnections {
             if (lastMode != SeekRWMode.READ) {
                 channel.position(readOffset);
                 lastMode = SeekRWMode.READ;
+
+                // re-initialize stream decoder if position changed
+                initDecoder(1);
             }
         }
 
@@ -523,10 +553,31 @@ public class FileConnections {
             return super.readLines(n, warn, skipNul);
         }
 
+        @Override
+        public int readBin(ByteBuffer buffer) throws IOException {
+            setReadPosition();
+            return super.readBin(buffer);
+        }
+
+        @Override
+        public String readChar(int nchars, boolean useBytes) throws IOException {
+            setReadPosition();
+            return super.readChar(nchars, useBytes);
+        }
+
+        @Override
+        public byte[] readBinChars() throws IOException {
+            setReadPosition();
+            return super.readBinChars();
+        }
+
         private void setReadPosition() throws IOException {
             if (lastMode != SeekRWMode.READ) {
                 raf.seek(readOffset);
                 lastMode = SeekRWMode.READ;
+
+                // re-initialize stream decoder if position changed
+                initDecoder(1);
             }
         }
 
@@ -549,6 +600,24 @@ public class FileConnections {
             writeOffset = raf.getFilePointer();
         }
 
+        @Override
+        public void writeBin(ByteBuffer buffer) throws IOException {
+            setWritePosition();
+            super.writeBin(buffer);
+        }
+
+        @Override
+        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+            setWritePosition();
+            super.writeChar(s, pad, eos, useBytes);
+        }
+
+        @Override
+        public void writeString(String s, boolean nl) throws IOException {
+            setWritePosition();
+            super.writeString(s, nl);
+        }
+
         @Override
         public ByteChannel getChannel() {
             return raf.getChannel();
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 93ce805b06..cdc9c7e314 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
@@ -73729,15 +73729,17 @@ Error in truncate.connection(zz) :
   can only truncate connections open for writing
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#truncate(fifo('__fifo_872636743', 'w+')); unlink('__fifo_872636743')
-Error in truncate.connection(fifo("__fifo_872636743", "w+")) :
+#truncate(fifo('__fifo_872636743', 'w+', blocking=T)); unlink('__fifo_872636743')
+Error in truncate.connection(fifo("__fifo_872636743", "w+", blocking = T)) :
   truncation not enabled for this connection
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#truncate(fifo('__fifo_982346798', 'r')); unlink('__fifo_982346798')
-Error in fifo("__fifo_982346798", "r") : cannot open the connection
+#truncate(fifo('__fifo_982346798', 'r', blocking=T)); unlink('__fifo_982346798')
+Error in fifo("__fifo_982346798", "r", blocking = T) :
+  cannot open the connection
 In addition: Warning message:
-In fifo("__fifo_982346798", "r") : cannot open fifo '__fifo_982346798'
+In fifo("__fifo_982346798", "r", blocking = T) :
+  cannot open fifo '__fifo_982346798'
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
 #truncate(pipe('ls'))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 6df0527db7..058b6cb3fc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -246,8 +246,8 @@ public class TestConnections extends TestRBase {
         assertEval("fn <- '__tmp_77253842367367'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); close(zz); readLines(file(fn)); unlink(fn)");
         assertEval("fn <- '__tmp_98723669834556'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); close(zz); zz <- file(fn, 'r'); truncate(zz); unlink(fn)");
         assertEval("zz <- rawConnection(raw(0), 'r+'); writeLines(c('hello', 'world'), zz); rawConnectionValue(zz); seek(zz, 5); truncate(zz); rawConnectionValue(zz); close(zz)");
-        assertEval("truncate(fifo('__fifo_872636743', 'w+')); unlink('__fifo_872636743')");
-        assertEval("truncate(fifo('__fifo_982346798', 'r')); unlink('__fifo_982346798')");
+        assertEval("truncate(fifo('__fifo_872636743', 'w+', blocking=T)); unlink('__fifo_872636743')");
+        assertEval("truncate(fifo('__fifo_982346798', 'r', blocking=T)); unlink('__fifo_982346798')");
     }
 
     private static final String[] LVAL = arr("T", "F");
-- 
GitLab


From 1f24e2cb6043bb614610ebab55cfa614aaa59d4f Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 2 Mar 2017 19:33:14 +0100
Subject: [PATCH 101/402] Refactored reading of single elements from a
 connection. Now, everything is again byte-based (even in a text-mode
 connection) and the read bytes are then encoded at once. This makes the code
 much cleaner. However, this assumes that a multi-byte character cannot
 contain any of the byte signatures of NUL '0x00' or line feed '0x0A'. But I
 haven't seen this in the UTF-8/UTF-16 tables.

---
 .../r/runtime/conn/ConnectionSupport.java     |   6 +-
 .../r/runtime/conn/DelegateRConnection.java   | 136 ++++++++++++------
 .../runtime/conn/DelegateReadRConnection.java |  56 --------
 .../conn/DelegateReadWriteRConnection.java    |  97 -------------
 .../conn/DelegateWriteRConnection.java        |  49 +------
 .../r/runtime/conn/FileConnections.java       |  29 +---
 .../truffle/r/runtime/conn/RConnection.java   |   6 +-
 .../r/runtime/conn/StdConnections.java        |   4 +-
 8 files changed, 111 insertions(+), 272 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 293e285677..3ff5c7dff1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -409,7 +409,7 @@ public class ConnectionSupport {
         }
 
         @Override
-        public int getc() throws IOException {
+        public int read() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
@@ -839,9 +839,9 @@ public class ConnectionSupport {
         }
 
         @Override
-        public int getc() throws IOException {
+        public int read() throws IOException {
             checkOpen();
-            return theConnection.getc();
+            return theConnection.read();
         }
 
         public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 37fd174e7a..1d6159c545 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -24,8 +24,11 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.Reader;
 import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
 import java.nio.channels.WritableByteChannel;
@@ -54,7 +57,7 @@ import sun.nio.cs.StreamDecoder;
  */
 abstract class DelegateRConnection implements RConnection {
     protected final BaseRConnection base;
-    private StreamDecoder decoder;
+    final ByteBuffer tmp = ByteBuffer.allocate(1);
 
     DelegateRConnection(BaseRConnection base) {
         this.base = Objects.requireNonNull(base);
@@ -101,7 +104,7 @@ abstract class DelegateRConnection implements RConnection {
         base.setIncomplete(false);
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
-        char[] buffer = new char[64];
+        byte[] buffer = new byte[64];
         int pushBack = 0;
         boolean nullRead = false;
         while (true) {
@@ -110,7 +113,7 @@ abstract class DelegateRConnection implements RConnection {
                 ch = pushBack;
                 pushBack = 0;
             } else {
-                ch = getc();
+                ch = read();
             }
             boolean lineEnd = false;
             if (ch < 0) {
@@ -119,7 +122,7 @@ abstract class DelegateRConnection implements RConnection {
                      * GnuR says if non-blocking and in text mode, silently push back incomplete
                      * lines, otherwise keep data and output warning.
                      */
-                    final String incompleteFinalLine = new String(buffer, 0, totalRead);
+                    final String incompleteFinalLine = new String(buffer, 0, totalRead, base.getEncoding());
                     if (!base.isBlocking() && base.isTextMode()) {
                         base.pushBack(RDataFactory.createStringVector(incompleteFinalLine), false);
                         base.setIncomplete(true);
@@ -136,7 +139,7 @@ abstract class DelegateRConnection implements RConnection {
                 lineEnd = true;
             } else if (ch == '\r') {
                 lineEnd = true;
-                ch = getc();
+                ch = read();
                 if (ch == '\n') {
                     // swallow the trailing lf
                 } else {
@@ -149,7 +152,7 @@ abstract class DelegateRConnection implements RConnection {
                 }
             }
             if (lineEnd) {
-                lines.add(new String(buffer, 0, totalRead));
+                lines.add(new String(buffer, 0, totalRead, base.getEncoding()));
                 if (n > 0 && lines.size() == n) {
                     break;
                 }
@@ -158,7 +161,7 @@ abstract class DelegateRConnection implements RConnection {
             } else {
                 if (!nullRead) {
                     buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
-                    buffer[totalRead++] = (char) (ch & 0xFFFF);
+                    buffer[totalRead++] = (byte) (ch & 0xFF);
                 }
                 if (skipNul) {
                     nullRead = false;
@@ -170,6 +173,15 @@ abstract class DelegateRConnection implements RConnection {
         return result;
     }
 
+    @Override
+    public String readChar(int nchars, boolean useBytes) throws IOException {
+        if (useBytes) {
+            return DelegateRConnection.readCharHelper(nchars, getChannel());
+        } else {
+            return DelegateRConnection.readCharHelper(nchars, getDecoder(nchars));
+        }
+    }
+
     /**
      * Writes a string to a channel.
      *
@@ -328,17 +340,6 @@ abstract class DelegateRConnection implements RConnection {
         return new String(chars, 0, j);
     }
 
-// @Override
-// public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-//
-//
-// // need to reset the stream decoder since position changed
-// reinitDecoder();
-// }
-//
-// protected abstract long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode)
-// throws IOException;
-
     /**
      * Implements standard seeking behavior.<br>
      * <p>
@@ -365,19 +366,6 @@ abstract class DelegateRConnection implements RConnection {
         return position;
     }
 
-    /**
-     * Enlarges the buffer if necessary.
-     */
-    private static char[] checkBuffer(char[] buffer, int n) {
-        if (n > buffer.length - 1) {
-            char[] newBuffer = new char[buffer.length + buffer.length / 2];
-            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
-            return newBuffer;
-        } else {
-            return buffer;
-        }
-    }
-
     /**
      * Enlarges the buffer if necessary.
      */
@@ -423,16 +411,9 @@ abstract class DelegateRConnection implements RConnection {
     /**
      * Creates the stream decoder on demand and returns it.
      */
-    protected StreamDecoder getDecoder() throws IOException {
-        if (decoder == null) {
-            initDecoder(-1);
-        }
-        return decoder;
-    }
-
-    protected void initDecoder(int bufSize) throws IOException {
+    protected StreamDecoder getDecoder(int bufSize) throws IOException {
         CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
-        decoder = StreamDecoder.forDecoder(getChannel(), charsetEncoder, bufSize);
+        return StreamDecoder.forDecoder(getChannel(), charsetEncoder, bufSize);
     }
 
     @Override
@@ -442,4 +423,79 @@ abstract class DelegateRConnection implements RConnection {
         }
         throw RError.nyi(RError.SHOW_CALLER, "truncate");
     }
+
+    @Override
+    public void writeBin(ByteBuffer buffer) throws IOException {
+        getChannel().write(buffer);
+    }
+
+    @Override
+    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+        DelegateRConnection.writeCharHelper(getChannel(), s, pad, eos);
+    }
+
+    @Override
+    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
+        boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        base.setIncomplete(incomplete);
+    }
+
+    @Override
+    public void writeString(String s, boolean nl) throws IOException {
+        DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+    }
+
+    @Override
+    public int read() throws IOException {
+        tmp.clear();
+        int nread = getChannel().read(tmp);
+        tmp.rewind();
+        return nread > 0 ? tmp.get() & 0xFF : -1;
+    }
+
+    @Override
+    public int readBin(ByteBuffer buffer) throws IOException {
+        return getChannel().read(buffer);
+    }
+
+    @Override
+    public byte[] readBinChars() throws IOException {
+        return DelegateRConnection.readBinCharsHelper(getChannel());
+    }
+
+    @Override
+    public boolean canRead() {
+        return true;
+    }
+
+    @Override
+    public boolean canWrite() {
+        return true;
+    }
+
+    @Override
+    public void flush() throws IOException {
+        // nothing to do for channels
+    }
+
+    @Override
+    public OutputStream getOutputStream() throws IOException {
+        return Channels.newOutputStream(getChannel());
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+        return Channels.newInputStream(getChannel());
+    }
+
+    @Override
+    public void close() throws IOException {
+        getChannel().close();
+    }
+
+    @Override
+    public void closeAndDestroy() throws IOException {
+        base.closed = true;
+        close();
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index ceef89ca96..dea881f3c2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -23,10 +23,8 @@
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -35,8 +33,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public abstract class DelegateReadRConnection extends DelegateRConnection {
 
-    private final ByteBuffer tmp = ByteBuffer.allocate(1);
-
     protected DelegateReadRConnection(BaseRConnection base) {
         super(base);
     }
@@ -61,42 +57,6 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
         throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
     }
 
-    @Override
-    public int getc() throws IOException {
-        if (isTextMode()) {
-            return getDecoder().read();
-        } else {
-            tmp.clear();
-            int nread = getChannel().read(tmp);
-            tmp.rewind();
-            return nread > 0 ? tmp.get() : -1;
-        }
-    }
-
-    @Override
-    public String readChar(int nchars, boolean useBytes) throws IOException {
-        if (useBytes) {
-            return DelegateRConnection.readCharHelper(nchars, getChannel());
-        } else {
-            return DelegateRConnection.readCharHelper(nchars, getDecoder());
-        }
-    }
-
-    @Override
-    public int readBin(ByteBuffer buffer) throws IOException {
-        return getChannel().read(buffer);
-    }
-
-    @Override
-    public byte[] readBinChars() throws IOException {
-        return DelegateRConnection.readBinCharsHelper(getChannel());
-    }
-
-    @Override
-    public void flush() {
-        // nothing to do when reading
-    }
-
     @Override
     public OutputStream getOutputStream() {
         throw RInternalError.shouldNotReachHere();
@@ -112,22 +72,6 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
         return false;
     }
 
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return Channels.newInputStream(getChannel());
-    }
-
-    @Override
-    public void close() throws IOException {
-        getChannel().close();
-    }
-
-    @Override
-    public void closeAndDestroy() throws IOException {
-        base.closed = true;
-        close();
-    }
-
     @Override
     public void truncate() {
         throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_ONLY_WRITE_CONNECTION);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index 7154492f4e..f8345bc9ab 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -22,109 +22,12 @@
  */
 package com.oracle.truffle.r.runtime.conn;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 abstract class DelegateReadWriteRConnection extends DelegateRConnection {
 
-    private final ByteBuffer tmp = ByteBuffer.allocate(1);
-
     protected DelegateReadWriteRConnection(BaseRConnection base) {
         super(base);
     }
 
-    @Override
-    public boolean canRead() {
-        return true;
-    }
-
-    @Override
-    public boolean canWrite() {
-        return true;
-    }
-
-    @Override
-    public int getc() throws IOException {
-        if (isTextMode()) {
-            return getDecoder().read();
-        } else {
-            tmp.clear();
-            int nread = getChannel().read(tmp);
-            tmp.rewind();
-            return nread > 0 ? tmp.get() : -1;
-        }
-    }
-
-    @Override
-    public String readChar(int nchars, boolean useBytes) throws IOException {
-        if (useBytes) {
-            return DelegateRConnection.readCharHelper(nchars, getChannel());
-        } else {
-            return DelegateRConnection.readCharHelper(nchars, getDecoder());
-        }
-    }
-
-    @Override
-    public int readBin(ByteBuffer buffer) throws IOException {
-        return getChannel().read(buffer);
-    }
-
-    @Override
-    public byte[] readBinChars() throws IOException {
-        return DelegateRConnection.readBinCharsHelper(getChannel());
-    }
-
-    @Override
-    public void flush() {
-        // nothing to do for channels
-    }
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        return Channels.newOutputStream(getChannel());
-    }
-
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return Channels.newInputStream(getChannel());
-    }
-
-    @Override
-    public void close() throws IOException {
-        getChannel().close();
-    }
-
-    @Override
-    public void closeAndDestroy() throws IOException {
-        base.closed = true;
-        close();
-    }
-
-    @Override
-    public void writeBin(ByteBuffer buffer) throws IOException {
-        getChannel().write(buffer);
-    }
-
-    @Override
-    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        DelegateRConnection.writeCharHelper(getChannel(), s, pad, eos);
-    }
-
-    @Override
-    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
-        base.setIncomplete(incomplete);
-    }
-
-    @Override
-    public void writeString(String s, boolean nl) throws IOException {
-        DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
-    }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 4d4520d88c..7a7b121121 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -24,14 +24,11 @@ package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 abstract class DelegateWriteRConnection extends DelegateRConnection {
 
@@ -60,7 +57,7 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
     }
 
     @Override
-    public int getc() throws IOException {
+    public int read() throws IOException {
         throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
     }
 
@@ -78,48 +75,4 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
     public boolean canWrite() {
         return true;
     }
-
-    @Override
-    public void closeAndDestroy() throws IOException {
-        base.closed = true;
-        close();
-    }
-
-    @Override
-    public void flush() throws IOException {
-        // channels don't need any flushing
-    }
-
-    @Override
-    public void close() throws IOException {
-        flush();
-        getChannel().close();
-    }
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        return Channels.newOutputStream(getChannel());
-    }
-
-    @Override
-    public void writeBin(ByteBuffer buffer) throws IOException {
-        getChannel().write(buffer);
-    }
-
-    @Override
-    public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        DelegateRConnection.writeCharHelper(getChannel(), s, pad, eos);
-    }
-
-    @Override
-    public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
-        base.setIncomplete(incomplete);
-    }
-
-    @Override
-    public void writeString(String s, boolean nl) throws IOException {
-        DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
-    }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index dd879051c3..6c6e7b35fe 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -31,11 +31,8 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.channels.FileChannel;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CharsetEncoder;
 import java.nio.file.OpenOption;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
@@ -347,7 +344,6 @@ public class FileConnections {
     private static class FileReadWriteTextConnection extends DelegateReadWriteRConnection {
 
         private final FileChannel channel;
-        private final CharsetEncoder encoder;
         private long readOffset;
         private long writeOffset;
         private SeekRWMode lastMode = SeekRWMode.READ;
@@ -360,26 +356,18 @@ public class FileConnections {
             opts.add(StandardOpenOption.CREATE);
             opts.add(StandardOpenOption.TRUNCATE_EXISTING);
             channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
-            encoder = base.getEncoding().newEncoder();
         }
 
         @Override
-        public int getc() throws IOException {
+        public int read() throws IOException {
             setReadPosition();
-            int value = super.getc();
+            final int value = super.read();
             if (value != -1) {
-                readOffset += getNumBytes(value);
+                readOffset++;
             }
             return value;
         }
 
-        private long getNumBytes(int value) throws CharacterCodingException {
-            // TODO We need to get the information about how much bytes have been consumed from the
-            // stream decoder. This is really bad!
-            ByteBuffer encode = encoder.encode(CharBuffer.wrap(new char[]{(char) value}));
-            return encode.position();
-        }
-
         @Override
         public boolean isSeekable() {
             return true;
@@ -392,6 +380,7 @@ public class FileConnections {
             switch (seekMode) {
                 case ENQUIRE:
                     set = false;
+                    break;
                 case START:
                     break;
                 default:
@@ -456,9 +445,6 @@ public class FileConnections {
             if (lastMode != SeekRWMode.READ) {
                 channel.position(readOffset);
                 lastMode = SeekRWMode.READ;
-
-                // re-initialize stream decoder if position changed
-                initDecoder(1);
             }
         }
 
@@ -504,9 +490,9 @@ public class FileConnections {
         }
 
         @Override
-        public int getc() throws IOException {
+        public int read() throws IOException {
             setReadPosition();
-            int value = super.getc();
+            final int value = raf.read();
             if (value != -1) {
                 readOffset++;
             }
@@ -575,9 +561,6 @@ public class FileConnections {
             if (lastMode != SeekRWMode.READ) {
                 raf.seek(readOffset);
                 lastMode = SeekRWMode.READ;
-
-                // re-initialize stream decoder if position changed
-                initDecoder(1);
             }
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index e6a345e5a6..4ea9d1edf8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -139,9 +139,9 @@ public interface RConnection extends AutoCloseable {
     long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException;
 
     /**
-     * Internal support for reading one character at a time.
+     * Internal support for reading one byte at a time.
      */
-    int getc() throws IOException;
+    int read() throws IOException;
 
     /**
      * Write the {@code lines} to the connection, with {@code sep} appended after each "line". N.B.
@@ -167,7 +167,7 @@ public interface RConnection extends AutoCloseable {
      * @param s string to output
      * @param pad number of (zero) pad bytes
      * @param eos string to append to s
-     * @param useBytes TODO
+     * @param useBytes
      */
     void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 6150dc902b..648995d525 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -215,7 +215,7 @@ public class StdConnections {
         }
 
         @Override
-        public int getc() throws IOException {
+        public int read() throws IOException {
             throw RInternalError.unimplemented("stdin getc");
         }
     }
@@ -240,7 +240,7 @@ public class StdConnections {
         }
 
         @Override
-        public int getc() throws IOException {
+        public int read() throws IOException {
             throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
         }
     }
-- 
GitLab


From bf0abd328a061d91ba0ed0e1788da5f6fa8c750d Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 3 Mar 2017 10:29:21 +0100
Subject: [PATCH 102/402] Fixed infinite loop bug in function 'readBin' when
 reading non-terminated strings from file. Also added unit tests for this bug.

---
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../r/runtime/conn/DelegateRConnection.java   | 45 +++++++++----------
 .../truffle/r/test/ExpectedTestOutput.test    | 11 +++++
 .../r/test/library/base/TestConnections.java  |  7 ++-
 4 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index c7757fbb17..b2812914ee 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -845,7 +845,8 @@ public final class RError extends RuntimeException {
         TRUNCATE_ONLY_WRITE_CONNECTION("can only truncate connections open for writing"),
         TRUNCATE_ONLY_OPEN_CONN("can only truncate an open connection"),
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
-        TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s");
+        TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"),
+        INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 1d6159c545..a8dc28fede 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -245,29 +245,6 @@ abstract class DelegateRConnection implements RConnection {
         channel.write(buf);
     }
 
-    /**
-     * Reads null-terminated character strings from a {@link ReadableByteChannel}.
-     */
-    public static byte[] readBinCharsHelper(ReadableByteChannel channel) throws IOException {
-        ByteBuffer buf = ByteBuffer.allocate(1);
-        int numRead = channel.read(buf);
-        if (numRead <= 0) {
-            return null;
-        }
-        int totalRead = 0;
-        byte[] buffer = new byte[64];
-        while (true) {
-            buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
-            buffer[totalRead++] = (byte) (buf.get() & 0xFF);
-            if (numRead == 0) {
-                break;
-            }
-            buf.clear();
-            numRead = channel.read(buf);
-        }
-        return buffer;
-    }
-
     /**
      * Reads a specified amount of characters.
      *
@@ -458,9 +435,29 @@ abstract class DelegateRConnection implements RConnection {
         return getChannel().read(buffer);
     }
 
+    /**
+     * Reads null-terminated character strings from a {@link ReadableByteChannel}.
+     */
     @Override
     public byte[] readBinChars() throws IOException {
-        return DelegateRConnection.readBinCharsHelper(getChannel());
+        int numRead = read();
+        if (numRead <= 0) {
+            return null;
+        }
+        int totalRead = 0;
+        byte[] buffer = new byte[64];
+        while (true) {
+            buffer = DelegateRConnection.checkBuffer(buffer, totalRead);
+            buffer[totalRead++] = (byte) numRead;
+            if (numRead == 0) {
+                break;
+            } else if (numRead == -1) {
+                RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_STRING_AT_EOF_DISCARDED);
+                return null;
+            }
+            numRead = read();
+        }
+        return buffer;
     }
 
     @Override
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 cdc9c7e314..319431438d 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
@@ -73348,6 +73348,13 @@ $`can write`
 [1] "no"
 
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin#
+#{ cat('abc', file = 'tmptest/com.oracle.truffle.r.test.library.base.conn/wb3'); readBin(file('tmptest/com.oracle.truffle.r.test.library.base.conn/wb3', 'rb'), character(), 2) }
+character(0)
+Warning message:
+In readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb3",  :
+  incomplete string at end of file has been discarded
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin#
 #{ readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", "rb"), 3) }
 numeric(0)
@@ -73355,6 +73362,10 @@ numeric(0)
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin#
 #{ writeBin("abc", file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb1", open="wb")) }
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadBin#
+#{ zz <- file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb2", open="wb"); writeChar("abc", zz); close(zz); readBin(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wb2", "rb"), character(), 4) }
+[1] "abc"
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileWriteReadChar#
 #{ readChar(file("tmptest/com.oracle.truffle.r.test.library.base.conn/wc1"), 3) }
 [1] "abc"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 058b6cb3fc..d2dabca9b2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -93,10 +93,15 @@ public class TestConnections extends TestRBase {
         assertEval(TestBase.template("{ readChar(file(\"%0\"), 3) }", testDir.subDir("wc1")));
     }
 
-    @Test
+    @Test(timeout = 1000)
     public void testFileWriteReadBin() {
         assertEval(TestBase.template("{ writeBin(\"abc\", file(\"%0\", open=\"wb\")) }", testDir.subDir("wb1")));
         assertEval(TestBase.template("{ readBin(file(\"%0\", \"rb\"), 3) }", testDir.subDir("wb1")));
+
+        assertEval(TestBase.template("{ zz <- file(\"%0\", open=\"wb\"); writeChar(\"abc\", zz); close(zz); readBin(file(\"%0\", \"rb\"), character(), 4) }", testDir.subDir("wb2")));
+
+        // incomplete line at the end of file
+        assertEval(TestBase.template("{ cat('abc', file = '%0'); readBin(file('%0', 'rb'), character(), 2) }", testDir.subDir("wb3")));
     }
 
     @Test
-- 
GitLab


From a449d0072bfba2dbd32a67605df7c96eff0bc735 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 3 Mar 2017 16:09:52 +0100
Subject: [PATCH 103/402] Introduced caches for connections which tremendously
 speeds up little read operations and read operations on compressed files.
 However, there is still a problem with Snowfall.

---
 .../r/runtime/conn/ConnectionSupport.java     |   2 +-
 .../r/runtime/conn/DelegateRConnection.java   | 110 +++++++++++++++---
 .../r/runtime/conn/FileConnections.java       |  63 +++++++++-
 3 files changed, 149 insertions(+), 26 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 3ff5c7dff1..4ad5ac898a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -765,7 +765,7 @@ public class ConnectionSupport {
         @Override
         public ByteChannel getChannel() throws IOException {
             checkOpen();
-            return theConnection.getChannel();
+            return theConnection;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index a8dc28fede..15a6702692 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
 import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
 import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.channels.SeekableByteChannel;
@@ -55,12 +56,16 @@ import sun.nio.cs.StreamDecoder;
  * operations.
  * </p>
  */
-abstract class DelegateRConnection implements RConnection {
+abstract class DelegateRConnection implements RConnection, ByteChannel {
+    private static final int DEFAULT_CACHE_SIZE = 64 * 1024;
     protected final BaseRConnection base;
-    final ByteBuffer tmp = ByteBuffer.allocate(1);
+    private final ByteBuffer cache;
 
     DelegateRConnection(BaseRConnection base) {
         this.base = Objects.requireNonNull(base);
+        cache = ByteBuffer.allocate(DEFAULT_CACHE_SIZE);
+        // indicate that there are no remaining bytes in the buffer
+        cache.flip();
     }
 
     @Override
@@ -104,6 +109,7 @@ abstract class DelegateRConnection implements RConnection {
         base.setIncomplete(false);
         ArrayList<String> lines = new ArrayList<>();
         int totalRead = 0;
+        int nBytesConsumed = 0;
         byte[] buffer = new byte[64];
         int pushBack = 0;
         boolean nullRead = false;
@@ -113,7 +119,7 @@ abstract class DelegateRConnection implements RConnection {
                 ch = pushBack;
                 pushBack = 0;
             } else {
-                ch = read();
+                ch = readInternal();
             }
             boolean lineEnd = false;
             if (ch < 0) {
@@ -123,6 +129,7 @@ abstract class DelegateRConnection implements RConnection {
                      * lines, otherwise keep data and output warning.
                      */
                     final String incompleteFinalLine = new String(buffer, 0, totalRead, base.getEncoding());
+                    nBytesConsumed += totalRead;
                     if (!base.isBlocking() && base.isTextMode()) {
                         base.pushBack(RDataFactory.createStringVector(incompleteFinalLine), false);
                         base.setIncomplete(true);
@@ -139,7 +146,7 @@ abstract class DelegateRConnection implements RConnection {
                 lineEnd = true;
             } else if (ch == '\r') {
                 lineEnd = true;
-                ch = read();
+                ch = readInternal();
                 if (ch == '\n') {
                     // swallow the trailing lf
                 } else {
@@ -153,6 +160,7 @@ abstract class DelegateRConnection implements RConnection {
             }
             if (lineEnd) {
                 lines.add(new String(buffer, 0, totalRead, base.getEncoding()));
+                nBytesConsumed += totalRead;
                 if (n > 0 && lines.size() == n) {
                     break;
                 }
@@ -170,13 +178,27 @@ abstract class DelegateRConnection implements RConnection {
         }
         String[] result = new String[lines.size()];
         lines.toArray(result);
+        updateReadOffset(nBytesConsumed);
         return result;
     }
 
+    /**
+     * Updates the read cursor.<br>
+     * <p>
+     * Called by methods using {@link #readInternal()} to tell how many bytes have been consumed to
+     * be able to update a read curosor if available.
+     * </p>
+     *
+     * @param nBytesConsumed Number of bytes consumed by a read operation.
+     */
+    protected void updateReadOffset(int nBytesConsumed) {
+        // default: nothing to do
+    }
+
     @Override
     public String readChar(int nchars, boolean useBytes) throws IOException {
         if (useBytes) {
-            return DelegateRConnection.readCharHelper(nchars, getChannel());
+            return DelegateRConnection.readCharHelper(nchars, this);
         } else {
             return DelegateRConnection.readCharHelper(nchars, getDecoder(nchars));
         }
@@ -390,7 +412,7 @@ abstract class DelegateRConnection implements RConnection {
      */
     protected StreamDecoder getDecoder(int bufSize) throws IOException {
         CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
-        return StreamDecoder.forDecoder(getChannel(), charsetEncoder, bufSize);
+        return StreamDecoder.forDecoder(this, charsetEncoder, bufSize);
     }
 
     @Override
@@ -403,36 +425,86 @@ abstract class DelegateRConnection implements RConnection {
 
     @Override
     public void writeBin(ByteBuffer buffer) throws IOException {
-        getChannel().write(buffer);
+        write(buffer);
     }
 
     @Override
     public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
-        DelegateRConnection.writeCharHelper(getChannel(), s, pad, eos);
+        DelegateRConnection.writeCharHelper(this, s, pad, eos);
     }
 
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
-        boolean incomplete = DelegateRConnection.writeLinesHelper(getChannel(), lines, sep, base.getEncoding());
+        boolean incomplete = DelegateRConnection.writeLinesHelper(this, lines, sep, base.getEncoding());
         base.setIncomplete(incomplete);
     }
 
     @Override
     public void writeString(String s, boolean nl) throws IOException {
-        DelegateRConnection.writeStringHelper(getChannel(), s, nl, base.getEncoding());
+        DelegateRConnection.writeStringHelper(this, s, nl, base.getEncoding());
+    }
+
+    @Override
+    public int read(ByteBuffer dst) throws IOException {
+        final int bytesRequested = dst.remaining();
+        int totalBytesRead = 0;
+        int bytesToRead = 0;
+        do {
+            ensureDataAvailable(dst.remaining());
+            bytesToRead = Math.min(cache.remaining(), dst.remaining());
+            cache.get(dst.array(), dst.position(), bytesToRead);
+            dst.position(dst.position() + bytesToRead);
+            totalBytesRead += bytesToRead;
+        } while (totalBytesRead < bytesRequested && bytesToRead > 0);
+        return totalBytesRead;
+    }
+
+    @Override
+    public int write(ByteBuffer src) throws IOException {
+        return getChannel().write(src);
+    }
+
+    /**
+     * Reads one byte from the channel.<br>
+     * <p>
+     * Should basically do the same job as {@link #read()} but is only used by internally by this
+     * class or subclasses an may therefore produce an inconsistent state over several calls. For
+     * example, updating the channel's cursor position can be collapsed.
+     * </p>
+     */
+    protected int readInternal() throws IOException {
+        ensureDataAvailable(1L);
+        if (!cache.hasRemaining()) {
+            return -1;
+        }
+        // consider byte to be unsigned
+        return cache.get() & 0xFF;
+    }
+
+    private void ensureDataAvailable(long i) throws IOException {
+        if (cache.remaining() < i) {
+            byte[] rem = new byte[cache.remaining()];
+            cache.get(rem);
+            assert !cache.hasRemaining();
+            cache.clear();
+            cache.put(rem);
+            getChannel().read(cache);
+            cache.flip();
+        }
+    }
+
+    protected void invalidateCache() {
+        cache.clear();
     }
 
     @Override
     public int read() throws IOException {
-        tmp.clear();
-        int nread = getChannel().read(tmp);
-        tmp.rewind();
-        return nread > 0 ? tmp.get() & 0xFF : -1;
+        return readInternal();
     }
 
     @Override
     public int readBin(ByteBuffer buffer) throws IOException {
-        return getChannel().read(buffer);
+        return read(buffer);
     }
 
     /**
@@ -440,7 +512,7 @@ abstract class DelegateRConnection implements RConnection {
      */
     @Override
     public byte[] readBinChars() throws IOException {
-        int numRead = read();
+        int numRead = readInternal();
         if (numRead <= 0) {
             return null;
         }
@@ -455,7 +527,7 @@ abstract class DelegateRConnection implements RConnection {
                 RError.warning(RError.SHOW_CALLER, RError.Message.INCOMPLETE_STRING_AT_EOF_DISCARDED);
                 return null;
             }
-            numRead = read();
+            numRead = readInternal();
         }
         return buffer;
     }
@@ -477,12 +549,12 @@ abstract class DelegateRConnection implements RConnection {
 
     @Override
     public OutputStream getOutputStream() throws IOException {
-        return Channels.newOutputStream(getChannel());
+        return Channels.newOutputStream(this);
     }
 
     @Override
     public InputStream getInputStream() throws IOException {
-        return Channels.newInputStream(getChannel());
+        return Channels.newInputStream(this);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 6c6e7b35fe..eaad787c2b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -139,12 +139,14 @@ public class FileConnections {
                 delegate = new FileWriteBinaryConnection(base, false);
                 break;
             case ReadWriteTrunc:
-                delegate = new FileReadWriteTextConnection(base);
+                delegate = new FileReadWriteTextConnection(base, false);
                 break;
             case ReadWriteTruncBinary:
                 delegate = new FileReadWriteBinaryConnection(base, false);
                 break;
             case ReadAppend:
+                delegate = new FileReadWriteTextConnection(base, true);
+                break;
             case ReadAppendBinary:
                 delegate = new FileReadWriteBinaryConnection(base, true);
                 break;
@@ -316,7 +318,6 @@ public class FileConnections {
                 opts.add(StandardOpenOption.TRUNCATE_EXISTING);
             }
             channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
-
         }
 
         @Override
@@ -336,7 +337,7 @@ public class FileConnections {
 
         @Override
         public void truncate() throws IOException {
-            channel.truncate(0);
+            channel.truncate(channel.position());
         }
 
     }
@@ -348,26 +349,35 @@ public class FileConnections {
         private long writeOffset;
         private SeekRWMode lastMode = SeekRWMode.READ;
 
-        FileReadWriteTextConnection(BasePathRConnection base) throws IOException {
+        FileReadWriteTextConnection(BasePathRConnection base, boolean append) throws IOException {
             super(base);
             List<OpenOption> opts = new ArrayList<>();
             opts.add(StandardOpenOption.READ);
             opts.add(StandardOpenOption.WRITE);
             opts.add(StandardOpenOption.CREATE);
-            opts.add(StandardOpenOption.TRUNCATE_EXISTING);
             channel = FileChannel.open(Paths.get(base.path), opts.toArray(new OpenOption[opts.size()]));
+            if (append) {
+                writeOffset = channel.size();
+            } else {
+                channel.truncate(0);
+            }
         }
 
         @Override
         public int read() throws IOException {
             setReadPosition();
-            final int value = super.read();
+            final int value = super.readInternal();
             if (value != -1) {
                 readOffset++;
             }
             return value;
         }
 
+        @Override
+        protected void updateReadOffset(int nBytesConsumed) {
+            readOffset += nBytesConsumed;
+        }
+
         @Override
         public boolean isSeekable() {
             return true;
@@ -424,6 +434,24 @@ public class FileConnections {
             return super.readLines(n, warn, skipNul);
         }
 
+        @Override
+        public int readBin(ByteBuffer buffer) throws IOException {
+            setReadPosition();
+            return super.readBin(buffer);
+        }
+
+        @Override
+        public String readChar(int nchars, boolean useBytes) throws IOException {
+            setReadPosition();
+            return super.readChar(nchars, useBytes);
+        }
+
+        @Override
+        public byte[] readBinChars() throws IOException {
+            setReadPosition();
+            return super.readBinChars();
+        }
+
         @Override
         public void close() throws IOException {
             channel.close();
@@ -436,6 +464,24 @@ public class FileConnections {
             writeOffset = channel.position();
         }
 
+        @Override
+        public void writeBin(ByteBuffer buffer) throws IOException {
+            setWritePosition();
+            super.writeBin(buffer);
+        }
+
+        @Override
+        public void writeChar(String s, int pad, String eos, boolean useBytes) throws IOException {
+            setWritePosition();
+            super.writeChar(s, pad, eos, useBytes);
+        }
+
+        @Override
+        public void writeString(String s, boolean nl) throws IOException {
+            setWritePosition();
+            super.writeString(s, nl);
+        }
+
         @Override
         public ByteChannel getChannel() {
             return channel;
@@ -499,6 +545,11 @@ public class FileConnections {
             return value;
         }
 
+        @Override
+        protected void updateReadOffset(int nBytesConsumed) {
+            readOffset += nBytesConsumed;
+        }
+
         @Override
         public boolean isSeekable() {
             return true;
-- 
GitLab


From 47cbb1a234347546afad536f289185c384068aa6 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 3 Mar 2017 17:22:51 +0100
Subject: [PATCH 104/402] Reduced buffer size and tried to find reason for
 segfault. Also added cache invalidation calls when seeking.

---
 .../r/runtime/conn/DelegateRConnection.java   | 24 ++++++++++++++-----
 .../r/runtime/conn/FileConnections.java       |  8 +++++++
 .../r/runtime/conn/RawConnections.java        |  1 +
 3 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 15a6702692..dd7ae17bdc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -57,7 +57,7 @@ import sun.nio.cs.StreamDecoder;
  * </p>
  */
 abstract class DelegateRConnection implements RConnection, ByteChannel {
-    private static final int DEFAULT_CACHE_SIZE = 64 * 1024;
+    private static final int DEFAULT_CACHE_SIZE = 16 * 1024;
     protected final BaseRConnection base;
     private final ByteBuffer cache;
 
@@ -449,14 +449,16 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
         final int bytesRequested = dst.remaining();
         int totalBytesRead = 0;
         int bytesToRead = 0;
+        boolean eof;
         do {
-            ensureDataAvailable(dst.remaining());
+            eof = ensureDataAvailable(dst.remaining());
             bytesToRead = Math.min(cache.remaining(), dst.remaining());
             cache.get(dst.array(), dst.position(), bytesToRead);
             dst.position(dst.position() + bytesToRead);
             totalBytesRead += bytesToRead;
         } while (totalBytesRead < bytesRequested && bytesToRead > 0);
-        return totalBytesRead;
+        return totalBytesRead == 0 && eof ? -1 : totalBytesRead;
+// return getChannel().read(dst);
     }
 
     @Override
@@ -473,24 +475,34 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
      * </p>
      */
     protected int readInternal() throws IOException {
-        ensureDataAvailable(1L);
+        ensureDataAvailable(1);
         if (!cache.hasRemaining()) {
             return -1;
         }
         // consider byte to be unsigned
         return cache.get() & 0xFF;
+
+// ByteBuffer buf = ByteBuffer.allocate(1);
+// int n = getChannel().read(buf);
+// if (n <= 0) {
+// return -1;
+// }
+// buf.flip();
+// return buf.get() & 0xFF;
     }
 
-    private void ensureDataAvailable(long i) throws IOException {
+    private boolean ensureDataAvailable(int i) throws IOException {
         if (cache.remaining() < i) {
             byte[] rem = new byte[cache.remaining()];
             cache.get(rem);
             assert !cache.hasRemaining();
             cache.clear();
             cache.put(rem);
-            getChannel().read(cache);
+            int read = getChannel().read(cache);
             cache.flip();
+            return read == -1;
         }
+        return false;
     }
 
     protected void invalidateCache() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index eaad787c2b..17b001d6d1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -267,6 +267,12 @@ public class FileConnections {
             return true;
         }
 
+        @Override
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            invalidateCache();
+            return DelegateRConnection.seek(channel, offset, seekMode, seekRWMode);
+        }
+
         @Override
         public ByteChannel getChannel() {
             return channel;
@@ -425,6 +431,7 @@ public class FileConnections {
                 default:
                     throw RError.nyi(RError.SHOW_CALLER, "seek mode");
             }
+            invalidateCache();
             return result;
         }
 
@@ -581,6 +588,7 @@ public class FileConnections {
                     writeOffset = offset;
                     break;
             }
+            invalidateCache();
             return result;
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 35b504eead..8a0bf52762 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -217,6 +217,7 @@ public class RawConnections {
 
         @Override
         public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            invalidateCache();
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
-- 
GitLab


From 63643f1f7bacf1e341401bed6fc6c50dc57aa05e Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 6 Mar 2017 14:35:50 +0100
Subject: [PATCH 105/402] Fixed SEGFAULT bug when running TestAppsSnowfall with
 package installation. - The reason was the renaming of emthod 'getc' to
 'read'. The method is called (by name) from native code. Implemented option
 to disable the cache (by setting its size to 0).  This is required for socket
 connections in order to not block the whole application. Introduced method
 'seekInternal' to be able to call 'invalidateCache' on seeking in base class.

---
 .../com/oracle/truffle/r/runtime/RError.java  |   2 +-
 .../r/runtime/conn/ConnectionSupport.java     |   6 +-
 .../r/runtime/conn/DelegateRConnection.java   | 103 ++++++++++++------
 .../runtime/conn/DelegateReadRConnection.java |   4 +
 .../conn/DelegateReadWriteRConnection.java    |   4 +
 .../conn/DelegateWriteRConnection.java        |   4 +-
 .../r/runtime/conn/FileConnections.java       |  17 ++-
 .../truffle/r/runtime/conn/RConnection.java   |   7 +-
 .../r/runtime/conn/RawConnections.java        |  11 +-
 .../r/runtime/conn/SocketConnections.java     |   4 +-
 .../r/runtime/conn/StdConnections.java        |   4 +-
 .../r/runtime/conn/TextConnections.java       |   4 +-
 .../r/test/library/base/TestConnections.java  |   2 +-
 13 files changed, 106 insertions(+), 66 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index b2812914ee..8a7f66a247 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -841,7 +841,7 @@ public final class RError extends RuntimeException {
         UNABLE_TO_RESOLVE("unable to resolve '%s'"),
         LINE_CONTAINS_EMBEDDED_NULLS("line %d appears to contain an embedded nul"),
         UNSUPPORTED_URL_METHOD("method = \"%s\" is not supported"),
-        CANNOT_REPLICATE_NULL("cannot replicate NULL to a non-zero length");
+        CANNOT_REPLICATE_NULL("cannot replicate NULL to a non-zero length"),
         TRUNCATE_ONLY_WRITE_CONNECTION("can only truncate connections open for writing"),
         TRUNCATE_ONLY_OPEN_CONN("can only truncate an open connection"),
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 4ad5ac898a..c0c2e5bf8e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -409,7 +409,7 @@ public class ConnectionSupport {
         }
 
         @Override
-        public int read() throws IOException {
+        public int getc() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
@@ -839,9 +839,9 @@ public class ConnectionSupport {
         }
 
         @Override
-        public int read() throws IOException {
+        public int getc() throws IOException {
             checkOpen();
-            return theConnection.read();
+            return theConnection.getc();
         }
 
         public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index dd7ae17bdc..e31aaa0bd5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -62,10 +62,19 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     private final ByteBuffer cache;
 
     DelegateRConnection(BaseRConnection base) {
+        this(base, DEFAULT_CACHE_SIZE);
+    }
+
+    DelegateRConnection(BaseRConnection base, int cacheSize) {
         this.base = Objects.requireNonNull(base);
-        cache = ByteBuffer.allocate(DEFAULT_CACHE_SIZE);
-        // indicate that there are no remaining bytes in the buffer
-        cache.flip();
+
+        if (cacheSize > 0) {
+            cache = ByteBuffer.allocate(cacheSize);
+            // indicate that there are no remaining bytes in the buffer
+            cache.flip();
+        } else {
+            cache = null;
+        }
     }
 
     @Override
@@ -88,12 +97,19 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
         return base.forceOpen(modeString);
     }
 
+    @SuppressWarnings("unused")
+    protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        throw RInternalError.shouldNotReachHere("seek has not been implemented for this connection");
+    }
+
     @Override
-    public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+    public final long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
         if (!isSeekable()) {
             throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_ENABLED_FOR_THIS_CONN, "seek");
         }
-        throw RInternalError.shouldNotReachHere("seek has not been implemented for this connection");
+        final long res = seekInternal(offset, seekMode, seekRWMode);
+        invalidateCache();
+        return res;
     }
 
     /**
@@ -410,7 +426,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     /**
      * Creates the stream decoder on demand and returns it.
      */
-    protected StreamDecoder getDecoder(int bufSize) throws IOException {
+    protected StreamDecoder getDecoder(int bufSize) {
         CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
         return StreamDecoder.forDecoder(this, charsetEncoder, bufSize);
     }
@@ -446,19 +462,22 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
 
     @Override
     public int read(ByteBuffer dst) throws IOException {
-        final int bytesRequested = dst.remaining();
-        int totalBytesRead = 0;
-        int bytesToRead = 0;
-        boolean eof;
-        do {
-            eof = ensureDataAvailable(dst.remaining());
-            bytesToRead = Math.min(cache.remaining(), dst.remaining());
-            cache.get(dst.array(), dst.position(), bytesToRead);
-            dst.position(dst.position() + bytesToRead);
-            totalBytesRead += bytesToRead;
-        } while (totalBytesRead < bytesRequested && bytesToRead > 0);
-        return totalBytesRead == 0 && eof ? -1 : totalBytesRead;
-// return getChannel().read(dst);
+        if (cache != null) {
+            final int bytesRequested = dst.remaining();
+            int totalBytesRead = 0;
+            int bytesToRead = 0;
+            boolean eof;
+            do {
+                eof = ensureDataAvailable(dst.remaining());
+                bytesToRead = Math.min(cache.remaining(), dst.remaining());
+                cache.get(dst.array(), dst.position(), bytesToRead);
+                dst.position(dst.position() + bytesToRead);
+                totalBytesRead += bytesToRead;
+            } while (totalBytesRead < bytesRequested && bytesToRead > 0 && !eof);
+            return totalBytesRead == 0 && eof ? -1 : totalBytesRead;
+        } else {
+            return getChannel().read(dst);
+        }
     }
 
     @Override
@@ -469,29 +488,33 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     /**
      * Reads one byte from the channel.<br>
      * <p>
-     * Should basically do the same job as {@link #read()} but is only used by internally by this
+     * Should basically do the same job as {@link #getc()} but is only used by internally by this
      * class or subclasses an may therefore produce an inconsistent state over several calls. For
      * example, updating the channel's cursor position can be collapsed.
      * </p>
      */
     protected int readInternal() throws IOException {
-        ensureDataAvailable(1);
-        if (!cache.hasRemaining()) {
-            return -1;
-        }
-        // consider byte to be unsigned
-        return cache.get() & 0xFF;
+        if (cache != null) {
+            ensureDataAvailable(1);
+            if (!cache.hasRemaining()) {
+                return -1;
+            }
+            // consider byte to be unsigned
+            return cache.get() & 0xFF;
+        } else {
 
-// ByteBuffer buf = ByteBuffer.allocate(1);
-// int n = getChannel().read(buf);
-// if (n <= 0) {
-// return -1;
-// }
-// buf.flip();
-// return buf.get() & 0xFF;
+            ByteBuffer buf = ByteBuffer.allocate(1);
+            int n = getChannel().read(buf);
+            if (n <= 0) {
+                return -1;
+            }
+            buf.flip();
+            return buf.get() & 0xFF;
+        }
     }
 
     private boolean ensureDataAvailable(int i) throws IOException {
+        assert cache != null;
         if (cache.remaining() < i) {
             byte[] rem = new byte[cache.remaining()];
             cache.get(rem);
@@ -505,12 +528,22 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
         return false;
     }
 
+    /**
+     * Invalidates the read cache by dropping cached data.<br>
+     * <p>
+     * This method is most useful if an operation like {@code seek} is performed that destroys the
+     * order data is read.
+     * </p>
+     */
     protected void invalidateCache() {
-        cache.clear();
+        if (cache != null) {
+            cache.clear();
+            cache.flip();
+        }
     }
 
     @Override
-    public int read() throws IOException {
+    public int getc() throws IOException {
         return readInternal();
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index dea881f3c2..d4b11c2d57 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -37,6 +37,10 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
         super(base);
     }
 
+    protected DelegateReadRConnection(BaseRConnection base, int cacheSize) {
+        super(base, cacheSize);
+    }
+
     @Override
     public void writeLines(RAbstractStringVector lines, String sep, boolean useBytes) throws IOException {
         throw new IOException(RError.Message.CANNOT_WRITE_CONNECTION.message);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index f8345bc9ab..c445251b02 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -30,4 +30,8 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
         super(base);
     }
 
+    protected DelegateReadWriteRConnection(BaseRConnection base, int cacheSize) {
+        super(base, cacheSize);
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 7a7b121121..16503501a0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 abstract class DelegateWriteRConnection extends DelegateRConnection {
 
     protected DelegateWriteRConnection(BaseRConnection base) {
-        super(base);
+        super(base, 0);
     }
 
     @Override
@@ -57,7 +57,7 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
     }
 
     @Override
-    public int read() throws IOException {
+    public int getc() throws IOException {
         throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 17b001d6d1..1f009cd7a9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -268,8 +268,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            invalidateCache();
+        public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return DelegateRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
@@ -332,7 +331,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return DelegateRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
@@ -370,7 +369,7 @@ public class FileConnections {
         }
 
         @Override
-        public int read() throws IOException {
+        public int getc() throws IOException {
             setReadPosition();
             final int value = super.readInternal();
             if (value != -1) {
@@ -390,7 +389,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             long result;
             boolean set = true;
             switch (seekMode) {
@@ -431,7 +430,6 @@ public class FileConnections {
                 default:
                     throw RError.nyi(RError.SHOW_CALLER, "seek mode");
             }
-            invalidateCache();
             return result;
         }
 
@@ -543,7 +541,7 @@ public class FileConnections {
         }
 
         @Override
-        public int read() throws IOException {
+        public int getc() throws IOException {
             setReadPosition();
             final int value = raf.read();
             if (value != -1) {
@@ -563,7 +561,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             long result = raf.getFilePointer();
             switch (seekMode) {
                 case ENQUIRE:
@@ -588,7 +586,6 @@ public class FileConnections {
                     writeOffset = offset;
                     break;
             }
-            invalidateCache();
             return result;
         }
 
@@ -719,7 +716,7 @@ public class FileConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             if (seekable) {
                 // TODO GZIP is basically seekable; however, the output stream does not allow any
                 // seeking
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 4ea9d1edf8..1314faf885 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -139,9 +139,12 @@ public interface RConnection extends AutoCloseable {
     long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException;
 
     /**
-     * Internal support for reading one byte at a time.
+     * Internal support for reading one byte at a time.<br>
+     * <p>
+     * <b>NOTE:</b> This method is also used from native code. Do not change the signature!
+     * </p>
      */
-    int read() throws IOException;
+    int getc() throws IOException;
 
     /**
      * Write the {@code lines} to the connection, with {@code sep} appended after each "line". N.B.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 8a0bf52762..3abb2e1bca 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -118,7 +118,7 @@ public class RawConnections {
         private SeekableMemoryByteChannel channel;
 
         RawReadRConnection(BaseRConnection base, SeekableMemoryByteChannel channel) {
-            super(base);
+            super(base, 0);
             this.channel = channel;
             try {
                 channel.position(0L);
@@ -148,7 +148,7 @@ public class RawConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
@@ -179,7 +179,7 @@ public class RawConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
@@ -204,7 +204,7 @@ public class RawConnections {
         private final SeekableMemoryByteChannel channel;
 
         protected RawReadWriteConnection(BaseRConnection base, SeekableMemoryByteChannel channel, boolean append) {
-            super(base);
+            super(base, 0);
             this.channel = channel;
             if (append) {
                 try {
@@ -216,8 +216,7 @@ public class RawConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            invalidateCache();
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             return RawRConnection.seek(channel, offset, seekMode, seekRWMode);
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index 2f978e6fa9..a4ea565e9e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -82,7 +82,7 @@ public class SocketConnections {
         protected final RSocketConnection thisBase;
 
         protected RSocketReadWriteConnection(RSocketConnection base) {
-            super(base);
+            super(base, 0);
             this.thisBase = base;
         }
 
@@ -118,7 +118,7 @@ public class SocketConnections {
         private SocketChannel socketChannel;
 
         protected RSocketReadWriteNonBlockConnection(RSocketConnection base) {
-            super(base);
+            super(base, 0);
         }
 
         protected void openStreams(Socket socketArg) throws IOException {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 648995d525..6150dc902b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -215,7 +215,7 @@ public class StdConnections {
         }
 
         @Override
-        public int read() throws IOException {
+        public int getc() throws IOException {
             throw RInternalError.unimplemented("stdin getc");
         }
     }
@@ -240,7 +240,7 @@ public class StdConnections {
         }
 
         @Override
-        public int read() throws IOException {
+        public int getc() throws IOException {
             throw new IOException(RError.Message.CANNOT_READ_CONNECTION.message);
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index e789830946..b1e4629053 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -92,7 +92,7 @@ public class TextConnections {
         private int index;
 
         TextReadRConnection(TextRConnection base, RAbstractStringVector object) {
-            super(base);
+            super(base, 0);
             assert object != null;
             StringBuffer sb = new StringBuffer();
             for (int i = 0; i < object.getLength(); i++) {
@@ -314,7 +314,7 @@ public class TextConnections {
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             throw RError.error(RError.SHOW_CALLER, RError.Message.SEEK_NOT_RELEVANT_FOR_TEXT_CON);
         }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index d2dabca9b2..2f34c08b2f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -242,7 +242,7 @@ public class TestConnections extends TestRBase {
     @Test
     public void testFifoOpenInexisting() {
         assertEval("capabilities(\"fifo\")");
-        assertEval(Output.IgnoreErrorContext, Output.IgnoreWarningContext, "{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }");
+        assertEval("{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }");
     }
 
     public void testTruncate() {
-- 
GitLab


From 783d73b981dc2a829ae0a160544ef772ec8429c7 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 3 Mar 2017 16:31:37 -0800
Subject: [PATCH 106/402] [GR-2997] Fix cast pipeline issues

---
 .../r/nodes/builtin/base/AsCharacter.java     | 16 ++--
 .../r/nodes/builtin/base/AsComplex.java       | 15 ++--
 .../r/nodes/builtin/base/AsDouble.java        | 15 ++--
 .../r/nodes/builtin/base/AsInteger.java       | 15 ++--
 .../r/nodes/builtin/base/AsLogical.java       | 15 ++--
 .../truffle/r/nodes/builtin/base/AsRaw.java   |  4 +-
 .../truffle/r/nodes/builtin/base/Bincode.java | 23 +++++-
 .../nodes/builtin/base/BitwiseFunctions.java  |  8 +-
 .../builtin/base/DatePOSIXFunctions.java      |  4 +-
 .../r/nodes/builtin/base/GrepFunctions.java   |  6 +-
 .../r/nodes/builtin/base/UpdateClass.java     | 10 ++-
 .../builtin/base/infix/BreakBuiltin.java      |  4 +
 .../truffle/r/test/ExpectedTestOutput.test    | 82 ++++++++++++++++++-
 .../test/builtins/TestBuiltin_asPOSIXlt.java  |  9 +-
 .../builtins/TestBuiltin_ascharacter.java     |  1 +
 .../test/builtins/TestBuiltin_ascomplex.java  |  3 +-
 .../r/test/builtins/TestBuiltin_asdouble.java |  3 +-
 .../test/builtins/TestBuiltin_asinteger.java  |  3 +-
 .../r/test/builtins/TestBuiltin_asraw.java    |  1 +
 .../r/test/builtins/TestBuiltin_bincode.java  |  8 +-
 .../builtins/TestBuiltin_bitwiseShiftL.java   |  2 +
 .../builtins/TestBuiltin_bitwiseShiftR.java   |  3 +
 .../builtins/TestBuiltin_classassign.java     |  8 +-
 23 files changed, 192 insertions(+), 66 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index 0c00091606..9059814482 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -24,6 +24,9 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -34,8 +37,8 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -47,16 +50,11 @@ public abstract class AsCharacter extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsCharacter.class);
-        casts.arg("x").mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector());
+        casts.arg("x").returnIf(missingValue().or(nullValue()), emptyStringVector()).mapIf(instanceOf(RAbstractListVector.class).not(), asStringVector());
     }
 
     @Specialization
-    protected RAbstractStringVector asCharacter(@SuppressWarnings("unused") RNull n) {
-        return RDataFactory.createEmptyStringVector();
-    }
-
-    @Specialization
-    protected RAbstractStringVector asCharacter(RAbstractStringVector v) {
+    protected RAbstractStringVector asCharacter(RAbstractStringVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) {
         if (noAttributes.profile(v.getAttributes() == null)) {
             return v;
         } else {
@@ -65,7 +63,7 @@ public abstract class AsCharacter extends RBuiltinNode {
     }
 
     @Specialization
-    protected RStringVector asCharacter(RAbstractListVector list) {
+    protected RStringVector asCharacter(RAbstractListVector list, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) {
         int len = list.getLength();
         boolean complete = RDataFactory.COMPLETE_VECTOR;
         String[] data = new String[len];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
index 4687524829..1ac005ce1b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyComplexVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -30,8 +33,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 
 @RBuiltin(name = "as.complex", kind = PRIMITIVE, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "..."}, behavior = PURE)
@@ -41,16 +43,11 @@ public abstract class AsComplex extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsComplex.class);
-        casts.arg("x").asComplexVector();
+        casts.arg("x").returnIf(missingValue().or(nullValue()), emptyComplexVector()).asComplexVector();
     }
 
     @Specialization
-    protected RAbstractComplexVector asComplex(@SuppressWarnings("unused") RNull n) {
-        return RDataFactory.createEmptyComplexVector();
-    }
-
-    @Specialization
-    protected RAbstractComplexVector asComplex(RAbstractComplexVector v) {
+    protected RAbstractComplexVector asComplex(RAbstractComplexVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) {
         if (noAttributes.profile(v.getAttributes() == null)) {
             return v;
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
index 7c65477dad..a8e7d27ae6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -29,8 +32,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 @RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
@@ -40,16 +42,11 @@ public abstract class AsDouble extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsDouble.class);
-        casts.arg("x").asDoubleVector();
+        casts.arg("x").returnIf(missingValue().or(nullValue()), emptyDoubleVector()).asDoubleVector();
     }
 
     @Specialization
-    protected RAbstractDoubleVector asDouble(@SuppressWarnings("unused") RNull n) {
-        return RDataFactory.createEmptyDoubleVector();
-    }
-
-    @Specialization
-    protected RAbstractDoubleVector asDouble(RAbstractDoubleVector v) {
+    protected RAbstractDoubleVector asDouble(RAbstractDoubleVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) {
         if (noAttributes.profile(v.getAttributes() == null)) {
             return v;
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
index f7beffc392..79e6144769 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -29,8 +32,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "as.integer", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
@@ -40,16 +42,11 @@ public abstract class AsInteger extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsInteger.class);
-        casts.arg("x").asIntegerVector();
+        casts.arg("x").returnIf(missingValue().or(nullValue()), emptyIntegerVector()).asIntegerVector();
     }
 
     @Specialization
-    protected RAbstractIntVector asInteger(@SuppressWarnings("unused") RNull n) {
-        return RDataFactory.createEmptyIntVector();
-    }
-
-    @Specialization
-    protected RAbstractIntVector asInteger(RAbstractIntVector v) {
+    protected RAbstractIntVector asInteger(RAbstractIntVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) {
         if (noAttributes.profile(v.getAttributes() == null)) {
             return v;
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
index 5df1046a5c..e9eb0ca41e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -29,8 +32,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
 @RBuiltin(name = "as.logical", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
@@ -40,16 +42,11 @@ public abstract class AsLogical extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsLogical.class);
-        casts.arg("x").asLogicalVector();
+        casts.arg("x").returnIf(missingValue().or(nullValue()), emptyLogicalVector()).asLogicalVector();
     }
 
     @Specialization
-    protected RAbstractLogicalVector asLogicaleger(@SuppressWarnings("unused") RNull n) {
-        return RDataFactory.createEmptyLogicalVector();
-    }
-
-    @Specialization
-    protected RAbstractLogicalVector asLogicaleger(RAbstractLogicalVector v) {
+    protected RAbstractLogicalVector asLogicaleger(RAbstractLogicalVector v, @SuppressWarnings("unused") RArgsValuesAndNames dotdotdot) {
         if (noAttributes.profile(v.getAttributes() == null)) {
             return v;
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
index cd935a7b14..ef2911acc2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
@@ -22,12 +22,14 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -40,7 +42,7 @@ public abstract class AsRaw extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(AsRaw.class);
-        casts.arg("x").allowNull().asRawVector();
+        casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENTS_PASSED, 0, "'as.raw'", 1).asRawVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
index ee5ee09e40..32498303a1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
@@ -22,6 +22,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
@@ -32,15 +33,33 @@ public abstract class Bincode extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(Bincode.class);
-        casts.arg("x").asDoubleVector();
+        casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENT_EMPTY, 1).asDoubleVector();
 
-        casts.arg("breaks").asDoubleVector();
+        casts.arg("breaks").mustNotBeMissing(RError.Message.ARGUMENT_EMPTY, 2).asDoubleVector();
 
         casts.arg("right").asLogicalVector().findFirst().map(toBoolean());
 
         casts.arg("include.lowest").asLogicalVector().findFirst().map(toBoolean());
     }
 
+    @SuppressWarnings("unused")
+    @Specialization
+    RIntVector formatC(RNull x, RAbstractDoubleVector breaks, boolean right, boolean includeBorder) {
+        return RDataFactory.createEmptyIntVector();
+    }
+
+    @SuppressWarnings("unused")
+    @Specialization
+    RIntVector formatC(RNull x, RNull breaks, boolean right, boolean includeBorder) {
+        return RDataFactory.createEmptyIntVector();
+    }
+
+    @SuppressWarnings("unused")
+    @Specialization
+    RIntVector formatC(RAbstractDoubleVector x, RNull breaks, boolean right, boolean includeBorder) {
+        return RDataFactory.createIntVector(x.getLength(), true);
+    }
+
     @Specialization
     RIntVector formatC(RAbstractDoubleVector x, RAbstractDoubleVector breaks, boolean right, boolean includeBorder) {
         int n = x.getLength();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
index 439d14b064..f90deab4bf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
@@ -17,6 +17,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asStringVect
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.shouldBe;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
@@ -205,8 +206,9 @@ public class BitwiseFunctions {
 
         static {
             Casts casts = new Casts(BitwiseShiftR.class);
-            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTR.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("n").mapIf(stringValue(), asStringVector(), asIntegerVector());
+            casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTR.name).mustBe(missingValue().not()).mustBe(
+                            doubleValue().or(integerValue())).asIntegerVector();
+            casts.arg("n").allowNull().mustBe(missingValue().not()).mapIf(stringValue(), asStringVector(), asIntegerVector());
         }
 
         @Specialization
@@ -234,7 +236,7 @@ public class BitwiseFunctions {
             Casts casts = new Casts(BitwiseShiftL.class);
             casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe(
                             doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("n").allowNull().mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.Message.NA_INTRODUCED_COERCION)).end(),
+            casts.arg("n").allowNull().mustBe(missingValue().not()).mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.Message.NA_INTRODUCED_COERCION)).end(),
                             asIntegerVector());
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
index c33f2d9649..f63bcc40cc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
@@ -179,8 +179,8 @@ public class DatePOSIXFunctions {
 
         static {
             Casts casts = new Casts(AsPOSIXlt.class);
-            casts.arg("x").mapNull(emptyDoubleVector()).asDoubleVector(true, false, false);
-            casts.arg("tz").asStringVector().findFirst("");
+            casts.arg("x").mapNull(emptyDoubleVector()).mustBe(missingValue().not()).asDoubleVector(true, false, false);
+            casts.arg("tz").mustNotBeMissing().asStringVector().findFirst("");
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 2bfc22099d..88717774e1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -11,7 +11,9 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -101,11 +103,11 @@ public class GrepFunctions {
         }
 
         protected static void castCosts(Casts casts) {
-            casts.arg("costs").asIntegerVector();
+            casts.arg("costs").defaultError(RError.Message.INVALID_ARG, "costs").mustBe((missingValue().or(nullValue()).not())).asIntegerVector();
         }
 
         protected static void castBounds(Casts casts) {
-            casts.arg("bounds").asDoubleVector();
+            casts.arg("bounds").defaultError(RError.Message.INVALID_ARG, "bounds").mustBe((missingValue().or(nullValue()).not())).asDoubleVector();
         }
 
         /**
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index 20f38f2b25..b579cd587c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -11,6 +11,7 @@
 
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -52,8 +53,8 @@ public abstract class UpdateClass extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(UpdateClass.class);
-        casts.arg("x"); // disallows null
-        casts.arg("value").asStringVector();
+        casts.arg("x").mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 1);
+        casts.arg("value").mustBe(missingValue().not(), RError.Message.ARGUMENT_EMPTY, 2).asStringVector();
     }
 
     @Specialization
@@ -64,6 +65,11 @@ public abstract class UpdateClass extends RBuiltinNode {
         return result;
     }
 
+    @Specialization
+    protected Object setClass(@SuppressWarnings("unused") RNull arg, @SuppressWarnings("unused") Object className) {
+        throw error(RError.Message.SET_ATTRIBUTES_ON_NULL);
+    }
+
     @Specialization(limit = "CACHE_LIMIT", guards = "cachedClassName == className")
     protected Object setClassCached(RAbstractContainer arg, @SuppressWarnings("unused") String className,
                     @Cached("className") String cachedClassName,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java
index b4dea21f74..e1aab99445 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java
@@ -32,6 +32,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "break", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
 public abstract class BreakBuiltin extends RBuiltinNode {
+    static {
+        Casts.noCasts(BreakBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
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 e1ec10e788..7611467d50 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
@@ -4827,6 +4827,14 @@ numeric(0)
 #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = 22:27, mon = 3L, year = 108L, wday = 2L, yday = 112L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = 'GMT'), 'GMT'); .Internal(as.POSIXct(argv[[1]], argv[[2]]))
 [1] 1208822400 1208908800 1208995200 1209081600 1209168000 1209254400
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#
+#.Internal(as.POSIXlt(, 1))
+Error in .Internal(as.POSIXlt(, 1)) : argument 1 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#
+#.Internal(as.POSIXlt(2, ))
+Error in .Internal(as.POSIXlt(2, )) : argument 2 is empty
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt1#
 #argv <- list(structure(c(2147483648.4, 2147483648.8), class = c('POSIXct', 'POSIXt'), tzone = ''), ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]]))
 [1] "2038-01-19 03:14:08 GMT" "2038-01-19 03:14:08 GMT"
@@ -4995,6 +5003,10 @@ quote(80L)
 #argv <- list(list(quote(quote), NA));as.call(argv[[1]]);
 quote(NA)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter#
+#{ as.character() }
+character(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter#
 #{ as.character(1) }
 [1] "1"
@@ -5406,6 +5418,10 @@ character(0)
 Warning message:
 NAs introduced by coercion
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex#
+#{ as.complex() }
+complex(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex#
 #{ as.complex(0) }
 [1] 0+0i
@@ -5538,6 +5554,10 @@ Time differences in hours
 Warning message:
 NAs introduced by coercion
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
+#{ as.double() }
+numeric(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#Output.IgnoreWarningContext#
 #{ as.double(10+2i) }
 [1] 10
@@ -6003,6 +6023,10 @@ numeric(0)
 Warning message:
 NAs introduced by coercion
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger#
+#{ as.integer() }
+integer(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger#
 #{ as.integer(-0/0) }
 [1] NA
@@ -6601,6 +6625,10 @@ Warning messages:
 Warning message:
 out-of-range values treated as 0 in coercion to raw
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#
+#{ as.raw() }
+Error in as.raw() : 0 arguments passed to 'as.raw' which requires 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#Output.IgnoreWarningContext#
 #{ as.raw(-1) }
 [1] 00
@@ -9127,6 +9155,22 @@ numeric(0)
 #argv <- structure(list(a = 1e-200, b = 1e-200), .Names = c('a',     'b'));do.call('beta', argv)
 [1] 2e+200
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#Output.MayIgnoreErrorContext#
+#{ .Internal(bincode(, 1, T, T)) }
+Error in .Internal(bincode(, 1, T, T)) : argument 1 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#Output.MayIgnoreErrorContext#
+#{ .Internal(bincode(1, ,T, T)) }
+Error in .Internal(bincode(1, , T, T)) : argument 2 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#
+#{ .Internal(bincode(2, NULL, T, T)) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#
+#{ .Internal(bincode(NULL, 2, T, T)) }
+integer(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_bincode.testBincode#
 #{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, FALSE) }
 [1]  2  2  2  2 NA
@@ -9266,6 +9310,14 @@ Error in bitwOr(c(1, 2, 3, 4), c(3 + (0+3i))) :
 [25]   -33554432   -67108864  -134217728  -268435456  -536870912 -1073741824
 [31]          NA
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
+#{ .Internal(bitwiseShiftL(, 1))}
+Error in .Internal(bitwiseShiftL(, 1)) : argument 1 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
+#{ .Internal(bitwiseShiftL(200, ))}
+Error in .Internal(bitwiseShiftL(200, )) : argument 2 is empty
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
 #{ bitwShiftL(TRUE, c(TRUE, FALSE)) }
 Error in bitwShiftL(TRUE, c(TRUE, FALSE)) :
@@ -9305,6 +9357,14 @@ In bitwShiftL(c(3, 2, 4), c(3 + (0+3i))) :
 #{ bitwShiftL(c(8,4,2), NULL) }
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
+#{ .Internal(bitwiseShiftR(, 1))}
+Error in .Internal(bitwiseShiftR(, 1)) : argument 1 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
+#{ .Internal(bitwiseShiftR(200, ))}
+Error in .Internal(bitwiseShiftR(200, )) : argument 2 is empty
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Ignored.Unknown#
 #{ bitwShiftR(c(1,2,3,4), c("Hello")) }
 [1] NA NA NA NA
@@ -9373,7 +9433,7 @@ Error in bitwXor(c("r"), c(16, 17)) : 'a' and 'b' must have the same type
 #argv <- list(function (from, strict = TRUE) from); .Internal(body(argv[[1]]))
 from
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_body.testbody4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_body.testbody4#
 #argv <- list(.Primitive('/')); .Internal(body(argv[[1]]))
 NULL
 
@@ -12884,6 +12944,18 @@ function() 42
 #{ x=1;class(x)<-"character"; x}
 [1] "1"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+#{`class<-`(, "foo") }
+Error in `class<-`(, "foo") : argument 1 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+#{`class<-`(, ) }
+Error in `class<-`(, ) : argument 1 is empty
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+#{`class<-`(NULL, "first") }
+Error: attempt to set an attribute on NULL
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
 #{x<-"abc";class(x)<-"a";class(x)<-"character";x;}
 [1] "abc"
@@ -13005,6 +13077,10 @@ Error in class(x) <- "array" :
 #{x<-c(2+3i,4+5i);class(x)<-"a";class(x)<-"complex";x;}
 [1] 2+3i 4+5i
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+#{x=1; `class<-`(x, ) }
+Error in `class<-`(x, ) : argument 2 is empty
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
 #{x=1; class(x)<-"first"; x;}
 [1] 1
@@ -29709,7 +29785,7 @@ Coefficients:
 #require(stats); lm(formula = y ~ x)
 Error in eval(expr, envir, enclos) : object 'y' not found
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment#Ignored.MissingBuiltin#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment#
 #e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123
 Error in e$a <- 123 : cannot change value of locked binding for 'a'
 
@@ -33620,7 +33696,7 @@ Error in nchar("aasd", type = "charsxzy") : invalid 'type' argument
 #argv <- list(character(0), 'c', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13#
 #argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\'Terry\', \'Therneau\', role = \'aut\',\n\t             email = \'therneau@mayo.edu\'),\n             person(\'Beth\', \'Atkinson\', role = \'aut\',\t\n\t             email = \'atkinson@mayo.edu\'),\n             person(\'Brian\', \'Ripley\', role = c(\'aut\', \'trl\', \'cre\'),\n                    email = \'ripley@stats.ox.ac.uk\',\n\t\t   comment = \'author of R port\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\n  Beth Atkinson [aut],\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
     Package    Priority     Version        Date   Authors@R Description
           5          11           5          10         345          43
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java
index b6cb25016b..782fe19c2e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_asPOSIXlt extends TestBase {
@@ -71,4 +72,10 @@ public class TestBuiltin_asPOSIXlt extends TestBase {
     public void testasPOSIXlt11() {
         assertEval("argv <- list(NULL, ''); .Internal(as.POSIXlt(argv[[1]], argv[[2]]))");
     }
+
+    @Test
+    public void testasPOSIXlt() {
+        assertEval(Output.MayIgnoreErrorContext, ".Internal(as.POSIXlt(, 1))");
+        assertEval(Output.MayIgnoreErrorContext, ".Internal(as.POSIXlt(2, ))");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
index 551890dda8..c14ea94779 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
@@ -249,6 +249,7 @@ public class TestBuiltin_ascharacter extends TestBase {
 
     @Test
     public void testAsCharacter() {
+        assertEval("{ as.character() }");
         assertEval("{ as.character(1) }");
         assertEval("{ as.character(1L) }");
         assertEval("{ as.character(TRUE) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java
index e8c02db813..7f63eca369 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -74,6 +74,7 @@ public class TestBuiltin_ascomplex extends TestBase {
 
     @Test
     public void testAsComplex() {
+        assertEval("{ as.complex() }");
         assertEval("{ as.complex(0) }");
         assertEval("{ as.complex(TRUE) }");
         assertEval("{ as.complex(\"1+5i\") }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
index be3fdc04e5..2277c79179 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -175,6 +175,7 @@ public class TestBuiltin_asdouble extends TestBase {
 
     @Test
     public void testAsDouble() {
+        assertEval("{ as.double() }");
         assertEval("{ as.double(\"1.27\") }");
         assertEval("{ as.double(1L) }");
         assertEval("{ as.double(as.raw(1)) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java
index dc6b2ebb7a..6efaa38af0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -116,6 +116,7 @@ public class TestBuiltin_asinteger extends TestBase {
 
     @Test
     public void testAsInteger() {
+        assertEval("{ as.integer() }");
         assertEval("{ as.integer(\"1\") }");
         assertEval("{ as.integer(c(\"1\",\"2\")) }");
         assertEval("{ as.integer(c(1,2,3)) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java
index cd7d0198a3..d8c0187dac 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java
@@ -49,6 +49,7 @@ public class TestBuiltin_asraw extends TestBase {
 
     @Test
     public void testAsRaw() {
+        assertEval("{ as.raw() }");
         assertEval("{ as.raw(NULL) }");
         assertEval("{ as.raw(1) }");
         assertEval("{ as.raw(1L) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java
index b846256ea7..15d35bf6b7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bincode.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -53,5 +53,11 @@ public class TestBuiltin_bincode extends TestBase {
         assertEval("{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, FALSE) }");
         assertEval("{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, TRUE, TRUE) }");
         assertEval("{ x <- c(0, 0.01, 0.5, 0.99, 1); b <- c(0, 0, 1, 1); .bincode(x, b, FALSE, TRUE) }");
+
+        assertEval("{ .Internal(bincode(NULL, 2, T, T)) }");
+        assertEval("{ .Internal(bincode(2, NULL, T, T)) }");
+
+        assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bincode(, 1, T, T)) }");
+        assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bincode(1, ,T, T)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
index d750ef4512..d62332e72c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftL.java
@@ -24,6 +24,8 @@ public class TestBuiltin_bitwiseShiftL extends TestBase {
 
     @Test
     public void testBitwiseFunctions() {
+        assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftL(, 1))}");
+        assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftL(200, ))}");
         assertEval("{ bitwShiftL(c(10,11,12,13,14,15), c(1,1,1,1,1,1)) }");
         assertEval("{ bitwShiftL(c(100,200,300), 1) }");
         assertEval("{ bitwShiftL(c(25,57,66), c(10,20,30,40,50,60)) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
index de9c5d5ae2..436951f231 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_bitwiseShiftR extends TestBase {
@@ -24,6 +25,8 @@ public class TestBuiltin_bitwiseShiftR extends TestBase {
 
     @Test
     public void testBitwiseFunctions() {
+        assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftR(, 1))}");
+        assertEval(Output.MayIgnoreErrorContext, "{ .Internal(bitwiseShiftR(200, ))}");
         assertEval("{ bitwShiftR(c(10,11,12,13,14,15), c(1,1,1,1,1,1)) }");
         assertEval("{ bitwShiftR(c(100,200,300), 1) }");
         assertEval("{ bitwShiftR(c(25,57,66), c(10,20,30,40,50,60)) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java
index 4d2c9af5a1..307c2f258c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_classassign extends TestBase {
@@ -126,6 +127,11 @@ public class TestBuiltin_classassign extends TestBase {
 
     @Test
     public void testUpdateClass() {
+        assertEval(Output.MayIgnoreErrorContext, "{`class<-`(, \"foo\") }");
+        assertEval(Output.MayIgnoreErrorContext, "{`class<-`(, ) }");
+        assertEval(Output.MayIgnoreErrorContext, "{x=1; `class<-`(x, ) }");
+        assertEval(Output.MayIgnoreErrorContext, "{`class<-`(NULL, \"first\") }");
+
         assertEval("{x=1; class(x)<-\"first\"; x;}");
 
         assertEval("{ x=1;class(x)<-\"character\"; x}");
-- 
GitLab


From fd42604d8acec65e256f2231bab10c958a60ffef Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 6 Mar 2017 19:33:35 +0100
Subject: [PATCH 107/402] Implemented function '.fastr.channelConnection'.

---
 .../r/nodes/builtin/base/BasePackage.java     |  1 +
 .../builtin/base/ConnectionFunctions.java     | 34 +++++++
 .../r/runtime/conn/ChannelConnections.java    | 95 +++++++++++++++++++
 .../r/runtime/conn/ConnectionSupport.java     |  3 +-
 .../r/test/library/base/TestConnections.java  | 23 +++++
 5 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 4d3905afb9..16e97d3504 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -270,6 +270,7 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.SocketConnection.class, ConnectionFunctionsFactory.SocketConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnection.class, ConnectionFunctionsFactory.RawConnectionNodeGen::create);
         add(ConnectionFunctions.RawConnectionValue.class, ConnectionFunctionsFactory.RawConnectionValueNodeGen::create);
+        add(ConnectionFunctions.ChannelConnection.class, ConnectionFunctionsFactory.ChannelConnectionNodeGen::create);
         add(ConnectionFunctions.Fifo.class, ConnectionFunctionsFactory.FifoNodeGen::create);
         add(ConnectionFunctions.Pipe.class, ConnectionFunctionsFactory.PipeNodeGen::create);
         add(ConnectionFunctions.Stderr.class, ConnectionFunctionsFactory.StderrNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 785b4a0f00..43eebefbe8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -54,6 +54,7 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.DoubleBuffer;
 import java.nio.IntBuffer;
+import java.nio.channels.ByteChannel;
 import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
 
@@ -61,6 +62,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.WriteDataNodeGen;
@@ -72,6 +75,8 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
+import com.oracle.truffle.r.runtime.conn.ChannelConnections.ChannelRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.FifoConnections.FifoRConnection;
 import com.oracle.truffle.r.runtime.conn.FileConnections.CompressedRConnection;
@@ -1329,4 +1334,33 @@ public abstract class ConnectionFunctions {
             return RNull.instance;
         }
     }
+
+    @RBuiltin(name = ".fastr.channelConnection", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"description", "channel", "open", "encoding"}, behavior = IO)
+    public abstract static class ChannelConnection extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(ChannelConnection.class);
+            CastsHelper.description(casts);
+            casts.arg("channel").mustNotBeMissing().mustBe(nullValue().not().and(instanceOf(TruffleObject.class)));
+            CastsHelper.openMode(casts);
+            CastsHelper.encoding(casts);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected RAbstractIntVector channelConnection(String description, TruffleObject channel, String open, String encoding) {
+            try {
+                if (JavaInterop.isJavaObject(ByteChannel.class, channel)) {
+                    ByteChannel ch = JavaInterop.asJavaObject(ByteChannel.class, channel);
+                    return new ChannelRConnection(description, ch, open, encoding).asVector();
+                }
+                // TODO improve error handling
+                throw new RInternalError("invalid object type %s", JavaInterop.unbox(channel).getClass());
+            } catch (IOException ex) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
new file mode 100644
index 0000000000..a5ebc5068e
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.nio.channels.ByteChannel;
+import java.util.Objects;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
+
+/**
+ * A connection type for communicating to arbitrary Java NIO channels.
+ */
+public class ChannelConnections {
+
+    public static class ChannelRConnection extends BaseRConnection {
+
+        private final String description;
+        private final ByteChannel channel;
+
+        public ChannelRConnection(String description, ByteChannel channel, String modeString, String encoding) throws IOException {
+            super(ConnectionClass.CHANNEL, modeString, AbstractOpenMode.Read, encoding);
+            this.description = description;
+            this.channel = Objects.requireNonNull(channel);
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            final AbstractOpenMode mode = getOpenMode().abstractOpenMode;
+            switch (mode) {
+                case Read:
+                case ReadBinary:
+                case Write:
+                case WriteBinary:
+                case ReadWrite:
+                case ReadWriteBinary:
+                    setDelegate(new ChannelReadWriteRConnection(this));
+                    break;
+                default:
+                    throw RError.nyi(RError.SHOW_CALLER, mode.name());
+            }
+        }
+
+        @Override
+        public String getSummaryDescription() {
+            return description;
+        }
+
+    }
+
+    private static class ChannelReadWriteRConnection extends DelegateReadWriteRConnection {
+
+        private final ChannelRConnection base;
+
+        protected ChannelReadWriteRConnection(ChannelRConnection base) {
+            super(base, 0);
+            this.base = base;
+        }
+
+        @Override
+        public ByteChannel getChannel() throws IOException {
+            return base.channel;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return false;
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index c0c2e5bf8e..356a823105 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -334,7 +334,8 @@ public class ConnectionSupport {
         RAW("rawConnection"),
         Internal("internal"),
         PIPE("pipe"),
-        FIFO("fifo");
+        FIFO("fifo"),
+        CHANNEL("Java Channel");
 
         private final String printName;
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 2f34c08b2f..641e936737 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.test.library.base;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.channels.ByteChannel;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -35,6 +36,10 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
+import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel;
 import com.oracle.truffle.r.test.TestBase;
 import com.oracle.truffle.r.test.TestRBase;
 
@@ -260,4 +265,22 @@ public class TestConnections extends TestRBase {
     private static String[] arr(String... args) {
         return args;
     }
+
+    private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel();
+
+    @Test
+    public void testChannelConnection() throws IOException {
+
+        final String line0 = "Hello, World!\n";
+        final String line1 = "incomplete";
+        CHANNEL.write(line0.getBytes());
+        CHANNEL.write(line1.getBytes());
+        CHANNEL.position(0);
+        assertEval(" v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection('hello', v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res", line0 + line1);
+    }
+
+    @Override
+    public void addPolyglotSymbols(Builder builder) {
+        builder.globalSymbol("_fastr_channel0", JavaInterop.asTruffleObject("hehe"));
+    }
 }
-- 
GitLab


From b605a88260abba28dd96370c92e0a0bc2d8265e2 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 7 Mar 2017 08:40:25 +0100
Subject: [PATCH 108/402] Finished unit test and improved error handling for
 channel connections.

---
 .../builtin/base/ConnectionFunctions.java     | 17 ++++--
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../r/runtime/conn/ChannelConnections.java    |  1 +
 .../conn/SeekableMemoryByteChannel.java       |  6 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 58 ++++---------------
 .../r/test/library/base/TestConnections.java  | 33 ++++++++++-
 6 files changed, 61 insertions(+), 57 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 43eebefbe8..064c0481a1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -55,6 +55,7 @@ import java.nio.ByteOrder;
 import java.nio.DoubleBuffer;
 import java.nio.IntBuffer;
 import java.nio.channels.ByteChannel;
+import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.util.ArrayList;
 
@@ -96,6 +97,7 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
@@ -1335,27 +1337,30 @@ public abstract class ConnectionFunctions {
         }
     }
 
-    @RBuiltin(name = ".fastr.channelConnection", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"description", "channel", "open", "encoding"}, behavior = IO)
+    @RBuiltin(name = ".fastr.channelConnection", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"channel", "open", "encoding"}, behavior = IO)
     public abstract static class ChannelConnection extends RBuiltinNode {
 
         static {
             Casts casts = new Casts(ChannelConnection.class);
-            CastsHelper.description(casts);
             casts.arg("channel").mustNotBeMissing().mustBe(nullValue().not().and(instanceOf(TruffleObject.class)));
             CastsHelper.openMode(casts);
             CastsHelper.encoding(casts);
         }
 
+        @Override
+        public Object[] getDefaultParameterValues() {
+            return new Object[]{RMissing.instance, RMissing.instance, Charset.defaultCharset().name()};
+        }
+
         @Specialization
         @TruffleBoundary
-        protected RAbstractIntVector channelConnection(String description, TruffleObject channel, String open, String encoding) {
+        protected RAbstractIntVector channelConnection(TruffleObject channel, String open, String encoding) {
             try {
                 if (JavaInterop.isJavaObject(ByteChannel.class, channel)) {
                     ByteChannel ch = JavaInterop.asJavaObject(ByteChannel.class, channel);
-                    return new ChannelRConnection(description, ch, open, encoding).asVector();
+                    return new ChannelRConnection("", ch, open, encoding).asVector();
                 }
-                // TODO improve error handling
-                throw new RInternalError("invalid object type %s", JavaInterop.unbox(channel).getClass());
+                throw error(RError.Message.INVALID_CHANNEL_OBJECT, JavaInterop.unbox(channel).getClass());
             } catch (IOException ex) {
                 throw RInternalError.shouldNotReachHere();
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 8a7f66a247..12d944ccc0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -846,7 +846,8 @@ public final class RError extends RuntimeException {
         TRUNCATE_ONLY_OPEN_CONN("can only truncate an open connection"),
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
         TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"),
-        INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded");
+        INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded"),
+        INVALID_CHANNEL_OBJECT("invalid channel object type: %s");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
index a5ebc5068e..f5d8cd1802 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
@@ -45,6 +45,7 @@ public class ChannelConnections {
             super(ConnectionClass.CHANNEL, modeString, AbstractOpenMode.Read, encoding);
             this.description = description;
             this.channel = Objects.requireNonNull(channel);
+            openNonLazyConnection();
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
index 256b4e4a99..7476dc5426 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -226,7 +226,11 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
 
     @Override
     public void close() throws IOException {
-        open = false;
+        setOpen(false);
+    }
+
+    public void setOpen(boolean open) {
+        this.open = open;
     }
 
     public InputStream getInputStream() {
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 319431438d..bb1f1db842 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
@@ -9373,7 +9373,7 @@ Error in bitwXor(c("r"), c(16, 17)) : 'a' and 'b' must have the same type
 #argv <- list(function (from, strict = TRUE) from); .Internal(body(argv[[1]]))
 from
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_body.testbody4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_body.testbody4#
 #argv <- list(.Primitive('/')); .Internal(body(argv[[1]]))
 NULL
 
@@ -29709,7 +29709,7 @@ Coefficients:
 #require(stats); lm(formula = y ~ x)
 Error in eval(expr, envir, enclos) : object 'y' not found
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment#Ignored.MissingBuiltin#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lockEnvironment.testlockEnvironment#
 #e <- new.env(); e$a <- 'foo'; lockEnvironment(e, 'a'); e$a <- 123
 Error in e$a <- 123 : cannot change value of locked binding for 'a'
 
@@ -33620,7 +33620,7 @@ Error in nchar("aasd", type = "charsxzy") : invalid 'type' argument
 #argv <- list(character(0), 'c', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar13#
 #argv <- list(structure(c('rpart', 'recommended', '4.1-1', '2013-03-20', 'c(person(\'Terry\', \'Therneau\', role = \'aut\',\n\t             email = \'therneau@mayo.edu\'),\n             person(\'Beth\', \'Atkinson\', role = \'aut\',\t\n\t             email = \'atkinson@mayo.edu\'),\n             person(\'Brian\', \'Ripley\', role = c(\'aut\', \'trl\', \'cre\'),\n                    email = \'ripley@stats.ox.ac.uk\',\n\t\t   comment = \'author of R port\'))', 'Recursive partitioning and regression trees', 'Recursive Partitioning', 'R (>= 2.14.0), graphics, stats, grDevices', 'survival', 'GPL-2 | GPL-3', 'yes', 'yes', 'Maintainers are not available to give advice on using a package\nthey did not author.', '2013-03-20 07:27:05 UTC; ripley', 'Terry Therneau [aut],\n  Beth Atkinson [aut],\n  Brian Ripley [aut, trl, cre] (author of R port)', 'Brian Ripley <ripley@stats.ox.ac.uk>'), .Names = c('Package', 'Priority', 'Version', 'Date', 'Authors@R', 'Description', 'Title', 'Depends', 'Suggests', 'License', 'LazyData', 'ByteCompile', 'Note', 'Packaged', 'Author', 'Maintainer')), 'c', TRUE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
     Package    Priority     Version        Date   Authors@R Description
           5          11           5          10         345          43
@@ -73276,6 +73276,14 @@ Read 4 items
 Summary of Residuals:
 
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testChannelConnection#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('hi there', zz); close(zz); NULL  }
+NULL
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testChannelConnection#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('Hello, World!', 'second line') } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res }
+[1] "Hello, World!" "second line"
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
 #fin <- file('', "w+", encoding = "___inexistingCharSet___")
 Error in file("", "w+", encoding = "___inexistingCharSet___") :
@@ -73290,7 +73298,7 @@ Error in file("", "w+", encoding = "___inexistingCharSet___") :
 fifo
 TRUE
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testFifoOpenInexisting#Output.IgnoreErrorContext#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.library.base.TestConnections.testFifoOpenInexisting#
 #{ fn <- '___fifo_2367253765'; zz <- fifo(fn, 'r', blocking = TRUE); close(zz); unlink(fn) }
 Error in fifo(fn, "r", blocking = TRUE) : cannot open the connection
 In addition: Warning message:
@@ -73728,48 +73736,6 @@ Error in textConnection(NULL, "r") : invalid 'text' argument
 #{ con <- textConnection(c("1", "2", "3","4")); readLines(con, 2); readLines(con, 2); readLines(con, 2) }
 character(0)
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#fn <- '__tmp_77253842367367'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); close(zz); readLines(file(fn)); unlink(fn)
-[1] 22
-NULL
-character(0)
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#fn <- '__tmp_98723669834556'; zz <- file(fn, 'w'); writeLines(c('Hello', 'wonderful', 'World'), zz); close(zz); zz <- file(fn, 'r'); truncate(zz); unlink(fn)
-Error in truncate.connection(zz) :
-  can only truncate connections open for writing
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#truncate(fifo('__fifo_872636743', 'w+', blocking=T)); unlink('__fifo_872636743')
-Error in truncate.connection(fifo("__fifo_872636743", "w+", blocking = T)) :
-  truncation not enabled for this connection
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#truncate(fifo('__fifo_982346798', 'r', blocking=T)); unlink('__fifo_982346798')
-Error in fifo("__fifo_982346798", "r", blocking = T) :
-  cannot open the connection
-In addition: Warning message:
-In fifo("__fifo_982346798", "r", blocking = T) :
-  cannot open fifo '__fifo_982346798'
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#truncate(pipe('ls'))
-Error in truncate.connection(pipe("ls")) :
-  can only truncate an open connection
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#zz <- file(''); writeLines(c('Hello', 'wonderful', 'World'), zz); seek(zz, 0); truncate(zz); flush(zz); readLines(zz)
-[1] 22
-NULL
-character(0)
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testTruncate#
-#zz <- rawConnection(raw(0), 'r+'); writeLines(c('hello', 'world'), zz); rawConnectionValue(zz); seek(zz, 5); truncate(zz); rawConnectionValue(zz); close(zz)
- [1] 68 65 6c 6c 6f 0a 77 6f 72 6c 64 0a
-[1] 12
-NULL
-[1] 68 65 6c 6c 6f
-
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextConnection#
 #c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\n', file=c); isIncomplete(c); close(c); out
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 641e936737..16b5b13370 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.test.library.base;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.ByteBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -45,6 +46,8 @@ import com.oracle.truffle.r.test.TestRBase;
 
 // Checkstyle: stop line length check
 public class TestConnections extends TestRBase {
+    private static final String CHANNEL_NAME = "_fastr_channel0";
+
     private static final class TestDir {
         private final Path testDirPath;
 
@@ -272,15 +275,39 @@ public class TestConnections extends TestRBase {
     public void testChannelConnection() throws IOException {
 
         final String line0 = "Hello, World!\n";
-        final String line1 = "incomplete";
+        final String line1 = "second line\n";
         CHANNEL.write(line0.getBytes());
         CHANNEL.write(line1.getBytes());
+        long oldPos = CHANNEL.position();
         CHANNEL.position(0);
-        assertEval(" v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection('hello', v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res", line0 + line1);
+        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res",
+                        CHANNEL_NAME),
+                        "c('Hello, World!', 'second line')");
+
+        if (!generatingExpected()) {
+            // test if FastR consumed the data
+            Assert.assertEquals(oldPos, CHANNEL.position());
+
+            // re-open channel
+            CHANNEL.setOpen(true);
+            CHANNEL.position(0);
+        }
+
+        final String response = "hi there";
+        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('%s', zz); close(zz); NULL ", CHANNEL_NAME, response),
+                        "NULL");
+
+        if (!generatingExpected()) {
+            ByteBuffer buf = ByteBuffer.allocate(response.length());
+            CHANNEL.setOpen(true);
+            CHANNEL.position(0);
+            CHANNEL.read(buf);
+            Assert.assertEquals(response, new String(buf.array()));
+        }
     }
 
     @Override
     public void addPolyglotSymbols(Builder builder) {
-        builder.globalSymbol("_fastr_channel0", JavaInterop.asTruffleObject("hehe"));
+        builder.globalSymbol(CHANNEL_NAME, JavaInterop.asTruffleObject(CHANNEL));
     }
 }
-- 
GitLab


From ea00a17ac48863b5089d6b47b7bbe5758c9ca617 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Mar 2017 15:15:12 +0100
Subject: [PATCH 109/402] update truffle dependency

---
 mx.fastr/suite.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index c21926d4d3..b24b44508b 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -28,7 +28,7 @@ suite = {
     "suites" : [
             {
                "name" : "truffle",
-               "version" : "c02973969fb144b533ae0e53187674cb04c2aacc",
+               "version" : "1350be0c0c0c52b9b2d6136dfc07466d73ab217f",
                "urls" : [
                     {"url" : "https://github.com/graalvm/truffle", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From 1187cfa492475fe535e4e1d67dc06c4912c0300f Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Mar 2017 15:27:11 +0100
Subject: [PATCH 110/402] add RRaw to primitives in BinaryBooleanNodeTest

---
 .../com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java
index 5203cde2f6..71aab4eccf 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java
@@ -57,6 +57,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RScalarVector;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -274,7 +275,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
     }
 
     private static boolean isPrimitive(Object result) {
-        return result instanceof Integer || result instanceof Double || result instanceof Byte || result instanceof RComplex;
+        return result instanceof Integer || result instanceof Double || result instanceof Byte || result instanceof RComplex || result instanceof RRaw;
     }
 
     private NodeHandle<BinaryBooleanNode> handle;
-- 
GitLab


From 892e6567c0a4e9695a205f1812fa7033085d3bb3 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 8 Mar 2017 16:07:09 +0100
Subject: [PATCH 111/402] Implemented RFFI functions 'R_ReadConnection',
 'R_WriteConnection', and 'R_GetConnection'. Also added a few more functions
 to access the properties of a connection. The implementation was tested with
 R package 'jsonlite'.

---
 .../fficall/src/jni/Connections.c             | 241 +++++++++++++++++-
 .../fficall/src/jni/call_rffi.c               |   1 +
 .../fficall/src/jni/rffiutils.h               |   2 +
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  57 +++++
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java |   7 +
 .../r/nodes/ffi/TracingUpCallsRFFIImpl.java   |  42 +++
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |  15 ++
 7 files changed, 362 insertions(+), 3 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 812f804dcd..8b4fc50ddc 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,18 +21,253 @@
  * questions.
  */
 
+#include <assert.h>
 #include <rffiutils.h>
 #include <R_ext/Connections.h>
 
+
+static jmethodID readConnMethodID;
+static jmethodID writeConnMethodID;
+static jmethodID getConnMethodID;
+static jmethodID getConnClassMethodID;
+static jmethodID getSummaryDescMethodID;
+static jmethodID isSeekableMethodID;
+static jmethodID getOpenModeMethodID;
+
+static jbyteArray wrap(JNIEnv *thisenv, void* buf, size_t n) {
+    jbyteArray barr = (*thisenv)->NewByteArray(thisenv, n);
+    (*thisenv)->SetByteArrayRegion(thisenv, barr, 0, n, buf);
+    return barr;
+}
+
+/*
+ * Returns the file descriptor of the connection if possible.
+ * Otherwise an error is issued.
+ */
+static int getFd(Rconnection con) {
+	if(strstr(con->class, "file") != NULL ) {
+		return *((int*)(con->private));
+	}
+	error(_("cannot get file descriptor for non-file connection"));
+	return -1;
+}
+
+/*
+ * Sets the file descriptor for the connection.
+ */
+static void setFd(Rconnection con, jint fd) {
+	*((int*)(con->private)) = fd;
+}
+
+
+void init_connections(JNIEnv *env) {
+	/* int readConn(int, byte[]) */
+	readConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ReadConnection", "(I[B)I", 0);
+
+	/* int writeConn(int, byte[]) */
+	writeConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_WriteConnection", "(I[B)I", 0);
+
+	/* RConnection getConnection(int) */
+	getConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_GetConnection", "(I)Ljava/lang/Object;", 0);
+
+
+	/* String getConnectionClassString(BaseRConnection) */
+	getConnClassMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getConnectionClassString", "(Ljava/lang/Object;)Ljava/lang/String;", 0);
+
+	/* String getSummaryDescription(BaseRConnection) */
+	getSummaryDescMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getSummaryDescription", "(Ljava/lang/Object;)Ljava/lang/String;", 0);
+
+	/* boolean isSeekable(BaseRConnection) */
+	isSeekableMethodID = checkGetMethodID(env, UpCallsRFFIClass, "isSeekable", "(Ljava/lang/Object;)Z", 0);
+
+	/* String getOpenModeString(BaseRConnection) */
+	getOpenModeMethodID = checkGetMethodID(env, UpCallsRFFIClass, "getOpenModeString", "(Ljava/lang/Object;)Ljava/lang/String;", 0);
+}
+
+static char *connStringToChars(JNIEnv *env, jstring string) {
+    jsize len = (*env)->GetStringUTFLength(env, string);
+    const char *stringChars = (*env)->GetStringUTFChars(env, string, NULL);
+    char *copyChars = malloc((len + 1)*sizeof(char));
+    memcpy(copyChars, stringChars, len*sizeof(char));
+    copyChars[len] = 0;
+	(*env)->ReleaseStringUTFChars(env, string, stringChars);
+	(*env)->DeleteLocalRef(env, string);
+    return copyChars;
+}
+
+/* ------------------- null connection functions --------------------- */
+
+static Rboolean NORET null_open(Rconnection con)
+{
+    error(_("%s not enabled for this connection"), "open");
+}
+
+static void null_close(Rconnection con)
+{
+    con->isopen = FALSE;
+}
+
+static void null_destroy(Rconnection con)
+{
+    if(con->private) free(con->private);
+}
+
+static int NORET null_vfprintf(Rconnection con, const char *format, va_list ap)
+{
+    error(_("%s not enabled for this connection"), "printing");
+}
+
+static int NORET null_fgetc(Rconnection con)
+{
+    error(_("%s not enabled for this connection"), "'getc'");
+}
+
+static double NORET null_seek(Rconnection con, double where, int origin, int rw)
+{
+    error(_("%s not enabled for this connection"), "'seek'");
+}
+
+static void NORET null_truncate(Rconnection con)
+{
+    error(_("%s not enabled for this connection"), "truncation");
+}
+
+static int null_fflush(Rconnection con)
+{
+}
+
+static size_t NORET null_read(void *ptr, size_t size, size_t nitems,
+			Rconnection con)
+{
+    error(_("%s not enabled for this connection"), "'read'");
+}
+
+static size_t NORET null_write(const void *ptr, size_t size, size_t nitems,
+			 Rconnection con)
+{
+    error(_("%s not enabled for this connection"), "'write'");
+}
+
+static void init_con(Rconnection new, char *description, int enc,
+	      const char * const mode)
+{
+    new->description = description;
+    new->enc = enc;
+    strncpy(new->mode, mode, 4); new->mode[4] = '\0';
+    new->isopen = new->incomplete = new->blocking = new->isGzcon = FALSE;
+    new->canread = new->canwrite = TRUE; /* in principle */
+    new->canseek = FALSE;
+    new->text = TRUE;
+    new->open = &null_open;
+    new->close = &null_close;
+    new->destroy = &null_destroy;
+    new->vfprintf = &null_vfprintf;
+    new->fgetc = new->fgetc_internal = &null_fgetc;
+    new->seek = &null_seek;
+    new->truncate = &null_truncate;
+    new->fflush = &null_fflush;
+    new->read = &null_read;
+    new->write = &null_write;
+    new->nPushBack = 0;
+    new->save = new->save2 = -1000;
+    new->private = NULL;
+    new->inconv = new->outconv = NULL;
+    new->UTF8out = FALSE;
+    new->id = 0;
+    new->ex_ptr = NULL;
+    new->status = NA_INTEGER;
+}
+
 SEXP R_new_custom_connection(const char *description, const char *mode, const char *class_name, Rconnection *ptr) {
 	return unimplemented("R_new_custom_connection");
 }
 
 size_t R_ReadConnection(Rconnection con, void *buf, size_t n) {
-	return (size_t) unimplemented("R_ReadConnection");
+    JNIEnv *thisenv = getEnv();
+    jbyteArray barr = (*thisenv)->NewByteArray(thisenv, n);
+
+    jint result =  (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, readConnMethodID, getFd(con), barr);
+    size_t readBytes = result >= 0 ? (size_t) result : 0;
+    assert(result <= (ssize_t) n);
+    if(result > 0) {
+    	(*thisenv)->GetByteArrayRegion(thisenv, barr, 0, result, buf);
+    }
+    return readBytes;
 }
 
 size_t R_WriteConnection(Rconnection con, void *buf, size_t n) {
-	return (size_t) unimplemented("R_WriteConnection");
+    JNIEnv *thisenv = getEnv();
+    jbyteArray barr = wrap(thisenv, buf, n);
+
+    jint result =  (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, writeConnMethodID, getFd(con), barr);
+    return result >= 0 ? (size_t) result : 0;
+}
+
+Rconnection R_GetConnection(SEXP sConn) {
+	if (!inherits(sConn, "connection")) {
+		error(_("invalid connection"));
+	}
+
+	int fd = asInteger(sConn);
+
+	JNIEnv *thisenv = getEnv();
+	jobject jRconn = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getConnMethodID, fd);
+
+	// query getConnectionClassString
+	jstring jConnClass = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getConnClassMethodID, jRconn);
+	const char *sConnClass;
+	if (jConnClass != 0) {
+		sConnClass = connStringToChars(thisenv, jConnClass);
+	}
+
+	// query getSummaryDescription
+	jstring jSummaryDesc = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getSummaryDescMethodID, jRconn);
+	char *sSummaryDesc;
+	if (jSummaryDesc != 0) {
+		sSummaryDesc = connStringToChars(thisenv, jSummaryDesc);
+	}
+
+	// query isSeekable()
+	jboolean seekable = (*thisenv)->CallBooleanMethod(thisenv, UpCallsRFFIObject, isSeekableMethodID, jRconn);
+
+	// query getOpenMode
+	jstring jOpenMode = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, getOpenModeMethodID, jRconn);
+	char *sOpenMode;
+	if (jOpenMode != 0) {
+		sOpenMode = connStringToChars(thisenv, jOpenMode);
+	}
+
+	Rconnection new = (Rconnection) malloc(sizeof(struct Rconn));
+	if (!new) {
+		error(_("allocation of file connection failed"));
+	}
+
+	init_con(new, sSummaryDesc, 0, sOpenMode);
+	free(sOpenMode);
+	new->class = sConnClass;
+	new->canseek = seekable;
+
+	/* The private field is forbidden to be used by any user. So we can use it to store the file descriptor. However, we should also use Rfileconn in future. */
+	new->private = (void *) malloc(sizeof(int));
+	if (!new->private) {
+		free(new);
+		error(_("allocation of file connection failed"));
+		/* for Solaris 12.5 */new = NULL;
+	}
+	setFd(new, fd);
+
+// TODO implement up-call functions and set them
+//    new->open = &file_open;
+//    new->close = &file_close;
+//    new->vfprintf = &file_vfprintf;
+//    new->fgetc_internal = &file_fgetc_internal;
+//    new->fgetc = &dummy_fgetc;
+//    new->seek = &file_seek;
+//    new->truncate = &file_truncate;
+//    new->fflush = &file_fflush;
+//    new->read = &file_read;
+//    new->write = &file_write;
+
+	return new;
 }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
index 4ec83f1392..47ffc6ef39 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
@@ -33,6 +33,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_initialize(JNIEnv *env, jcla
 	init_variables(env, initialValues);
 	init_dynload(env);
 	init_internals(env);
+	init_connections(env);
 	init_rmath(env);
 	init_random(env);
 	init_parse(env);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index cca2f64363..fbd3a26f1c 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -29,6 +29,7 @@
 #include <limits.h>
 #include <Rinternals.h>
 #include <setjmp.h>
+#include <Connections.h>
 
 #define VALIDATE_REFS 1
 
@@ -87,6 +88,7 @@ void init_random(JNIEnv *env);
 void init_parse(JNIEnv *env);
 void init_pcre(JNIEnv *env);
 void init_c(JNIEnv *env);
+void init_connections(JNIEnv *env);
 
 void setEmbedded(void);
 
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 a338ac2d2e..e98b5d7988 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
@@ -26,7 +26,10 @@ import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guarantee;
 import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf;
 import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented;
 
+import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -51,6 +54,8 @@ import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -1186,4 +1191,56 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return RASTUtils.createLanguageElement(expr);
     }
 
+    @Override
+    public int R_ReadConnection(int fd, byte[] buf) {
+
+        try (BaseRConnection fromIndex = RConnection.fromIndex(fd)) {
+            Arrays.fill(buf, (byte) 0);
+            return fromIndex.readBin(ByteBuffer.wrap(buf));
+        } catch (IOException e) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_READING_CONNECTION, e.getMessage());
+        }
+    }
+
+    @Override
+    public int R_WriteConnection(int fd, byte[] buf) {
+        try (BaseRConnection fromIndex = RConnection.fromIndex(fd)) {
+            Arrays.fill(buf, (byte) 0);
+            final ByteBuffer wrapped = ByteBuffer.wrap(buf);
+            fromIndex.writeBin(wrapped);
+            return wrapped.position();
+        } catch (IOException e) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.ERROR_WRITING_CONNECTION, e.getMessage());
+        }
+    }
+
+    @Override
+    public Object R_GetConnection(int fd) {
+        return RConnection.fromIndex(fd);
+    }
+
+    @Override
+    public String getSummaryDescription(Object x) {
+        BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class);
+        return conn.getSummaryDescription();
+    }
+
+    @Override
+    public String getConnectionClassString(Object x) {
+        BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class);
+        return conn.getConnectionClass().getPrintName();
+    }
+
+    @Override
+    public String getOpenModeString(Object x) {
+        BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class);
+        return conn.getOpenMode().toString();
+    }
+
+    @Override
+    public boolean isSeekable(Object x) {
+        BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class);
+        return conn.isSeekable();
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index d475cc1f9e..3cb37d4a25 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -63,6 +63,7 @@ public enum RFFIUpCallMethod {
     R_ExternalPtrProt("(object) : object"),
     R_ExternalPtrTag("(object) : object"),
     R_FindNamespace("(object) : object"),
+    R_GetConnection("(sint32) : object"),
     R_GlobalContext("() : object"),
     R_GlobalEnv("() : object"),
     R_HomeDir("() : object"),
@@ -72,10 +73,12 @@ public enum RFFIUpCallMethod {
     R_NewHashedEnv("(object, object) : object"),
     R_ParseVector("(object, sint32, object) : object"),
     R_PromiseExpr("(object) : object"),
+    R_ReadConnection("(sint32, object) : sint32"),
     R_SetExternalPtrAddr("(object, object) : void"),
     R_SetExternalPtrProt("(object, object) : void"),
     R_SetExternalPtrTag("(object, object) : void"),
     R_ToplevelExec("() : object"),
+    R_WriteConnection("(sint32, object) : sint32"),
     R_computeIdentical("(object, object, sint32) : sint32"),
     R_do_MAKE_CLASS("(string) : object"),
     R_getContextCall("(object) : object"),
@@ -146,6 +149,10 @@ public enum RFFIUpCallMethod {
     TAG("(object) : object"),
     TYPEOF("(object) : sint32"),
     VECTOR_ELT("(object, sint32) : object"),
+    getConnectionClassString("(object) : object"),
+    getOpenModeString("(object) : object"),
+    getSummaryDescription("(object) : object"),
+    isSeekable("(object) : object"),
     unif_rand("() : double");
 
     /**
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 2943d37a76..c5ec109c8c 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
@@ -741,4 +741,46 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.R_CHAR(x);
     }
 
+    @Override
+    public int R_ReadConnection(int fd, byte[] buf) {
+        RFFIUtils.traceUpCall("R_ReadConnection", fd, buf);
+        return delegate.R_ReadConnection(fd, buf);
+    }
+
+    @Override
+    public int R_WriteConnection(int fd, byte[] buf) {
+        RFFIUtils.traceUpCall("R_WriteConnection", fd, buf);
+        return delegate.R_WriteConnection(fd, buf);
+    }
+
+    @Override
+    public Object R_GetConnection(int fd) {
+        RFFIUtils.traceUpCall("R_GetConnection", fd);
+        return delegate.R_GetConnection(fd);
+    }
+
+    @Override
+    public String getSummaryDescription(Object x) {
+        RFFIUtils.traceUpCall("getSummaryDescription", x);
+        return delegate.getSummaryDescription(x);
+    }
+
+    @Override
+    public String getConnectionClassString(Object x) {
+        RFFIUtils.traceUpCall("getConnectionClassString", x);
+        return delegate.getConnectionClassString(x);
+    }
+
+    @Override
+    public String getOpenModeString(Object x) {
+        RFFIUtils.traceUpCall("getOpenModeString", x);
+        return delegate.getOpenModeString(x);
+    }
+
+    @Override
+    public boolean isSeekable(Object x) {
+        RFFIUtils.traceUpCall("isSeekable", x);
+        return delegate.isSeekable(x);
+    }
+
 }
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 1bd2e8efe2..14b6e3611b 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -254,4 +255,18 @@ public interface StdUpCallsRFFI {
 
     Object R_CHAR(Object x);
 
+    int R_ReadConnection(int fd, byte[] buf);
+
+    int R_WriteConnection(int fd, byte[] buf);
+
+    Object R_GetConnection(int fd);
+
+    String getSummaryDescription(Object x);
+
+    String getConnectionClassString(Object x);
+
+    String getOpenModeString(Object x);
+
+    boolean isSeekable(Object x);
+
 }
-- 
GitLab


From 9794943395cda33138567f4fdb5507b760840ea5 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Thu, 9 Mar 2017 12:52:45 +0100
Subject: [PATCH 112/402] Deriv builtin implementation

---
 .../truffle/r/library/stats/deriv/D.java      |  101 +
 .../truffle/r/library/stats/deriv/Deriv.java  |  703 +++++
 .../r/library/stats/deriv/DerivVisitor.java   |  408 +++
 .../foreign/CallAndExternalFunctions.java     |    7 +
 .../truffle/r/nodes/test/ExtBuiltinsList.java |    1 +
 .../test/ForwardedValuesAnalyserTest.java     |   30 +
 .../r/nodes/test/RBuiltinDiagnostics.java     |    5 +-
 .../truffle/r/nodes/builtin/CastBuilder.java  |    4 +
 .../casts/analysis/ForwardingStatus.java      |    4 +-
 .../com/oracle/truffle/r/runtime/RError.java  |    7 +-
 .../truffle/r/runtime/nodes/RCodeBuilder.java |    9 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 2534 ++++++++++++++++-
 .../r/test/builtins/TestBuiltin_D.java        |   40 +
 .../r/test/builtins/TestBuiltin_deriv.java    |  211 ++
 mx.fastr/copyrights/overrides                 |    2 +
 15 files changed, 4050 insertions(+), 16 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
new file mode 100644
index 0000000000..8180a40c81
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.stats.deriv;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
+
+public abstract class D extends RExternalBuiltinNode.Arg2 {
+
+    static {
+        Casts casts = new Casts(D.class);
+        casts.arg(0, "expr").mustBe(instanceOf(RExpression.class).or(instanceOf(RLanguage.class)).or(instanceOf(RSymbol.class)).or(numericValue()).or(complexValue()),
+                        RError.Message.INVALID_EXPRESSION_TYPE, typeName());
+        casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "variable must be a character string").shouldBe(size(1),
+                        RError.Message.ONLY_FIRST_VARIABLE_NAME).findFirst();
+    }
+
+    public static D create() {
+        return DNodeGen.create();
+    }
+
+    protected static boolean isConstant(Object expr) {
+        return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol);
+    }
+
+    @Specialization(guards = "isConstant(expr)")
+    @TruffleBoundary
+    protected Object doD(Object expr, String var) {
+        return doD(ConstantNode.create(expr), var);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object doD(RSymbol expr, String var) {
+        return doD(RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), var);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object doD(RLanguage expr, String var) {
+        return doD((RSyntaxElement) expr.getRep(), var);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object doD(RExpression expr, String var,
+                    @Cached("create()") D dNode) {
+        return dNode.execute(expr.getDataAt(0), var);
+    }
+
+    private static Object doD(RSyntaxElement elem, String var) {
+        RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var);
+        RSyntaxElement dExpr = vis.accept(elem);
+        dExpr = Deriv.addParens(dExpr);
+        return RASTUtils.createLanguageElement(dExpr);
+    }
+
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
new file mode 100644
index 0000000000..36aa408315
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
@@ -0,0 +1,703 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.stats.deriv;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.boxPrimitive;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthGte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lengthLte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.RRootNode;
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.function.FormalArguments;
+import com.oracle.truffle.r.nodes.function.RCallSpecialNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.REmpty;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
+
+//Transcribed from GnuR, library/stats/src/deriv.c
+
+public abstract class Deriv extends RExternalBuiltinNode {
+
+    static {
+        Casts casts = new Casts(Deriv.class);
+        casts.arg(1, "namevec").mustBe(stringValue()).asStringVector().mustBe(notEmpty(), RError.Message.INVALID_VARIABLE_NAMES);
+        casts.arg(2, "function.arg").mapIf(logicalValue(), chain(asLogicalVector()).with(findFirst().logicalElement()).with(map(toBoolean())).end()).mapIf(stringValue(), boxPrimitive());
+        casts.arg(3, "tag").defaultError(RError.Message.INVALID_VARIABLE_NAMES).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst().mustBe(lengthGte(1).and(lengthLte(60)));
+        casts.arg(4, "hessian").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
+    }
+
+    static final String LEFT_PAREN = "(";
+    static final String PLUS = "+";
+    static final String MINUS = "-";
+    static final String TIMES = "*";
+    static final String DIVIDE = "/";
+    static final String POWER = "^";
+    static final String LOG = "log";
+    static final String EXP = "exp";
+    static final String COS = "cos";
+    static final String SIN = "sin";
+    static final String TAN = "tan";
+    static final String COSH = "cosh";
+    static final String SINH = "sinh";
+    static final String TANH = "tanh";
+    static final String SQRT = "sqrt";
+    static final String PNORM = "pnorm";
+    static final String DNORM = "dnorm";
+    static final String ASIN = "asin";
+    static final String ACOS = "acos";
+    static final String ATAN = "atan";
+    static final String GAMMA = "gamma";
+    static final String LGAMMA = "lgamma";
+    static final String DIGAMMA = "digamma";
+    static final String TRIGAMMA = "trigamma";
+    static final String PSIGAMMA = "psigamma";
+
+    public static Deriv create() {
+        return DerivNodeGen.create();
+    }
+
+    public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5);
+
+    @Override
+    public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
+        checkLength(args, 5);
+        return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4));
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    protected static boolean isConstant(Object expr) {
+        return !(expr instanceof RLanguage || expr instanceof RExpression || expr instanceof RSymbol);
+    }
+
+    @Specialization(guards = "isConstant(expr)")
+    protected Object derive(VirtualFrame frame, Object expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return derive(frame, RDataFactory.createLanguage(ConstantNode.create(expr)), names, functionArg, tag, hessian);
+    }
+
+    @Specialization
+    protected Object derive(VirtualFrame frame, RSymbol expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return derive(frame, (RBaseNode) RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), names, functionArg, tag, hessian);
+    }
+
+    @Specialization
+    protected Object derive(VirtualFrame frame, RExpression expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian,
+                    @Cached("create()") Deriv derivNode) {
+        return derivNode.execute(frame, expr.getDataAt(0), names, functionArg, tag, hessian);
+    }
+
+    @Specialization
+    protected Object derive(VirtualFrame frame, RLanguage expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return derive(frame, expr.getRep(), names, functionArg, tag, hessian);
+    }
+
+    private Object derive(VirtualFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        LinkedList<RSyntaxNode> exprlist = new LinkedList<>();
+        int fIndex = findSubexpression(elem, exprlist, tag);
+
+        int nderiv = names.getLength();
+        int[] dIndex = new int[nderiv];
+        int[] d2Index = hessian ? new int[(nderiv * (1 + nderiv)) / 2] : null;
+        for (int i = 0, k = 0; i < nderiv; i++) {
+            RBaseNode dExpr = d(elem, names.getDataAt(i));
+            dIndex[i] = findSubexpression(dExpr, exprlist, tag);
+
+            if (hessian) {
+                for (int j = i; j < nderiv; j++) {
+                    RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
+                    d2Index[k] = findSubexpression(d2Expr, exprlist, tag);
+                    k++;
+                }
+            }
+        }
+
+        int nexpr = exprlist.size();
+
+        if (fIndex > 0) {
+            exprlist.add(ReadVariableNode.create(tag + fIndex));
+        } else {
+            exprlist.add(cloneElement(elem.asRSyntaxNode()));
+        }
+
+        exprlist.add(null);
+        if (hessian) {
+            exprlist.add(null);
+        }
+
+        for (int i = 0, k = 0; i < nderiv; i++) {
+            if (dIndex[i] > 0) {
+                exprlist.add(ReadVariableNode.create(tag + dIndex[i]));
+
+                if (hessian) {
+                    RBaseNode dExpr = d(elem, names.getDataAt(i));
+                    for (int j = i; j < nderiv; j++) {
+                        if (d2Index[k] > 0) {
+                            exprlist.add(ReadVariableNode.create(tag + d2Index[k]));
+                        } else {
+                            exprlist.add((RSyntaxNode) d(dExpr, names.getDataAt(j)));
+                        }
+                        k++;
+                    }
+                }
+
+            } else {
+                // the first derivative is constant or simple variable
+                // TODO: do not call the d twice
+                RBaseNode dExpr = d(elem, names.getDataAt(i));
+                exprlist.add((RSyntaxNode) dExpr);
+
+                if (hessian) {
+                    for (int j = i; j < nderiv; j++) {
+                        if (d2Index[k] > 0) {
+                            exprlist.add(ReadVariableNode.create(tag + d2Index[k]));
+                        } else {
+                            RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
+                            if (isZero((RSyntaxElement) d2Expr)) {
+                                exprlist.add(null);
+                            } else {
+                                exprlist.add((RSyntaxNode) d2Expr);
+                            }
+                        }
+                        k++;
+                    }
+                }
+            }
+        }
+
+        exprlist.add(null);
+        exprlist.add(null);
+        if (hessian) {
+            exprlist.add(null);
+        }
+
+        for (int i = 0; i < nexpr; i++) {
+            String subexprName = tag + (i + 1);
+            if (countOccurences(subexprName, exprlist, i + 1) < 2) {
+                replace(subexprName, exprlist.get(i), exprlist, i + 1);
+                exprlist.set(i, null);
+            } else {
+                exprlist.set(i, createAssignNode(subexprName, exprlist.get(i)));
+            }
+        }
+
+        int p = nexpr;
+        exprlist.set(p++, createAssignNode(".value", exprlist.get(nexpr))); // .value <-
+        exprlist.set(p++, createGrad(names)); // .grad <-
+        if (hessian) {
+            exprlist.set(p++, createHess(names)); // .hessian
+        }
+        // .grad[, "..."] <- ...
+        for (int i = 0; i < nderiv; i++) {
+            RSyntaxNode ans = exprlist.get(p);
+            exprlist.set(p, derivAssign(names.getDataAt(i), ans));
+            p++;
+
+            if (hessian) {
+                for (int j = i; j < nderiv; j++, p++) {
+                    ans = exprlist.get(p);
+                    if (ans != null) {
+                        if (i == j) {
+                            exprlist.set(p, hessAssign1(names.getDataAt(i), addParens(ans)));
+                        } else {
+                            exprlist.set(p, hessAssign2(names.getDataAt(i), names.getDataAt(j), addParens(ans)));
+                        }
+                    }
+                }
+            }
+
+        }
+        // attr(.value, "gradient") <- .grad
+        exprlist.set(p++, addGrad());
+        if (hessian) {
+            exprlist.set(p++, addHess());
+        }
+
+        // .value
+        exprlist.set(p++, ReadVariableNode.create(".value"));
+
+        // prune exprlist
+        exprlist.removeAll(Collections.singleton(null));
+
+        List<Argument<RSyntaxNode>> blockStatements = exprlist.stream().map(e -> RCodeBuilder.argument(e)).collect(Collectors.toList());
+        RSyntaxNode blockCall = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.create("{"), blockStatements);
+
+        if (functionArg instanceof RAbstractStringVector) {
+            RAbstractStringVector funArgNames = (RAbstractStringVector) functionArg;
+            List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
+            for (int i = 0; i < funArgNames.getLength(); i++) {
+                targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, funArgNames.getDataAt(i), ConstantNode.create(RMissing.instance)));
+            }
+
+            return createFunction(frame, blockCall, targetArgs);
+        } else if (functionArg == Boolean.TRUE) {
+            List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
+            for (int i = 0; i < names.getLength(); i++) {
+                targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, names.getDataAt(i), ConstantNode.create(RMissing.instance)));
+            }
+
+            return createFunction(frame, blockCall, targetArgs);
+        } else if (functionArg instanceof RFunction) {
+            RFunction funTemplate = (RFunction) functionArg;
+            FormalArguments formals = ((RRootNode) funTemplate.getRootNode()).getFormalArguments();
+            RNode[] defArgs = formals.getArguments();
+            List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
+            for (int i = 0; i < defArgs.length; i++) {
+                targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, formals.getSignature().getName(i), cloneElement((RSyntaxNode) defArgs[i])));
+            }
+
+            return createFunction(frame, blockCall, targetArgs);
+        } else {
+            RLanguage lan = RDataFactory.createLanguage(blockCall.asRNode());
+            RExpression res = RDataFactory.createExpression(new Object[]{lan});
+            return res;
+        }
+
+    }
+
+    private static RFunction createFunction(VirtualFrame frame, RSyntaxNode blockCall, List<Argument<RSyntaxNode>> targetArgs) {
+        RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
+        FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame);
+        return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame.materialize());
+    }
+
+    private int findSubexpression(RBaseNode expr, List<RSyntaxNode> exprlist, String tag) {
+        if (!(expr instanceof RSyntaxElement)) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+        }
+
+        RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() {
+            @Override
+            protected Integer visit(RSyntaxCall call) {
+                if (call.getSyntaxLHS() instanceof RSyntaxLookup && ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier() == LEFT_PAREN) {
+                    return accept(call.getSyntaxArguments()[0]);
+                }
+
+                RSyntaxElement[] args = call.getSyntaxArguments();
+                List<Argument<RSyntaxNode>> newArgs = new ArrayList<>();
+                for (int i = 0; i < args.length; i++) {
+                    int k = accept(args[i]);
+                    if (k > 0) {
+                        newArgs.add(RCodeBuilder.argument(ReadVariableNode.create(tag + k)));
+                    } else {
+                        newArgs.add(RCodeBuilder.argument(cloneElement(args[i])));
+                    }
+                }
+                RSyntaxNode newCall = RContext.getASTBuilder().call(call.getSourceSection(), cloneElement(call.getSyntaxLHS()), newArgs);
+                return accumulate(newCall, exprlist);
+            }
+
+            @Override
+            protected Integer visit(RSyntaxConstant element) {
+                return checkConstant(element.getValue());
+            }
+
+            @Override
+            protected Integer visit(RSyntaxLookup element) {
+                return 0;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxFunction element) {
+                throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+            }
+
+        };
+        return vis.accept((RSyntaxElement) expr);
+    }
+
+    private static int checkConstant(Object val) {
+        if (val instanceof Double || val instanceof Integer || val instanceof RComplex || val instanceof Byte || val instanceof RSymbol) {
+            return 0;
+        } else {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+        }
+    }
+
+    private static boolean isDoubleValue(RSyntaxElement elem, double value) {
+        if (elem instanceof RSyntaxConstant) {
+            Object val = ((RSyntaxConstant) elem).getValue();
+            if (val instanceof Number) {
+                return ((Number) val).doubleValue() == value;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    static boolean isZero(RSyntaxElement elem) {
+        return isDoubleValue(elem, 0.);
+    }
+
+    static boolean isOne(RSyntaxElement elem) {
+        return isDoubleValue(elem, 1.);
+    }
+
+    private int accumulate(RSyntaxElement expr, List<RSyntaxNode> exprlist) {
+        for (int k = 0; k < exprlist.size(); k++) {
+            if (equal(expr, exprlist.get(k))) {
+                return k + 1;
+            }
+        }
+        exprlist.add((RSyntaxNode) expr);
+        return exprlist.size();
+    }
+
+    // TODO: move to a utility class
+    private boolean equal(RSyntaxElement expr1, RSyntaxElement expr2) {
+        if (expr1.getClass() != expr2.getClass()) {
+            return false;
+        }
+        if (expr1 instanceof RSyntaxLookup) {
+            return ((RSyntaxLookup) expr1).getIdentifier() == ((RSyntaxLookup) expr2).getIdentifier();
+        }
+        if (expr1 instanceof RSyntaxConstant) {
+            return ((RSyntaxConstant) expr1).getValue().equals(((RSyntaxConstant) expr2).getValue());
+        }
+        if (expr1 instanceof RSyntaxCall) {
+            RSyntaxElement[] args1 = ((RSyntaxCall) expr1).getSyntaxArguments();
+            RSyntaxElement[] args2 = ((RSyntaxCall) expr2).getSyntaxArguments();
+            if (args1.length != args2.length) {
+                return false;
+            }
+            if (!equal(((RSyntaxCall) expr1).getSyntaxLHS(), ((RSyntaxCall) expr2).getSyntaxLHS())) {
+                return false;
+            }
+            for (int i = 0; i < args1.length; i++) {
+                if (!equal(args1[i], args2[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "equal");
+    }
+
+    static String getFunctionName(RSyntaxElement expr) {
+        if (expr instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) expr;
+            return call.getSyntaxLHS() instanceof RSyntaxLookup ? ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier() : null;
+        } else {
+            return null;
+        }
+    }
+
+    static RSyntaxNode cloneElement(RSyntaxElement element) {
+        return (RSyntaxNode) RASTUtils.cloneNode(((RBaseNode) element));
+    }
+
+    private static RBaseNode d(RBaseNode expr, String var) {
+        if (!(expr instanceof RSyntaxElement)) {
+            throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
+        }
+
+        RSyntaxVisitor<RSyntaxElement> vis = new DerivVisitor(var);
+        return (RBaseNode) vis.accept((RSyntaxElement) expr);
+    }
+
+    private static int argsLength(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxCall) {
+            return ((RSyntaxCall) elem).getSyntaxArguments().length;
+        } else {
+            return 0;
+        }
+    }
+
+    static RSyntaxElement arg(RSyntaxElement elem, int argIndex) {
+        assert elem instanceof RSyntaxCall && (argIndex < ((RSyntaxCall) elem).getSyntaxArguments().length);
+        return ((RSyntaxCall) elem).getSyntaxArguments()[argIndex];
+    }
+
+    private static RSyntaxElement setArg(RSyntaxElement elem, int argIndex, RSyntaxElement arg) {
+        assert elem instanceof RSyntaxCall && (argIndex < ((RSyntaxCall) elem).getSyntaxArguments().length);
+        RSyntaxCall call = (RSyntaxCall) elem;
+        RSyntaxElement[] args = call.getSyntaxArguments();
+        RSyntaxNode[] newArgs = new RSyntaxNode[args.length];
+        for (int i = 0; i < args.length; i++) {
+            if (i == argIndex) {
+                newArgs[i] = (RSyntaxNode) arg;
+            } else {
+                newArgs[i] = cloneElement(args[i]);
+            }
+        }
+        return RCallSpecialNode.createCall(call.getSourceSection(), (RNode) cloneElement(call.getSyntaxLHS()), ArgumentsSignature.empty(args.length), newArgs);
+    }
+
+    static RSyntaxNode newCall(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) {
+        if (arg2 == null) {
+            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1);
+        } else {
+            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1, (RSyntaxNode) arg2);
+        }
+    }
+
+    private static int countOccurences(String subexprName, List<RSyntaxNode> exprlist, int fromIndex) {
+        if (fromIndex >= exprlist.size()) {
+            return 0;
+        }
+
+        RSyntaxNode exprListNode = exprlist.get(fromIndex);
+        if (exprListNode == null) {
+            return countOccurences(subexprName, exprlist, fromIndex + 1);
+        }
+
+        RSyntaxVisitor<Integer> vis = new RSyntaxVisitor<Integer>() {
+            @Override
+            protected Integer visit(RSyntaxCall element) {
+                RSyntaxElement[] args = element.getSyntaxArguments();
+                int cnt = 0;
+                for (int i = 0; i < args.length; i++) {
+                    cnt += accept(args[i]);
+                }
+                return cnt;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxConstant element) {
+                return 0;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxLookup element) {
+                return subexprName.equals(element.getIdentifier()) ? 1 : 0;
+            }
+
+            @Override
+            protected Integer visit(RSyntaxFunction element) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        };
+
+        return vis.accept(exprListNode) + countOccurences(subexprName, exprlist, fromIndex + 1);
+    }
+
+    private static void replace(String subexprName, RSyntaxNode replacement, List<RSyntaxNode> exprlist, int fromIndex) {
+        if (fromIndex >= exprlist.size()) {
+            return;
+        }
+
+        RSyntaxElement exprListNode = exprlist.get(fromIndex);
+        if (exprListNode == null) {
+            replace(subexprName, replacement, exprlist, fromIndex + 1);
+            return;
+        }
+
+        RSyntaxVisitor<RSyntaxElement> vis = new RSyntaxVisitor<RSyntaxElement>() {
+
+            // TODO: do not create a new call node after the first replacement
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxCall call) {
+                RSyntaxElement[] args = call.getSyntaxArguments();
+                RSyntaxNode[] newArgs = new RSyntaxNode[args.length];
+                for (int i = 0; i < args.length; i++) {
+                    newArgs[i] = (RSyntaxNode) accept(args[i]);
+                }
+                return RCallSpecialNode.createCall(call.getSourceSection(), (RNode) call.getSyntaxLHS(), ArgumentsSignature.empty(args.length), newArgs);
+            }
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxConstant element) {
+                return element;
+            }
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxLookup element) {
+                return subexprName.equals(element.getIdentifier()) ? replacement : element;
+            }
+
+            @Override
+            protected RSyntaxElement visit(RSyntaxFunction element) {
+                throw RInternalError.shouldNotReachHere();
+            }
+
+        };
+
+        exprlist.set(fromIndex, (RSyntaxNode) vis.accept(exprListNode));
+
+        replace(subexprName, replacement, exprlist, fromIndex + 1);
+    }
+
+    private static RSyntaxNode createAssignNode(String varName, RSyntaxNode rhs) {
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(varName.intern()), addParens(rhs));
+    }
+
+    private static RSyntaxNode hessAssign1(String varName, RSyntaxNode rhs) {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(varName.intern()), ConstantNode.create(varName.intern()));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, rhs);
+    }
+
+    private static RSyntaxNode hessAssign2(String varName1, String varName2, RSyntaxNode rhs) {
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(varName1.intern()), ConstantNode.create(varName2.intern()));
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(varName2.intern()), ConstantNode.create(varName1.intern()));
+
+        RSyntaxNode tmp3 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp2, rhs);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp1, tmp3);
+    }
+
+    private static RSyntaxNode createGrad(RAbstractStringVector names) {
+        int n = names.getLength();
+        List<Argument<RSyntaxNode>> cArgs = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern())));
+        }
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs);
+        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1);
+
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value"));
+        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n));
+        ConstantNode data = ConstantNode.create(0.);
+
+        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".grad"), p);
+    }
+
+    private static RSyntaxNode createHess(RAbstractStringVector names) {
+        int n = names.getLength();
+        List<Argument<RSyntaxNode>> cArgs = new ArrayList<>();
+        for (int i = 0; i < n; i++) {
+            cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern())));
+        }
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs);
+        RSyntaxNode tmp1Clone = cloneElement(tmp1);
+        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1, tmp1Clone);
+
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value"));
+        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n), ConstantNode.create(n));
+        ConstantNode data = ConstantNode.create(0.);
+
+        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".hessian"), p);
+    }
+
+    private static RSyntaxNode derivAssign(String name, RSyntaxNode expr) {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".grad"), ConstantNode.create(REmpty.instance),
+                        ConstantNode.create(name.intern()));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, expr);
+    }
+
+    private static RSyntaxNode addGrad() {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("gradient"));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".grad"));
+    }
+
+    private static RSyntaxNode addHess() {
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("hessian"));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".hessian"));
+    }
+
+    private static boolean isForm(RSyntaxElement expr, String functionName) {
+        return argsLength(expr) == 2 && getFunctionName(expr) == functionName;
+    }
+
+    static RSyntaxNode addParens(RSyntaxElement node) {
+        RSyntaxElement expr = node;
+        if (node instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) node;
+            RSyntaxElement[] args = call.getSyntaxArguments();
+            RSyntaxNode[] newArgs = new RSyntaxNode[args.length];
+            for (int i = 0; i < args.length; i++) {
+                newArgs[i] = addParens(args[i]);
+            }
+            expr = RCallSpecialNode.createCall(call.getSourceSection(), (RNode) cloneElement(call.getSyntaxLHS()), ArgumentsSignature.empty(args.length), newArgs);
+        }
+
+        if (isForm(expr, PLUS)) {
+            if (isForm(arg(expr, 1), PLUS)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+        } else if (isForm(expr, MINUS)) {
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+        } else if (isForm(expr, TIMES)) {
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) ||
+                            isForm(arg(expr, 1), DIVIDE)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+            if (isForm(arg(expr, 0), MINUS) || isForm(arg(expr, 0), MINUS)) {
+                expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null));
+            }
+        } else if (isForm(expr, DIVIDE)) {
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) ||
+                            isForm(arg(expr, 1), DIVIDE)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+            if (isForm(arg(expr, 0), PLUS) || isForm(arg(expr, 0), MINUS)) {
+                expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null));
+            }
+        } else if (isForm(expr, POWER)) {
+            if (isForm(arg(expr, 0), POWER)) {
+                expr = setArg(expr, 0, newCall(LEFT_PAREN, arg(expr, 0), null));
+            }
+            if (isForm(arg(expr, 1), PLUS) || isForm(arg(expr, 1), MINUS) || isForm(arg(expr, 1), TIMES) ||
+                            isForm(arg(expr, 1), DIVIDE)) {
+                expr = setArg(expr, 1, newCall(LEFT_PAREN, arg(expr, 1), null));
+            }
+        }
+        return (RSyntaxNode) expr;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
new file mode 100644
index 0000000000..8dc3708ecd
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
@@ -0,0 +1,408 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.stats.deriv;
+
+import static com.oracle.truffle.r.library.stats.deriv.Deriv.*;
+
+import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.runtime.RDeparse;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
+
+//Transcribed from GnuR, library/stats/src/deriv.c
+
+public class DerivVisitor extends RSyntaxVisitor<RSyntaxElement> {
+
+    private final String var;
+
+    DerivVisitor(String var) {
+        this.var = var;
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxCall call) {
+        String functionName = getFunctionName(call);
+        assert Utils.isInterned(functionName);
+
+        RSyntaxElement arg0 = call.getSyntaxArguments()[0];
+        RSyntaxElement arg1 = call.getSyntaxArguments().length > 1 ? call.getSyntaxArguments()[1] : null;
+
+        if (functionName == LEFT_PAREN) {
+            return accept(arg0);
+        }
+
+        if (functionName == PLUS) {
+            if (call.getSyntaxArguments().length == 1) {
+                return accept(arg0);
+            } else {
+                return simplify(PLUS, accept(arg0), accept(arg1));
+            }
+        }
+
+        if (functionName == MINUS) {
+            if (call.getSyntaxArguments().length == 1) {
+                return simplify(MINUS, accept(arg0), null);
+            } else {
+                return simplify(MINUS, accept(arg0), accept(arg1));
+            }
+        }
+
+        if (functionName == TIMES) {
+            return simplify(PLUS, simplify(TIMES, accept(arg0), cloneElement(arg1)),
+                            simplify(TIMES, cloneElement(arg0), accept(arg1)));
+        }
+
+        if (functionName == DIVIDE) {
+            return simplify(MINUS,
+                            simplify(DIVIDE, accept(arg0), cloneElement(arg1)),
+                            simplify(DIVIDE,
+                                            simplify(TIMES, cloneElement(arg0), accept(arg1)),
+                                            simplify(POWER, cloneElement(arg1), ConstantNode.create(2.))));
+        }
+
+        if (functionName == POWER) {
+            if (isNumeric(arg1)) {
+                return simplify(TIMES,
+                                arg1,
+                                simplify(TIMES,
+                                                accept(arg0),
+                                                simplify(POWER, cloneElement(arg0), decDouble(arg1))));
+
+            } else {
+                // (a^b)' = a^(b-1).b.a' + a^b.log(a).b'
+                RSyntaxElement expr1 = simplify(TIMES,
+                                simplify(POWER,
+                                                arg0,
+                                                simplify(MINUS, cloneElement(arg1), ConstantNode.create(1.))),
+                                simplify(TIMES, cloneElement(arg1), accept(arg0)));
+
+                RSyntaxElement expr2 = simplify(TIMES,
+                                simplify(POWER, cloneElement(arg0), cloneElement(arg1)),
+                                simplify(TIMES,
+                                                simplify(LOG, cloneElement(arg0), null),
+                                                accept(arg1)));
+                return simplify(PLUS, expr1, expr2);
+            }
+        }
+
+        if (functionName == EXP) {
+            return simplify(TIMES, cloneElement(call), accept(arg0));
+        }
+
+        if (functionName == LOG) {
+            if (call.getSyntaxArguments().length != 1) {
+                throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "only single-argument calls are supported");
+            }
+            return simplify(DIVIDE, accept(arg0), cloneElement(arg0));
+        }
+
+        if (functionName == COS) {
+            return simplify(TIMES,
+                            simplify(SIN, cloneElement(arg0), null),
+                            simplify(MINUS, accept(arg0), null));
+        }
+
+        if (functionName == SIN) {
+            return simplify(TIMES,
+                            simplify(COS, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == TAN) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(POWER,
+                                            simplify(COS, cloneElement(arg0), null),
+                                            ConstantNode.create(2.)));
+        }
+
+        if (functionName == COSH) {
+            return simplify(TIMES,
+                            simplify(SINH, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == SINH) {
+            return simplify(TIMES,
+                            simplify(COSH, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == TANH) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(POWER,
+                                            simplify(COSH, cloneElement(arg0), null),
+                                            ConstantNode.create(2.)));
+        }
+
+        if (functionName == SQRT) {
+            return accept(simplify(POWER, cloneElement(arg0), ConstantNode.create(0.5)));
+        }
+
+        if (functionName == PNORM) {
+            return simplify(TIMES,
+                            simplify(DNORM, cloneElement(arg0), null),
+                            accept(arg0));
+        }
+
+        if (functionName == DNORM) {
+            return simplify(TIMES,
+                            simplify(MINUS, cloneElement(arg0), null),
+                            simplify(TIMES,
+                                            simplify(DNORM, cloneElement(arg0), null),
+                                            accept(arg0)));
+        }
+
+        if (functionName == ASIN) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(SQRT,
+                                            simplify(MINUS,
+                                                            ConstantNode.create(1.),
+                                                            simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))),
+                                            null));
+        }
+
+        if (functionName == ACOS) {
+            return simplify(MINUS,
+                            simplify(DIVIDE,
+                                            accept(arg0),
+                                            simplify(SQRT,
+                                                            simplify(MINUS,
+                                                                            ConstantNode.create(1.),
+                                                                            simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))),
+                                                            null)),
+                            null);
+        }
+
+        if (functionName == ATAN) {
+            return simplify(DIVIDE,
+                            accept(arg0),
+                            simplify(PLUS,
+                                            ConstantNode.create(1.),
+                                            simplify(POWER, cloneElement(arg0), ConstantNode.create(2.))));
+        }
+
+        if (functionName == LGAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(DIGAMMA, cloneElement(arg0), null));
+        }
+
+        if (functionName == GAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(TIMES, cloneElement(call),
+                                            simplify(DIGAMMA, cloneElement(arg0), null)));
+        }
+
+        if (functionName == DIGAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(TRIGAMMA, cloneElement(arg0), null));
+        }
+
+        if (functionName == TRIGAMMA) {
+            return simplify(TIMES,
+                            accept(arg0),
+                            simplify(PSIGAMMA, cloneElement(arg0), ConstantNode.create(2)));
+        }
+
+        if (functionName == PSIGAMMA) {
+            if (call.getSyntaxArguments().length == 1) {
+                return simplify(TIMES,
+                                accept(arg0),
+                                simplify(PSIGAMMA, cloneElement(arg0), ConstantNode.create(1)));
+            } else if (isIntegerOrDouble(arg1)) {
+                return simplify(TIMES,
+                                accept(arg0),
+                                simplify(PSIGAMMA, cloneElement(arg0), incInteger(arg1)));
+            } else {
+                return simplify(TIMES,
+                                accept(arg0),
+                                simplify(PSIGAMMA,
+                                                cloneElement(arg0),
+                                                simplify(PLUS, cloneElement(arg1), ConstantNode.create(1))));
+            }
+        }
+
+        throw RError.error(RError.SHOW_CALLER, RError.Message.NOT_IN_DERIVATIVE_TABLE, RDeparse.deparseSyntaxElement(call.getSyntaxLHS()));
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxConstant element) {
+        return ConstantNode.create(0.);
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxLookup element) {
+        double dVal = element.getIdentifier().equals(var) ? 1 : 0;
+        return ConstantNode.create(dVal);
+    }
+
+    @Override
+    protected RSyntaxElement visit(RSyntaxFunction element) {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    private RSyntaxElement simplify(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) {
+        if (functionName == PLUS) {
+            if (arg2 == null) {
+                return arg1;
+            } else if (isZero(arg1)) {
+                return arg2;
+            } else if (isZero(arg2)) {
+                return arg1;
+            } else if (isUminus(arg1)) {
+                return simplify(MINUS, arg2, arg(arg1, 0));
+            } else if (isUminus(arg2)) {
+                return simplify(MINUS, arg1, arg(arg2, 0));
+            } else {
+                return newCall(PLUS, arg1, arg2);
+            }
+        } else if (functionName == MINUS) {
+            if (arg2 == null) {
+                if (isZero(arg1)) {
+                    return ConstantNode.create(0.);
+                } else if (isUminus(arg1)) {
+                    return arg(arg1, 0);
+                } else {
+                    return newCall(MINUS, arg1, arg2);
+                }
+            } else {
+                if (isZero(arg2)) {
+                    return arg1;
+                } else if (isZero(arg1)) {
+                    return simplify(MINUS, arg2, null);
+                } else if (isUminus(arg1)) {
+                    return simplify(MINUS,
+                                    simplify(PLUS, arg(arg1, 0), arg2),
+                                    null);
+                } else if (isUminus(arg2)) {
+                    return simplify(PLUS, arg1, arg(arg2, 0));
+                } else {
+                    return newCall(MINUS, arg1, arg2);
+                }
+            }
+        } else if (functionName == TIMES) {
+            if (isZero(arg1) || isZero(arg2)) {
+                return ConstantNode.create(0.);
+            } else if (isOne(arg1)) {
+                return arg2;
+            } else if (isOne(arg2)) {
+                return arg1;
+            } else if (isUminus(arg1)) {
+                return simplify(MINUS, simplify(TIMES, arg(arg1, 0), arg2), null);
+            } else if (isUminus(arg2)) {
+                return simplify(MINUS, simplify(TIMES, arg1, arg(arg2, 0)), null);
+            } else {
+                return newCall(TIMES, arg1, arg2);
+            }
+        } else if (functionName == DIVIDE) {
+            if (isZero(arg1)) {
+                return ConstantNode.create(0.);
+            } else if (isZero(arg2)) {
+                return ConstantNode.create(RRuntime.DOUBLE_NA);
+            } else if (isOne(arg2)) {
+                return arg1;
+            } else if (isUminus(arg1)) {
+                return simplify(MINUS, simplify(DIVIDE, arg(arg1, 0), arg2), null);
+            } else if (isUminus(arg2)) {
+                return simplify(MINUS, simplify(DIVIDE, arg1, arg(arg2, 0)), null);
+            } else {
+                return newCall(DIVIDE, arg1, arg2);
+            }
+        } else if (functionName == POWER) {
+            if (isZero(arg2)) {
+                return ConstantNode.create(1.);
+            } else if (isZero(arg1)) {
+                return ConstantNode.create(0.);
+            } else if (isOne(arg1)) {
+                return ConstantNode.create(1.);
+            } else if (isOne(arg2)) {
+                return arg1;
+            } else {
+                return newCall(POWER, arg1, arg2);
+            }
+        } else if (functionName == EXP) {
+            // FIXME: simplify exp(lgamma( E )) = gamma( E )
+            return newCall(EXP, arg1, null);
+        } else if (functionName == LOG) {
+            // FIXME: simplify log(gamma( E )) = lgamma( E )
+            return newCall(LOG, arg1, null);
+        } else if (functionName == COS || functionName == SIN || functionName == TAN || functionName == COSH || functionName == SINH || functionName == TANH || functionName == SQRT ||
+                        functionName == PNORM || functionName == DNORM || functionName == ASIN || functionName == ACOS || functionName == ATAN || functionName == GAMMA || functionName == LGAMMA ||
+                        functionName == DIGAMMA || functionName == TRIGAMMA || functionName == PSIGAMMA) {
+            return newCall(functionName, arg1, arg2);
+        } else {
+            return ConstantNode.create(RRuntime.DOUBLE_NA);
+        }
+    }
+
+    private static boolean isIntegerOrDouble(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxConstant) {
+            Object val = ((RSyntaxConstant) elem).getValue();
+            return val instanceof Integer || val instanceof Double;
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean isUminus(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxCall && MINUS == getFunctionName(elem)) {
+            RSyntaxElement[] args = ((RSyntaxCall) elem).getSyntaxArguments();
+            switch (args.length) {
+                case 1:
+                    return true;
+                case 2:
+                    return false;
+                default:
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, "invalid form in unary minus check");
+            }
+        } else {
+            return false;
+        }
+    }
+
+    private static boolean isNumeric(RSyntaxElement elem) {
+        if (elem instanceof RSyntaxConstant) {
+            Object val = ((RSyntaxConstant) elem).getValue();
+            return val instanceof Integer || val instanceof Double || val instanceof Byte;
+        } else {
+            return false;
+        }
+    }
+
+    private static RSyntaxConstant decDouble(RSyntaxElement elem) {
+        assert elem instanceof RSyntaxConstant;
+        assert ((RSyntaxConstant) elem).getValue() instanceof Number;
+        Number n = (Number) ((RSyntaxConstant) elem).getValue();
+        return ConstantNode.create(n.doubleValue() - 1);
+    }
+
+    private static RSyntaxConstant incInteger(RSyntaxElement elem) {
+        assert elem instanceof RSyntaxConstant;
+        assert ((RSyntaxConstant) elem).getValue() instanceof Number;
+        Number n = (Number) ((RSyntaxConstant) elem).getValue();
+        return ConstantNode.create(n.intValue() + 1);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 037a66f6f7..ab28e791fd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -55,6 +55,8 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction3Node;
 import com.oracle.truffle.r.library.stats.SignrankFreeNode;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen;
+import com.oracle.truffle.r.library.stats.deriv.D;
+import com.oracle.truffle.r.library.stats.deriv.Deriv;
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodes;
 import com.oracle.truffle.r.library.stats.WilcoxFreeNode;
 import com.oracle.truffle.r.library.tools.C_ParseRdNodeGen;
@@ -744,6 +746,11 @@ public class CallAndExternalFunctions {
             switch (name) {
                 case "compcases":
                     return new CompleteCases();
+                // stats
+                case "doD":
+                    return D.create();
+                case "deriv":
+                    return Deriv.create();
                 // utils
                 case "countfields":
                     return CountFieldsNodeGen.create();
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
index 8b6d15fd21..98eb067b7a 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
@@ -101,6 +101,7 @@ public class ExtBuiltinsList {
                     com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getGenericNodeGen.class,
                     com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_nextMethodCallNodeGen.class,
                     com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_externalPtrPrototypeObjectNodeGen.class,
+                    com.oracle.truffle.r.library.stats.deriv.DerivNodeGen.class,
     };
 
     @SuppressWarnings("unchecked")
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
index 76fb3d0457..ccaa151114 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
@@ -22,6 +22,12 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -30,6 +36,7 @@ import org.junit.Test;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
@@ -42,6 +49,7 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapIfStep;
+import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.MapStep;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardedValuesAnalyser;
 import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.runtime.RType;
@@ -406,4 +414,26 @@ public class ForwardedValuesAnalyserTest {
         assertFalse(result.isStringForwarded());
         assertFalse(result.isMissingForwarded());
     }
+
+    @Test
+    public void testReturnIfWithTrueBranchChain() {
+        //@formatter:off
+        PipelineStep<?, ?> findFirstBoolean = new CoercionStep<>(RType.Logical, false).setNext(new FindFirstStep<>(null, Byte.class, null)).setNext(new MapStep<>(new MapByteToBoolean(false)));
+        PipelineStep<?, ?> firstStep = new MapIfStep<>(new RTypeFilter<>(RType.Logical), // the condition
+                        findFirstBoolean, null, true);
+        //@formatter:on
+
+        ForwardedValuesAnalyser fwdAn = new ForwardedValuesAnalyser();
+        ForwardingAnalysisResult result = fwdAn.analyse(firstStep);
+        // TODO: change it to the positive assertion when the selected mappers (such as
+        // MapByteToBoolean) are supported
+        assertFalse(result.isLogicalForwarded());
+        assertTrue(result.logicalForwarded.mapper instanceof MapByteToBoolean);
+        assertTrue(result.isDoubleForwarded());
+        assertTrue(result.isIntegerForwarded());
+        assertTrue(result.isNullForwarded());
+        assertTrue(result.isStringForwarded());
+        assertTrue(result.isMissingForwarded());
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index c4f1c1b102..2ab3ac955a 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -431,13 +431,14 @@ public class RBuiltinDiagnostics {
             print(1, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size());
             print(1, "");
 
-            printDeadSpecs();
-
             if (diagSuite.diagConfig.verbose) {
                 for (List<Type> uncoveredArgs : nonCoveredArgsSet) {
                     print(1, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList()));
                 }
             }
+            print(1, "");
+
+            printDeadSpecs();
         }
 
         private void printBuiltinHeader(int level) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index da3d7e2cda..61b20ae0af 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -426,6 +426,10 @@ public final class CastBuilder {
             return new NotNAStep<>(null, null);
         }
 
+        public static <T> PipelineStep<T, T> boxPrimitive() {
+            return new PipelineStep.BoxPrimitiveStep<>();
+        }
+
         public static NullFilter nullValue() {
             return NullFilter.INSTANCE;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java
index a59b7c0435..c8fb811228 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingStatus.java
@@ -39,7 +39,7 @@ public abstract class ForwardingStatus {
     };
     public static final ForwardingStatus FORWARDED = new Forwarded(null);
 
-    final Mapper<?, ?> mapper;
+    public final Mapper<?, ?> mapper;
     private final byte flag;
 
     protected ForwardingStatus(byte flag, Mapper<?, ?> mapper) {
@@ -97,7 +97,7 @@ public abstract class ForwardingStatus {
     }
 
     ForwardingStatus or(ForwardingStatus other) {
-        return fromFlag(or(this.flag, other.flag));
+        return fromFlag(or(this.flag, other.flag), this.mapper != null ? this.mapper : other.mapper);
     }
 
     ForwardingStatus not() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 12d944ccc0..a73c50c1f7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -847,7 +847,12 @@ public final class RError extends RuntimeException {
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
         TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"),
         INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded"),
-        INVALID_CHANNEL_OBJECT("invalid channel object type: %s");
+        INVALID_CHANNEL_OBJECT("invalid channel object type: %s"),
+        INVALID_TAG("invalid tag"),
+        INVALID_VARIABLE_NAMES("invalid variable names"),
+        INVALID_EXPRESSION("invalid expression in '%s'"),
+        INVALID_EXPRESSION_TYPE("expression must not be type '%s'"),
+        NOT_IN_DERIVATIVE_TABLE("Function '%s' is not in the derivatives table");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
index 45eb98dcea..50b52b7a7e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,4 +197,11 @@ public interface RCodeBuilder<T> {
     default T call(SourceSection source, T lhs, T argument1, T argument2, T argument3) {
         return call(source, lhs, Arrays.asList(argument(argument1), argument(argument2), argument(argument3)));
     }
+
+    /**
+     * Helper function: create a call with four unnamed arguments.
+     */
+    default T call(SourceSection source, T lhs, T argument1, T argument2, T argument3, T argument4) {
+        return call(source, lhs, Arrays.asList(argument(argument1), argument(argument2), argument(argument3), argument(argument4)));
+    }
 }
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 f263e95c09..5fc5fb2db8 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
@@ -143,6 +143,31 @@ Error in Conj(as.raw(12)) : non-numeric argument to function
 attr(,"foo")
 [1] "foo"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#(df <- D(1, "x"));df(0)
+[1] 0
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#(df <- D(expression(x^2*sin(x)), "x"));df(0)
+2 * x * sin(x) + x^2 * cos(x)
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#(df <- D(quote(x^2*sin(x)), "x"));df(0)
+2 * x * sin(x) + x^2 * cos(x)
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#g<-quote(x^2);(df <- D(g, "x"));df(0)
+2 * x
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#x<-1;(df <- D(x, "x"));df(0)
+[1] 0
+Error in df(0) : argument "df1" is missing, with no default
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Date2POSIXlt.testDate2POSIXlt1#
 #argv <- list(structure(c(14712, 14712), class = 'Date')); .Internal(Date2POSIXlt(argv[[1]]))
 [1] "2010-04-13 UTC" "2010-04-13 UTC"
@@ -4827,11 +4852,11 @@ numeric(0)
 #argv <- list(structure(list(sec = 0, min = 0L, hour = 0L, mday = 22:27, mon = 3L, year = 108L, wday = 2L, yday = 112L, isdst = -1L), .Names = c('sec', 'min', 'hour', 'mday', 'mon', 'year', 'wday', 'yday', 'isdst'), class = c('POSIXlt', 'POSIXt'), tzone = 'GMT'), 'GMT'); .Internal(as.POSIXct(argv[[1]], argv[[2]]))
 [1] 1208822400 1208908800 1208995200 1209081600 1209168000 1209254400
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#Output.MayIgnoreErrorContext#
 #.Internal(as.POSIXlt(, 1))
 Error in .Internal(as.POSIXlt(, 1)) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asPOSIXlt.testasPOSIXlt#Output.MayIgnoreErrorContext#
 #.Internal(as.POSIXlt(2, ))
 Error in .Internal(as.POSIXlt(2, )) : argument 2 is empty
 
@@ -9310,11 +9335,11 @@ Error in bitwOr(c(1, 2, 3, 4), c(3 + (0+3i))) :
 [25]   -33554432   -67108864  -134217728  -268435456  -536870912 -1073741824
 [31]          NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftL(, 1))}
 Error in .Internal(bitwiseShiftL(, 1)) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftL.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftL(200, ))}
 Error in .Internal(bitwiseShiftL(200, )) : argument 2 is empty
 
@@ -9357,11 +9382,11 @@ In bitwShiftL(c(3, 2, 4), c(3 + (0+3i))) :
 #{ bitwShiftL(c(8,4,2), NULL) }
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftR(, 1))}
 Error in .Internal(bitwiseShiftR(, 1)) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bitwiseShiftR.testBitwiseFunctions#Output.MayIgnoreErrorContext#
 #{ .Internal(bitwiseShiftR(200, ))}
 Error in .Internal(bitwiseShiftR(200, )) : argument 2 is empty
 
@@ -12944,15 +12969,15 @@ function() 42
 #{ x=1;class(x)<-"character"; x}
 [1] "1"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{`class<-`(, "foo") }
 Error in `class<-`(, "foo") : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{`class<-`(, ) }
 Error in `class<-`(, ) : argument 1 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{`class<-`(NULL, "first") }
 Error: attempt to set an attribute on NULL
 
@@ -13077,7 +13102,7 @@ Error in class(x) <- "array" :
 #{x<-c(2+3i,4+5i);class(x)<-"a";class(x)<-"complex";x;}
 [1] 2+3i 4+5i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_classassign.testUpdateClass#Output.MayIgnoreErrorContext#
 #{x=1; `class<-`(x, ) }
 Error in `class<-`(x, ) : argument 2 is empty
 
@@ -16782,6 +16807,2495 @@ invalid 'cutoff' value for 'deparse', using default
 #argv <- list(quote(utils::str), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "utils::str"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr2 + .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr2 + .expr1
+    .hessian[, "x", "x"] <- 1 + 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- x + 2 * (x - 1)
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr4 + .expr1 * (1 + 2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- x + 2 * (x - 1)
+    .expr6 <- 1 + 2
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr4 + .expr1 * .expr6
+    .hessian[, "x", "x"] <- .expr6 + .expr6
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)+(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- x + 1 + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1 + 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)+(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- x + 1 + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1 + 1
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)-(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- x + 1 - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1 - 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)-(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- x + 1 - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1 - 1
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ (x+1)/(x+2), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/.expr2 - .expr1/.expr2^2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Output.IgnoreWhitespace#
+#deriv(~ (x+1)/(x+2), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .expr5 <- .expr2^2
+    .expr8 <- 1/.expr5
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr2 - .expr1/.expr5
+    .hessian[, "x", "x"] <- -(.expr8 + (.expr8 - .expr1 * (2 *
+        .expr2)/.expr5^2))
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Ignored.OutputFormatting#
+#deriv(~ (x+1)^(x+2), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- x + 2
+    .expr3 <- .expr1^.expr2
+    .value <- .expr3
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr1^(.expr2 - 1) * .expr2 + .expr3 * log(.expr1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)+(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- -(x + 1) + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1 - 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)+(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- -(x + 1) + (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1 - 1
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)-(x+2), c("x"), hessian=FALSE)
+expression({
+    .value <- -(x + 1) - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(1 + 1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ -(x+1)-(x+2), c("x"), hessian=TRUE)
+expression({
+    .value <- -(x + 1) - (x + 2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- -(1 + 1)
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 1, c("x"), hessian=FALSE)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 1, c("x"), hessian=TRUE)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 2*x, c("x"), hessian=FALSE)
+expression({
+    .value <- 2 * x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ 2*x, c("x"), hessian=TRUE)
+expression({
+    .value <- 2 * x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#Ignored.OutputFormatting#
+#deriv(~ 2/x, c("x"), hessian=FALSE)
+expression({
+    .value <- 2/x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(2/x^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x+1, c("x"), hessian=FALSE)
+expression({
+    .value <- x + 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x+1, c("x"), hessian=TRUE)
+expression({
+    .value <- x + 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x, c("x"), hessian=FALSE)
+expression({
+    .value <- x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x, c("x"), hessian=TRUE)
+expression({
+    .value <- x
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x/2, c("x"), hessian=FALSE)
+expression({
+    .value <- x/2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x/2, c("x"), hessian=TRUE)
+expression({
+    .value <- x/2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/2
+    .hessian[, "x", "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x^2, c("x"), hessian=FALSE)
+expression({
+    .value <- x^2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#deriv(~ x^2, c("x"), hessian=TRUE)
+expression({
+    .value <- x^2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 2 * x
+    .hessian[, "x", "x"] <- 2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x
+[1,] 3
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x
+[1,] 3
+attr(,"hessian")
+, , x
+
+     x
+[1,] 2
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)*(x+2*(x-1)), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 6
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)+(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 3
+attr(,"gradient")
+     x
+[1,] 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)+(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 3
+attr(,"gradient")
+     x
+[1,] 2
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)-(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)-(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)/(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+        x
+[1,] 0.25
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)/(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+        x
+[1,] 0.25
+attr(,"hessian")
+, , x
+
+         x
+[1,] -0.25
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ (x+1)^(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)+(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)+(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)-(x+2), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x
+[1,] -2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ -(x+1)-(x+2), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x
+[1,] -2
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 1, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 1, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 2*x, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 2*x, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 2
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ 2/x, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] Inf
+attr(,"gradient")
+        x
+[1,] -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x+1, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x+1, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x/2, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] 0.5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x/2, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] 0.5
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x^2, c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions1#
+#df <- deriv(~ x^2, c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 2
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)*(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr2
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)*(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr2
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- y + 2 * (x - 1)
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr4 + .expr1 * 2
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr4 <- y + 2 * (x - 1)
+    .value <- .expr1 * .expr4
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr4 + .expr1 * 2
+    .hessian[, "x", "x"] <- 2 + 2
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)-(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .value <- x + 1 - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- -1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)-(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .value <- x + 1 - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- -1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)/(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1/.expr2
+    .grad[, "y"] <- -(.expr1/.expr2^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)/(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .expr5 <- .expr2^2
+    .value <- .expr1/.expr2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1/.expr2
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -(1/.expr5)
+    .grad[, "y"] <- -(.expr1/.expr5)
+    .hessian[, "y", "y"] <- .expr1 * (2 * .expr2)/.expr5^2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ (x+1)^(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .expr3 <- .expr1^.expr2
+    .value <- .expr3
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr1^(.expr2 - 1) * .expr2
+    .grad[, "y"] <- .expr3 * log(.expr1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x + 1
+    .expr2 <- y + 2
+    .expr3 <- .expr1^.expr2
+    .expr4 <- .expr2 - 1
+    .expr5 <- .expr1^.expr4
+    .expr11 <- log(.expr1)
+    .expr15 <- .expr3 * .expr11
+    .value <- .expr3
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr5 * .expr2
+    .hessian[, "x", "x"] <- .expr1^(.expr4 - 1) * .expr4 * .expr2
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr5 *
+        .expr11 * .expr2 + .expr5
+    .grad[, "y"] <- .expr15
+    .hessian[, "y", "y"] <- .expr15 * .expr11
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ -(x+1)+(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .value <- -(x + 1) + (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- -1
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ -(x+1)+(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .value <- -(x + 1) + (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- -1
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 0
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ -(x+1)-(y+2), c("x","y"), hessian=FALSE)
+expression({
+    .expr5 <- -1
+    .value <- -(x + 1) - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- .expr5
+    .grad[, "y"] <- .expr5
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ -(x+1)-(y+2), c("x","y"), hessian=TRUE)
+expression({
+    .expr5 <- -1
+    .value <- -(x + 1) - (y + 2)
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr5
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 0
+    .grad[, "y"] <- .expr5
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ 2*x*y, c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 2 * y
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ 2*x*y, c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 2 * y
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 2
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ 2/x*y, c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- 2/x
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- -(2/x^2 * y)
+    .grad[, "y"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ 2/x*y, c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- 2/x
+    .expr3 <- x^2
+    .expr4 <- 2/.expr3
+    .value <- .expr1 * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- -(.expr4 * y)
+    .hessian[, "x", "x"] <- 2 * (2 * x)/.expr3^2 * y
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -.expr4
+    .grad[, "y"] <- .expr1
+    .hessian[, "y", "y"] <- 0
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ x + y, c("x","y"), hessian=FALSE)
+expression({
+    .value <- x + y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ x + y, c("x","y"), hessian=TRUE)
+expression({
+    .value <- x + y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1
+    .grad[, "y"] <- 1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#deriv(~ x*y, c("x","y"), hessian=FALSE)
+expression({
+    .value <- x * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- y
+    .grad[, "y"] <- x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x*y, c("x","y"), hessian=TRUE)
+expression({
+    .value <- x * y
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- y
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- 1
+    .grad[, "y"] <- x
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x/y/2, c("x","y"), hessian=FALSE)
+expression({
+    .value <- x/y/2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- 1/y/2
+    .grad[, "y"] <- -(x/y^2/2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x/y/2, c("x","y"), hessian=TRUE)
+expression({
+    .expr5 <- y^2
+    .value <- x/y/2
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- 1/y/2
+    .hessian[, "x", "x"] <- 0
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- -(1/.expr5/2)
+    .grad[, "y"] <- -(x/.expr5/2)
+    .hessian[, "y", "y"] <- x * (2 * y)/.expr5^2/2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x^y, c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- x^y
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- x^(y - 1) * y
+    .grad[, "y"] <- .expr1 * log(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+#deriv(~ x^y, c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- x^y
+    .expr2 <- y - 1
+    .expr3 <- x^.expr2
+    .expr9 <- log(x)
+    .expr13 <- .expr1 * .expr9
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr3 * y
+    .hessian[, "x", "x"] <- x^(.expr2 - 1) * .expr2 * y
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr3 *
+        .expr9 * y + .expr3
+    .grad[, "y"] <- .expr13
+    .hessian[, "y", "y"] <- .expr13 * .expr9
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x y
+[1,] 2 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 2
+attr(,"gradient")
+     x y
+[1,] 2 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x y
+[1,] 0 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)*(y+2*(x-1)), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -2
+attr(,"gradient")
+     x y
+[1,] 0 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 4 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)-(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x  y
+[1,] 1 -1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)-(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -1
+attr(,"gradient")
+     x  y
+[1,] 1 -1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)/(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+       x     y
+[1,] 0.5 -0.25
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)/(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+       x     y
+[1,] 0.5 -0.25
+attr(,"hessian")
+, , x
+
+     x     y
+[1,] 0 -0.25
+
+, , y
+
+         x    y
+[1,] -0.25 0.25
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x y
+[1,] 2 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x y
+[1,] 2 0
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 2 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ (x+1)^(y+2), c("x","y"), hessian=TRUE); x<-1; y<-1; eval(df)
+[1] 8
+attr(,"gradient")
+      x        y
+[1,] 12 5.545177
+attr(,"hessian")
+, , x
+
+      x        y
+[1,] 12 12.31777
+
+, , y
+
+            x        y
+[1,] 12.31777 3.843624
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)+(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+      x y
+[1,] -1 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)+(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+      x y
+[1,] -1 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)-(y+2), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x  y
+[1,] -1 -1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ -(x+1)-(y+2), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -3
+attr(,"gradient")
+      x  y
+[1,] -1 -1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2*x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2*x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 2
+
+, , y
+
+     x y
+[1,] 2 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2/x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] NaN Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ 2/x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] NaN Inf
+attr(,"hessian")
+, , x
+
+       x    y
+[1,] NaN -Inf
+
+, , y
+
+        x y
+[1,] -Inf 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x + y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 1 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x + y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 1 1
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 0
+
+, , y
+
+     x y
+[1,] 0 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x*y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x*y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x y
+[1,] 0 0
+attr(,"hessian")
+, , x
+
+     x y
+[1,] 0 1
+
+, , y
+
+     x y
+[1,] 1 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x/y/2, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] Inf NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x/y/2, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x   y
+[1,] Inf NaN
+attr(,"hessian")
+, , x
+
+     x    y
+[1,] 0 -Inf
+
+, , y
+
+        x   y
+[1,] -Inf NaN
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x^y, c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+       x    y
+[1,] NaN -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
+#df <- deriv(~ x^y, c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] 1
+attr(,"gradient")
+       x    y
+[1,] NaN -Inf
+attr(,"hessian")
+, , x
+
+       x   y
+[1,] NaN NaN
+
+, , y
+
+       x   y
+[1,] NaN Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ acos(x), c("x"), hessian=FALSE)
+expression({
+    .value <- acos(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(1/sqrt(1 - x^2))
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ asin(x), c("x"), hessian=FALSE)
+expression({
+    .value <- asin(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/sqrt(1 - x^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ asin(x), c("x"), hessian=TRUE)
+expression({
+    .expr3 <- 1 - x^2
+    .expr4 <- sqrt(.expr3)
+    .value <- asin(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr4
+    .hessian[, "x", "x"] <- 0.5 * (2 * x * .expr3^-0.5)/.expr4^2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ atan(x), c("x"), hessian=FALSE)
+expression({
+    .value <- atan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/(1 + x^2)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ atan(x), c("x"), hessian=TRUE)
+expression({
+    .expr3 <- 1 + x^2
+    .value <- atan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr3
+    .hessian[, "x", "x"] <- -(2 * x/.expr3^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cos(x), c("x"), hessian=FALSE)
+expression({
+    .value <- cos(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -sin(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cos(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- cos(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- -sin(x)
+    .hessian[, "x", "x"] <- -.expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cosh(x), c("x"), hessian=FALSE)
+expression({
+    .value <- cosh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- sinh(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ cosh(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- cosh(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- sinh(x)
+    .hessian[, "x", "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ digamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- digamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- trigamma(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ dnorm(x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- dnorm(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- -(x * .expr1)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ exp(x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- exp(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ exp(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- exp(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr1
+    .hessian[, "x", "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ gamma(x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- gamma(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- .expr1 * digamma(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ lgamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- lgamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- digamma(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ log(x), c("x"), hessian=FALSE)
+expression({
+    .value <- log(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ log(x), c("x"), hessian=TRUE)
+expression({
+    .value <- log(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/x
+    .hessian[, "x", "x"] <- -(1/x^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ pnorm(x), c("x"), hessian=FALSE)
+expression({
+    .value <- pnorm(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- dnorm(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ pnorm(x), c("x"), hessian=TRUE)
+expression({
+    .expr2 <- dnorm(x)
+    .value <- pnorm(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr2
+    .hessian[, "x", "x"] <- -(x * .expr2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ psigamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- psigamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- psigamma(x, 1L)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sin(x), c("x"), hessian=FALSE)
+expression({
+    .value <- sin(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sin(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- sin(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- cos(x)
+    .hessian[, "x", "x"] <- -.expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sinh(x), c("x"), hessian=FALSE)
+expression({
+    .value <- sinh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- cosh(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sinh(x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- sinh(x)
+    .value <- .expr1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- cosh(x)
+    .hessian[, "x", "x"] <- .expr1
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sqrt(x), c("x"), hessian=FALSE)
+expression({
+    .value <- sqrt(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0.5 * x^-0.5
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ sqrt(x), c("x"), hessian=TRUE)
+expression({
+    .value <- sqrt(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 0.5 * x^-0.5
+    .hessian[, "x", "x"] <- 0.5 * (-0.5 * x^-1.5)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ tan(x), c("x"), hessian=FALSE)
+expression({
+    .value <- tan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/cos(x)^2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ tan(x), c("x"), hessian=TRUE)
+expression({
+    .expr2 <- cos(x)
+    .expr3 <- .expr2^2
+    .value <- tan(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr3
+    .hessian[, "x", "x"] <- 2 * (sin(x) * .expr2)/.expr3^2
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ tanh(x), c("x"), hessian=FALSE)
+expression({
+    .value <- tanh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 1/cosh(x)^2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.OutputFormatting#
+#deriv(~ tanh(x), c("x"), hessian=TRUE)
+expression({
+    .expr2 <- cosh(x)
+    .expr3 <- .expr2^2
+    .value <- tanh(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 1/.expr3
+    .hessian[, "x", "x"] <- -(2 * (sinh(x) * .expr2)/.expr3^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#deriv(~ trigamma(x), c("x"), hessian=FALSE)
+expression({
+    .value <- trigamma(x)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- psigamma(x, 2L)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ acos(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1.570796
+attr(,"gradient")
+      x
+[1,] -1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ asin(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ asin(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ atan(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ atan(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cos(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cos(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+      x
+[1,] -1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cosh(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ cosh(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 0
+attr(,"hessian")
+, , x
+
+     x
+[1,] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ digamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x
+[1,] Inf
+Warning message:
+In digamma(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ dnorm(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.3989423
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ exp(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ exp(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 1
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ gamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x
+[1,] NaN
+Warning messages:
+1: In gamma(x) : NaNs produced
+2: In digamma(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ lgamma(x), c("x"), hessian=FALSE); x<-0.5; eval(df)
+[1] 0.5723649
+attr(,"gradient")
+            x
+[1,] -1.96351
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ log(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.MissingWarning#
+#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<--1; eval(df)
+[1] NaN
+attr(,"gradient")
+      x
+[1,] -1
+attr(,"hessian")
+, , x
+
+      x
+[1,] -1
+
+Warning message:
+In log(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+        x
+[1,] -Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ log(x), c("x"), hessian=TRUE); x<-1; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+      x
+[1,] -1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ pnorm(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+             x
+[1,] 0.3989423
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ pnorm(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0.5
+attr(,"gradient")
+             x
+[1,] 0.3989423
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ psigamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] NaN
+attr(,"gradient")
+       x
+[1,] Inf
+Warning message:
+In psigamma(x) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sin(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sin(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sinh(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sinh(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sqrt(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ sqrt(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+        x
+[1,] -Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tan(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tan(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<--1; eval(df)
+[1] -0.7615942
+attr(,"gradient")
+             x
+[1,] 0.4199743
+attr(,"hessian")
+, , x
+
+          x
+[1,] 0.6397
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] 0
+attr(,"gradient")
+     x
+[1,] 1
+attr(,"hessian")
+, , x
+
+     x
+[1,] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
+#df <- deriv(~ tanh(x), c("x"), hessian=TRUE); x<-1; eval(df)
+[1] 0.7615942
+attr(,"gradient")
+             x
+[1,] 0.4199743
+attr(,"hessian")
+, , x
+
+           x
+[1,] -0.6397
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+#df <- deriv(~ trigamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] Inf
+attr(,"gradient")
+       x
+[1,] NaN
+Warning message:
+In psigamma(x, 2L) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#deriv(~ log(2*x), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .value <- log(.expr1)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2/.expr1
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Ignored.OutputFormatting#
+#deriv(~ log(2*x), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .value <- log(.expr1)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- 2/.expr1
+    .hessian[, "x", "x"] <- -(2 * 2/.expr1^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#deriv(~ log(sin(2*x)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .value <- log(.expr2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- cos(.expr1) * 2/.expr2
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace#
+#deriv(~ log(sin(2*x)), c("x"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .expr5 <- cos(.expr1) * 2
+    .value <- log(.expr2)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .hessian <- array(0, c(length(.value), 1L, 1L), list(NULL,
+        c("x"), c("x")))
+    .grad[, "x"] <- .expr5/.expr2
+    .hessian[, "x", "x"] <- -(.expr2 * 2 * 2/.expr2 + .expr5 *
+        .expr5/.expr2^2)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace#
+#deriv(~ log(sin(2*x)*cos(x^2)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .expr3 <- x^2
+    .expr4 <- cos(.expr3)
+    .expr5 <- .expr2 * .expr4
+    .value <- log(.expr5)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- (cos(.expr1) * 2 * .expr4 - .expr2 * (sin(.expr3) *
+        .expr1))/.expr5
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#Output.IgnoreWhitespace#
+#deriv(~ pnorm(sin(2*x)^log(x+1)), c("x"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr2 <- sin(.expr1)
+    .expr3 <- x + 1
+    .expr4 <- log(.expr3)
+    .expr5 <- .expr2^.expr4
+    .value <- pnorm(.expr5)
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- dnorm(.expr5) * (.expr2^(.expr4 - 1) * (.expr4 *
+        (cos(.expr1) * 2)) + .expr5 * (log(.expr2) * (1/.expr3)))
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(2*x), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(2*x), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+        x
+[1,] -Inf
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(sin(2*x)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(sin(2*x)), c("x"), hessian=TRUE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+attr(,"hessian")
+, , x
+
+       x
+[1,] NaN
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ log(sin(2*x)*cos(x^2)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x
+[1,] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctionsWithCompArg1#
+#df <- deriv(~ pnorm(sin(2*x)^log(x+1)), c("x"), hessian=FALSE); x<-0; eval(df)
+[1] 0.8413447
+attr(,"gradient")
+       x
+[1,] NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
+#(df <- deriv(~x^2*sin(x), "x", function.arg=TRUE));df(0)
+function (x)
+{
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+}
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
+#(df <- deriv(~x^2*sin(x), "x", function.arg=c("x")));df(0)
+function (x)
+{
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+}
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testFunctionGenereration#Output.IgnoreWhitespace#
+#(df <- deriv(~x^2*sin(x), "x", function.arg=function(x=1){}));df(0)
+function (x = 1)
+{
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+}
+[1] 0
+attr(,"gradient")
+     x
+[1,] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#Output.IgnoreWhitespace#
+#deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=FALSE)
+expression({
+    .expr1 <- 2 * x
+    .expr4 <- log(.expr1) + sin(x)
+    .expr5 <- y^x
+    .expr6 <- exp(x)
+    .expr7 <- .expr5 * .expr6
+    .expr8 <- cos(.expr7)
+    .expr9 <- .expr4 * .expr8
+    .expr11 <- x^y
+    .expr13 <- x + y + 1
+    .expr15 <- x * y + .expr11/.expr13
+    .expr21 <- sin(.expr7)
+    .expr35 <- .expr11/.expr13^2
+    .value <- .expr9 * .expr15
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .grad[, "x"] <- ((2/.expr1 + cos(x)) * .expr8 - .expr4 *
+        (.expr21 * (.expr5 * log(y) * .expr6 + .expr7))) * .expr15 +
+        .expr9 * (y + (x^(y - 1) * y/.expr13 - .expr35))
+    .grad[, "y"] <- .expr9 * (x + (.expr11 * log(x)/.expr13 -
+        .expr35)) - .expr4 * (.expr21 * (y^(x - 1) * x * .expr6)) *
+        .expr15
+    attr(.value, "gradient") <- .grad
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#Ignored.OutputFormatting#
+#deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=TRUE)
+expression({
+    .expr1 <- 2 * x
+    .expr3 <- sin(x)
+    .expr4 <- log(.expr1) + .expr3
+    .expr5 <- y^x
+    .expr6 <- exp(x)
+    .expr7 <- .expr5 * .expr6
+    .expr8 <- cos(.expr7)
+    .expr9 <- .expr4 * .expr8
+    .expr11 <- x^y
+    .expr13 <- x + y + 1
+    .expr15 <- x * y + .expr11/.expr13
+    .expr19 <- 2/.expr1 + cos(x)
+    .expr21 <- sin(.expr7)
+    .expr22 <- log(y)
+    .expr23 <- .expr5 * .expr22
+    .expr24 <- .expr23 * .expr6
+    .expr25 <- .expr24 + .expr7
+    .expr26 <- .expr21 * .expr25
+    .expr28 <- .expr19 * .expr8 - .expr4 * .expr26
+    .expr30 <- y - 1
+    .expr31 <- x^.expr30
+    .expr32 <- .expr31 * y
+    .expr34 <- .expr13^2
+    .expr35 <- .expr11/.expr34
+    .expr37 <- y + (.expr32/.expr13 - .expr35)
+    .expr40 <- .expr28 * .expr37
+    .expr41 <- .expr19 * .expr26
+    .expr66 <- .expr32/.expr34
+    .expr71 <- .expr11 * (2 * .expr13)/.expr34^2
+    .expr77 <- log(x)
+    .expr78 <- .expr11 * .expr77
+    .expr81 <- x + (.expr78/.expr13 - .expr35)
+    .expr83 <- x - 1
+    .expr85 <- y^.expr83 * x
+    .expr86 <- .expr85 * .expr6
+    .expr87 <- .expr21 * .expr86
+    .expr89 <- .expr8 * .expr86
+    .expr108 <- .expr78/.expr34
+    .expr109 <- .expr108 - .expr71
+    .expr113 <- .expr4 * .expr87
+    .expr125 <- .expr113 * .expr81
+    .value <- .expr9 * .expr15
+    .grad <- array(0, c(length(.value), 2L), list(NULL, c("x",
+        "y")))
+    .hessian <- array(0, c(length(.value), 2L, 2L), list(NULL,
+        c("x", "y"), c("x", "y")))
+    .grad[, "x"] <- .expr28 * .expr15 + .expr9 * .expr37
+    .hessian[, "x", "x"] <- .expr40 - (.expr41 + (.expr3 + 2 *
+        2/.expr1^2) * .expr8 + (.expr41 + .expr4 * (.expr8 *
+        .expr25 * .expr25 + .expr21 * (.expr23 * .expr22 * .expr6 +
+        .expr24 + .expr25)))) * .expr15 + (.expr40 + .expr9 *
+        (x^(.expr30 - 1) * .expr30 * y/.expr13 - .expr66 - (.expr66 -
+            .expr71)))
+    .hessian[, "x", "y"] <- .hessian[, "y", "x"] <- .expr28 *
+        .expr81 - (.expr19 * .expr87 + .expr4 * (.expr89 * .expr25 +
+        .expr21 * ((.expr85 * .expr22 + .expr5 * (1/y)) * .expr6 +
+            .expr86))) * .expr15 + (.expr9 * (1 + ((.expr31 *
+        .expr77 * y + .expr31)/.expr13 - .expr66 - .expr109)) -
+        .expr113 * .expr37)
+    .grad[, "y"] <- .expr9 * .expr81 - .expr113 * .expr15
+    .hessian[, "y", "y"] <- .expr9 * (.expr78 * .expr77/.expr13 -
+        .expr108 - .expr109) - .expr125 - (.expr4 * (.expr89 *
+        .expr86 + .expr21 * (y^(.expr83 - 1) * .expr83 * x *
+        .expr6)) * .expr15 + .expr125)
+    attr(.value, "gradient") <- .grad
+    attr(.value, "hessian") <- .hessian
+    .value
+})
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#
+#df <- deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=FALSE); x<-0; y<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x   y
+[1,] NaN NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testLongExpression#
+#df <- deriv(~ (log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1)), c("x","y"), hessian=TRUE); x<-0; y<-0; eval(df)
+[1] -Inf
+attr(,"gradient")
+       x   y
+[1,] NaN NaN
+attr(,"hessian")
+, , x
+
+       x   y
+[1,] NaN NaN
+
+, , y
+
+       x   y
+[1,] NaN NaN
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#(df <- deriv(1, "x"));df(0)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#(df <- deriv(expression(x^2*sin(x)), "x"));df(0)
+expression({
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#(df <- deriv(quote(x^2*sin(x)), "x"));df(0)
+expression({
+    .expr1 <- x^2
+    .expr2 <- sin(x)
+    .value <- .expr1 * .expr2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x * .expr2 + .expr1 * cos(x)
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#g<-quote(x^2);(df <- deriv(g, "x"));df(0)
+expression({
+    .value <- x^2
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 2 * x
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testUnusualExprs#
+#x<-1;(df <- deriv(x, "x"));df(0)
+expression({
+    .value <- 1
+    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
+    .grad[, "x"] <- 0
+    attr(.value, "gradient") <- .grad
+    .value
+})
+Error in df(0) : argument "df1" is missing, with no default
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_det.testDet#
 #{ det(matrix(c(1,-3,4,-5),nrow=2)) }
 [1] 7
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
new file mode 100644
index 0000000000..6fd2878571
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestBuiltin_D extends TestBase {
+
+    @Test
+    public void testD() {
+        assertEval("(df <- D(expression(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("(df <- D(quote(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("g<-quote(x^2);(df <- D(g, \"x\"));df(0)");
+        assertEval("(df <- D(1, \"x\"));df(0)");
+        assertEval("x<-1;(df <- D(x, \"x\"));df(0)");
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
new file mode 100644
index 0000000000..13eae8aaf3
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestTrait;
+
+public class TestBuiltin_deriv extends TestBase {
+
+    final class DerivExpr {
+        final String expr;
+        final String assertedExpr;
+        final int dn;
+        final boolean hessian;
+
+        DerivExpr(String expr, int dn) {
+            this(expr, dn, false);
+        }
+
+        DerivExpr(String expr, int dn, boolean hessian) {
+            this.expr = expr;
+            this.dn = dn;
+            this.hessian = hessian;
+            String vars = dn == 1 ? "c(\"x\")" : "c(\"x\",\"y\")";
+            String h = hessian ? "TRUE" : "FALSE";
+            this.assertedExpr = "deriv(~ " + expr + ", " + vars + ", hessian=" + h + ")";
+        }
+
+        DerivEval derive() {
+            assertEval(assertedExpr);
+            return new DerivEval(this);
+        }
+
+        DerivEval derive(TestTrait trait) {
+            assertEval(trait, assertedExpr);
+            return new DerivEval(this);
+        }
+    }
+
+    final class DerivEval {
+        final DerivExpr de;
+        final String assertedExpr;
+
+        DerivEval(DerivExpr de) {
+            this.de = de;
+            String vars = de.dn == 1 ? "x<-%s" : "x<-%s; y<-%s";
+            this.assertedExpr = "df <- " + de.assertedExpr + "; " + vars + "; eval(df)";
+        }
+
+        DerivEval eval(Object... vals) {
+            String ex = String.format(this.assertedExpr, vals);
+            assertEval(ex);
+            return this;
+        }
+
+        DerivEval eval(TestTrait trait, Object... vals) {
+            String ex = String.format(this.assertedExpr, vals);
+            assertEval(trait, ex);
+            return this;
+        }
+
+        DerivExpr withHessian() {
+            return new DerivExpr(de.expr, de.dn, true);
+        }
+    }
+
+    private DerivExpr deriv1(String expr) {
+        return new DerivExpr(expr, 1);
+    }
+
+    private DerivExpr deriv2(String expr) {
+        return new DerivExpr(expr, 2);
+    }
+
+    private void assertDerivAndEval1(String expr) {
+        deriv1(expr).derive().eval(0).withHessian().derive().eval(0);
+    }
+
+    private void assertDerivAndEval1(TestTrait trait, String expr) {
+        deriv1(expr).derive(trait).eval(0, 0);
+    }
+
+    private DerivEval assertDeriv1(String expr) {
+        return deriv1(expr).derive();
+    }
+
+    private void assertDerivAndEval2(String expr) {
+        deriv2(expr).derive().eval(0, 0).withHessian().derive().eval(0, 0);
+    }
+
+    @Test
+    public void testDeriveBasicExpressions1() {
+        assertDerivAndEval1("1");
+        assertDerivAndEval1("x");
+        assertDerivAndEval1("x+1");
+        assertDerivAndEval1("2*x");
+        assertDerivAndEval1("x/2");
+        assertDerivAndEval1(Ignored.OutputFormatting, "2/x");
+        assertDerivAndEval1("x^2");
+        assertDerivAndEval1("(x+1)+(x+2)");
+        assertDerivAndEval1("(x+1)-(x+2)");
+        assertDerivAndEval1("-(x+1)+(x+2)");
+        assertDerivAndEval1("-(x+1)-(x+2)");
+        assertDerivAndEval1("(x+1)*(x+2)");
+        deriv1("(x+1)/(x+2)").derive().eval(0).withHessian().derive(Output.IgnoreWhitespace).eval(0);
+        assertDerivAndEval1("(x+1)*(x+2*(x-1))");
+        assertDerivAndEval1(Ignored.OutputFormatting, "(x+1)^(x+2)");
+    }
+
+    @Test
+    public void testDeriveFunctions1() {
+        deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(Ignored.MissingWarning,
+                        -1);
+        assertDerivAndEval1("exp(x)");
+        assertDerivAndEval1("cos(x)");
+        assertDerivAndEval1("sin(x)");
+        assertDerivAndEval1("tan(x)");
+        assertDerivAndEval1("cosh(x)");
+        assertDerivAndEval1("sinh(x)");
+        deriv1("tanh(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(-1);
+        assertDerivAndEval1("sqrt(x)");
+        deriv1("pnorm(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
+        assertDerivAndEval1(Ignored.OutputFormatting, "dnorm(x)");
+        assertDerivAndEval1("asin(x)");
+        assertDerivAndEval1(Ignored.OutputFormatting, "acos(x)");
+        deriv1("atan(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
+        assertDeriv1("gamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("lgamma(x)").eval(0.5);
+        assertDeriv1("digamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("trigamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("psigamma(x)").eval(Ignored.Unimplemented, 0);
+    }
+
+    @Test
+    public void testDeriveFunctionsWithCompArg1() {
+        deriv1("log(2*x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
+        deriv1("log(sin(2*x))").derive().eval(0).withHessian().derive(Output.IgnoreWhitespace).eval(0);
+        assertDerivAndEval1(Output.IgnoreWhitespace, "log(sin(2*x)*cos(x^2))");
+        assertDerivAndEval1(Output.IgnoreWhitespace, "pnorm(sin(2*x)^log(x+1))");
+    }
+
+    @Test
+    public void testDeriveBasicExpressions2() {
+        assertDerivAndEval2("x + y");
+        deriv2("x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("2*x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("x/y/2").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("2/x*y").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("x^y").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)*(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0);
+        assertDerivAndEval2("(x+1)-(y+2)");
+        deriv2("-(x+1)+(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0);
+        deriv2("-(x+1)-(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0);
+        deriv2("(x+1)/(y+2)").derive(Ignored.OutputFormatting).eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)*(y+2*(x-1))").derive().eval(0,
+                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)^(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
+                        0).eval(1, 1);
+    }
+
+    @Test
+    public void testLongExpression() {
+        deriv2("(log(2*x)+sin(x))*cos(y^x*(exp(x)))*(x*y+x^y/(x+y+1))").derive(Output.IgnoreWhitespace).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+    }
+
+    @Test
+    public void testFunctionGenereration() {
+        assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=TRUE));df(0)");
+        assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=c(\"x\")));df(0)");
+        assertEval(Output.IgnoreWhitespace, "(df <- deriv(~x^2*sin(x), \"x\", function.arg=function(x=1){}));df(0)");
+    }
+
+    @Test
+    public void testUnusualExprs() {
+        assertEval("(df <- deriv(expression(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("(df <- deriv(quote(x^2*sin(x)), \"x\"));df(0)");
+        assertEval("g<-quote(x^2);(df <- deriv(g, \"x\"));df(0)");
+        assertEval("(df <- deriv(1, \"x\"));df(0)");
+        assertEval("x<-1;(df <- deriv(x, \"x\"));df(0)");
+    }
+
+}
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 9ace1ab1d3..f6786e5110 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -764,3 +764,5 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
-- 
GitLab


From c00d0c0550b354a241c4c9988581bf73b644e211 Mon Sep 17 00:00:00 2001
From: Martin Entlicher <martin.entlicher@oracle.com>
Date: Thu, 9 Mar 2017 15:28:01 +0100
Subject: [PATCH 113/402] [GR-2975] Mark platform sources as internal.

---
 .../r/nodes/builtin/RBuiltinPackages.java     |  2 +-
 .../builtin/base/ConnectionFunctions.java     |  2 +-
 .../truffle/r/nodes/builtin/base/Parse.java   | 19 ++++++++++++-------
 .../oracle/truffle/r/runtime/RProfile.java    | 10 +++++-----
 .../com/oracle/truffle/r/runtime/RSource.java | 16 ++++++++++++----
 .../r/runtime/conn/ConnectionSupport.java     |  7 +++++++
 .../r/runtime/conn/FileConnections.java       |  9 ++++++++-
 7 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
index 8b13bea09c..13a04235fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
@@ -96,7 +96,7 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         Path basePathbase = baseDirPath.resolve("R").resolve("base");
         Source baseSource = null;
         try {
-            baseSource = RSource.fromFileName(basePathbase.toString());
+            baseSource = RSource.fromFileName(basePathbase.toString(), true);
         } catch (IOException ex) {
             Utils.rSuicide(String.format("unable to open the base package %s", basePathbase));
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 064c0481a1..333055b1fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -263,7 +263,7 @@ public abstract class ConnectionFunctions {
                 }
             }
             try {
-                return new FileRConnection(description, path, open, blocking, encoding, raw).asVector();
+                return new FileRConnection(description, path, open, blocking, encoding, raw, true).asVector();
             } catch (IOException ex) {
                 warning(RError.Message.CANNOT_OPEN_FILE, description, ex.getMessage());
                 throw error(RError.Message.CANNOT_OPEN_CONNECTION);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index 8ecb53980e..78f3f3d6cd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -193,7 +193,7 @@ public abstract class Parse extends RBuiltinNode {
                 } else {
                     path = fileName;
                 }
-                Source result = createFileSource(path, coalescedLines);
+                Source result = createFileSource(path, coalescedLines, false);
                 assert result != null : "Source created from environment should not be null";
                 return result;
             } else {
@@ -204,23 +204,28 @@ public abstract class Parse extends RBuiltinNode {
             if (srcFileText.equals("<text>")) {
                 return Source.newBuilder(coalescedLines).name("<parse>").mimeType(RRuntime.R_APP_MIME).build();
             } else {
-                return createFileSource(ConnectionSupport.removeFileURLPrefix(srcFileText), coalescedLines);
+                return createFileSource(ConnectionSupport.removeFileURLPrefix(srcFileText), coalescedLines, false);
             }
         }
     }
 
     private static Source createSource(RConnection conn, String coalescedLines) {
         // TODO check if file
-        String path = ConnectionSupport.getBaseConnection(conn).getSummaryDescription();
-        return createFileSource(path, coalescedLines);
+        ConnectionSupport.BaseRConnection bconn = ConnectionSupport.getBaseConnection(conn);
+        String path = bconn.getSummaryDescription();
+        return createFileSource(path, coalescedLines, bconn.isInternal());
     }
 
-    private static Source createFileSource(String path, String chars) {
+    private static Source createFileSource(String path, String chars, boolean internal) {
         try {
-            return RSource.fromFileName(chars, path);
+            return RSource.fromFileName(chars, path, internal);
         } catch (URISyntaxException e) {
             // Note: to be compatible with GnuR we construct Source even with a malformed path
-            return Source.newBuilder(chars).name(path).mimeType(RRuntime.R_APP_MIME).build();
+            Source.Builder<RuntimeException, RuntimeException, RuntimeException> builder = Source.newBuilder(chars).name(path).mimeType(RRuntime.R_APP_MIME);
+            if (internal) {
+                builder.internal();
+            }
+            return builder.build();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
index acd5193d57..50d4e6c01a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
@@ -60,7 +60,7 @@ public final class RProfile implements RContext.ContextState {
             }
             File siteProfileFile = new File(siteProfilePath);
             if (siteProfileFile.exists()) {
-                newSiteProfile = getProfile(siteProfilePath);
+                newSiteProfile = getProfile(siteProfilePath, false);
             }
         }
 
@@ -78,7 +78,7 @@ public final class RProfile implements RContext.ContextState {
             if (userProfilePath != null) {
                 File userProfileFile = new File(userProfilePath);
                 if (userProfileFile.exists()) {
-                    newUserProfile = getProfile(userProfilePath);
+                    newUserProfile = getProfile(userProfilePath, false);
                 }
             }
         }
@@ -92,7 +92,7 @@ public final class RProfile implements RContext.ContextState {
 
     public static Source systemProfile() {
         Path path = FileSystems.getDefault().getPath(REnvVars.rHome(), "library", "base", "R", "Rprofile");
-        Source source = getProfile(path.toString());
+        Source source = getProfile(path.toString(), true);
         if (source == null) {
             Utils.rSuicide("can't find system profile");
         }
@@ -107,9 +107,9 @@ public final class RProfile implements RContext.ContextState {
         return userProfile;
     }
 
-    private static Source getProfile(String path) {
+    private static Source getProfile(String path, boolean internal) {
         try {
-            return RSource.fromFileName(path);
+            return RSource.fromFileName(path, internal);
         } catch (IOException ex) {
             // GnuR does not report an error, just ignores
             return null;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
index 31938c37b5..5f6462db6d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
@@ -90,10 +90,14 @@ public class RSource {
      * Create an (external) source from the {@code text} that is known to originate from the file
      * system path {@code path}. The simulates the behavior of {@link #fromFile}.
      */
-    public static Source fromFileName(String text, String path) throws URISyntaxException {
+    public static Source fromFileName(String text, String path, boolean internal) throws URISyntaxException {
         File file = new File(path).getAbsoluteFile();
         URI uri = new URI("file://" + file.getAbsolutePath());
-        return Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME).build();
+        Source.Builder<RuntimeException, RuntimeException, RuntimeException> builder = Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME);
+        if (internal) {
+            builder.internal();
+        }
+        return builder.build();
     }
 
     /**
@@ -137,8 +141,12 @@ public class RSource {
     /**
      * Create an (external) source from the file system path {@code path}.
      */
-    public static Source fromFileName(String path) throws IOException {
-        return Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME).build();
+    public static Source fromFileName(String path, boolean internal) throws IOException {
+        Source.Builder<IOException, RuntimeException, RuntimeException> builder = Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME);
+        if (internal) {
+            builder.internal();
+        }
+        return builder.build();
     }
 
     /**
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 356a823105..46a93b40dc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -881,6 +881,13 @@ public class ConnectionSupport {
             return descriptor;
         }
 
+        /**
+         * Determines if the sources created by this connection are marked as internal.
+         */
+        public boolean isInternal() {
+            return false;
+        }
+
         public OpenMode getOpenMode() {
             return openMode;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 1f009cd7a9..7aa052f920 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -64,10 +64,12 @@ public class FileConnections {
      */
     public static class FileRConnection extends BasePathRConnection {
         private final boolean raw;
+        private final boolean internal;
 
-        public FileRConnection(String description, String path, String modeString, boolean blocking, String encoding, boolean raw) throws IOException {
+        public FileRConnection(String description, String path, String modeString, boolean blocking, String encoding, boolean raw, boolean internal) throws IOException {
             super(description, checkTemp(path), ConnectionClass.File, modeString, blocking, encoding);
             this.raw = raw;
+            this.internal = internal;
             openNonLazyConnection();
         }
 
@@ -79,6 +81,11 @@ public class FileConnections {
             }
         }
 
+        @Override
+        public boolean isInternal() {
+            return internal;
+        }
+
         @Override
         protected void createDelegateConnection() throws IOException {
 
-- 
GitLab


From 2f7e9d379d2e5e9a1a98df9c4d83361b727cf9ba Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 13 Mar 2017 18:22:16 -0700
Subject: [PATCH 114/402] =?UTF-8?q?doc=20fixes=20re=20=E2=80=94use-install?=
 =?UTF-8?q?ed-pkgs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 documentation/dev/testing.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index 0e6ed21eab..074302028c 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -104,7 +104,7 @@ Packages are downloaded and installed from the repos given by the `repos` argume
 The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation (the testing system does not honor the `--lib` argument).
 
 ##### Specifying packages to Install
-If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed.pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely:
+If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed-pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely:
 
     --ok-only: sets it to the file `com.oracle.truffle.r.test.packages.ok.packages`. This file is a list of packages that are known to install.
 
@@ -143,7 +143,7 @@ Testing packages requires that they are first installed, so all of the above is
     --verbose | -v: output tracing on basic steps
     -V: more verbose tracing
     --dry-run: output what would be installed but don't actually install
-    --no-install | -n: suppress installation phase (useful for --create blacklist and --use-installed-packages/--run-tests)
+    --no-install | -n: suppress installation phase (useful for --create blacklist and --use-installed-pkgs/--run-tests)
     --random count: install count packages randomly chosen from the candidate set
     --testdir dir: store test output in dir (defaults to "test").
     --print-ok-installs: print the successfully installed packages
-- 
GitLab


From 0b0d9384730e3099a6eb150632a2c0c192ad80e8 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 15 Mar 2017 15:22:29 +0100
Subject: [PATCH 115/402] Fix: ArrayIndexOutOfBoundsException when populating
 sequence that is longer than required.

---
 .../truffle/r/runtime/data/RDoubleSequence.java      |  2 +-
 .../oracle/truffle/r/runtime/data/RIntSequence.java  |  2 +-
 .../oracle/truffle/r/test/ExpectedTestOutput.test    | 12 ++++++++++++
 .../r/test/builtins/TestBuiltin_asmatrix.java        |  4 +++-
 4 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
index eaf92cff20..71cf88bace 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
@@ -90,7 +90,7 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
 
     private RDoubleVector populateVectorData(double[] result) {
         double current = start;
-        for (int i = 0; i < getLength(); i++) {
+        for (int i = 0; i < result.length && i < getLength(); i++) {
             result[i] = current;
             current += stride;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
index ed1daeb266..90d5a01501 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
@@ -85,7 +85,7 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
 
     private RIntVector populateVectorData(int[] result) {
         int current = start;
-        for (int i = 0; i < getLength(); i++) {
+        for (int i = 0; i < result.length && i < getLength(); i++) {
             result[i] = current;
             current += stride;
         }
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 5fc5fb2db8..83b6bca2e5 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
@@ -6396,6 +6396,18 @@ logical(0)
  [9,] "a"  "a"  "a"  "a"  "a"  "a"  "a"  "a"  "a"  "a"
 [10,] "a"  "a"  "a"  "a"  "a"  "a"  "a"  "a"  "a"  "a"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix#
+#{ matrix(1.1:16.1,2,2)}
+     [,1] [,2]
+[1,]  1.1  3.1
+[2,]  2.1  4.1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix#
+#{ matrix(1:16,2,2)}
+     [,1] [,2]
+[1,]    1    3
+[2,]    2    4
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asmatrix.testMatrix#
 #{ matrix(1:4, nrow=2) }
      [,1] [,2]
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java
index 5e62c86975..54beac54cc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asmatrix.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -69,6 +69,8 @@ public class TestBuiltin_asmatrix extends TestBase {
         assertEval("{ matrix(1:6, nrow=c(3,4,5),byrow=TRUE)}");
         assertEval("{ matrix(1:6)}");
         assertEval("{ matrix(1:6, ncol=3:5,byrow=TRUE)}");
+        assertEval("{ matrix(1:16,2,2)}");
+        assertEval("{ matrix(1.1:16.1,2,2)}");
 
         assertEval("{ matrix(TRUE,FALSE,FALSE,TRUE)}");
         assertEval("{ matrix(c(NaN,4+5i,2+0i,5+10i)) } ");
-- 
GitLab


From 48c31fad1114c881ac904f87c4ed10f17dded1c6 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 15 Mar 2017 16:59:29 +0100
Subject: [PATCH 116/402] ErrorContext node implements getErrorContext to avoid
 NPEs

---
 .../src/com/oracle/truffle/r/runtime/RError.java             | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index a73c50c1f7..5fd5c8dd71 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -74,6 +74,11 @@ public final class RError extends RuntimeException {
         private ErrorContext() {
             // private constructor
         }
+
+        @Override
+        protected RBaseNode getErrorContext() {
+            return this;
+        }
     }
 
     private static final class ErrorContextImpl extends ErrorContext {
-- 
GitLab


From d22fe77447522cc4f24c4d3da947bb601ddc53ca Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 16 Mar 2017 14:42:15 -0700
Subject: [PATCH 117/402] pkgtest: fix bug when tested packages is already
 installed

---
 .../r/install.packages.R                      | 66 ++++++++++++-------
 documentation/dev/testing.md                  |  4 +-
 2 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/com.oracle.truffle.r.test.packages/r/install.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R
index 2695cf973f..798ee89b0e 100644
--- a/com.oracle.truffle.r.test.packages/r/install.packages.R
+++ b/com.oracle.truffle.r.test.packages/r/install.packages.R
@@ -414,28 +414,34 @@ get.pkgs <- function() {
 
 	in.installed <- function(x) x["Package"] %in% installed.pkgs
 
-	basic.exclude <- function(x) {
-		in.installed(x) || in.blacklist(x)
+	basic.exclude <- function(x, exclude.installed = T) {
+		in.blacklist(x) || ifelse(exclude.installed, in.installed(x), F)
 	}
 
-	# either pkg.pattern is set or pkg.filelist but not both (checked earlier)
-	# if inverting, alter sense of the basic match but still exclude blacklist/installed
-	if (!is.na(pkg.filelistfile)) {
-		if (invert.pkgset) {
-			match.fun <- function(x) !in.filelist(x) && !basic.exclude(x)
-		} else {
-		    match.fun <- function(x) in.filelist(x) && !basic.exclude(x)
-	    }
-	} else {
-		if (invert.pkgset) {
-			match.fun <- function(x) !in.pattern(x) && !basic.exclude(x)
+	set.match.fun <- function(exclude.installed = T) {
+		# either pkg.pattern is set or pkg.filelist but not both (checked earlier)
+		# if inverting, alter sense of the basic match but still exclude blacklist/installed
+		if (!is.na(pkg.filelistfile)) {
+			if (invert.pkgset) {
+				match.fun <- function(x) !in.filelist(x) && !basic.exclude(x, exclude.installed)
+			} else {
+				match.fun <- function(x) in.filelist(x) && !basic.exclude(x, exclude.installed)
+			}
 		} else {
-		    match.fun <- function(x) in.pattern(x) && !basic.exclude(x)
+			if (invert.pkgset) {
+				match.fun <- function(x) !in.pattern(x) && !basic.exclude(x, exclude.installed)
+			} else {
+				match.fun <- function(x) in.pattern(x) && !basic.exclude(x, exclude.installed)
+			}
 		}
 	}
+
+	match.fun <- set.match.fun()
+
 	matched.avail.pkgs <- apply(avail.pkgs, 1, match.fun)
-	toinstall.pkgs <<-avail.pkgs[matched.avail.pkgs, , drop=F]
-	if (length(toinstall.pkgs) == 0) {
+	toinstall.pkgs <<- avail.pkgs[matched.avail.pkgs, , drop=F]
+
+	if (length(toinstall.pkgs) == 0 && !use.installed.pkgs) {
 		print("Fatal error: requested package(s) found in repo(s)")
 		quit(save="no", status=100)
 
@@ -450,15 +456,22 @@ get.pkgs <- function() {
 			test.pkgnames[[i]] <- test.avail.pkgnames[[rands[[i]]]]
 		}
 	} else {
-		test.pkgnames <- rownames(toinstall.pkgs)
-		if (!is.na(count.daily)) {
-			# extract count from index given by yday
-			npkgs <- length(test.pkgnames)
-			yday <- as.POSIXlt(Sys.Date())$yday
-			chunk <- as.integer(npkgs / count.daily)
-			start <- (yday %% chunk) * count.daily
-			end <- ifelse(start + count.daily > npkgs, npkgs, start + count.daily - 1)
-			test.pkgnames <- test.pkgnames[start:end]
+		if (length(toinstall.pkgs) == 0) {
+			# use.installed.pkgs == TRUE (see above)
+			match.fun <- set.match.fun(F)
+			matched.avail.pkgs <- apply(avail.pkgs, 1, match.fun)
+			test.pkgnames <- rownames(avail.pkgs[matched.avail.pkgs, , drop=F])
+		} else {
+			test.pkgnames <- rownames(toinstall.pkgs)
+			if (!is.na(count.daily)) {
+				# extract count from index given by yday
+				npkgs <- length(test.pkgnames)
+				yday <- as.POSIXlt(Sys.Date())$yday
+				chunk <- as.integer(npkgs / count.daily)
+				start <- (yday %% chunk) * count.daily
+				end <- ifelse(start + count.daily > npkgs, npkgs, start + count.daily - 1)
+				test.pkgnames <- test.pkgnames[start:end]
+			}
 		}
 	}
 
@@ -880,6 +893,9 @@ parse.args <- function() {
 	if (is.na(pkg.pattern) && is.na(pkg.filelistfile)) {
 	    pkg.pattern <<- "^.*"
 	}
+	if (!install) {
+		use.installed.pkgs <<- T
+	}
 	# list.versions is just that
     if (list.versions) {
 		install <<- F
diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index 074302028c..d01e8d5dcd 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -104,7 +104,7 @@ Packages are downloaded and installed from the repos given by the `repos` argume
 The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation (the testing system does not honor the `--lib` argument).
 
 ##### Specifying packages to Install
-If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed-pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely:
+If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed-pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set for installation. This option is implied by `--no-install`. Some convenience options implicitly set `--pkg-filelist`, namely:
 
     --ok-only: sets it to the file `com.oracle.truffle.r.test.packages.ok.packages`. This file is a list of packages that are known to install.
 
@@ -143,7 +143,7 @@ Testing packages requires that they are first installed, so all of the above is
     --verbose | -v: output tracing on basic steps
     -V: more verbose tracing
     --dry-run: output what would be installed but don't actually install
-    --no-install | -n: suppress installation phase (useful for --create blacklist and --use-installed-pkgs/--run-tests)
+    --no-install | -n: suppress installation phase (useful for --create blacklist and --run-tests)
     --random count: install count packages randomly chosen from the candidate set
     --testdir dir: store test output in dir (defaults to "test").
     --print-ok-installs: print the successfully installed packages
-- 
GitLab


From 8a14844eefb52191d0eb00bd3fa72f0ad29925b0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 7 Mar 2017 12:10:08 +0100
Subject: [PATCH 118/402] Added S4 unit tests.

---
 .../com/oracle/truffle/r/test/S4/TestS4.java  | 133 ++++++++++++++++++
 1 file changed, 133 insertions(+)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
new file mode 100644
index 0000000000..4719890c6b
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.S4;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestRBase;
+
+// Checkstyle: stop LineLength
+
+/**
+ * Tests for the S4 object model implementation.
+ */
+public class TestS4 extends TestRBase {
+    @Test
+    public void testSlotAccess() {
+        assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), virtual) }");
+        assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), \"virtual\") }");
+        assertEval(Output.IgnoreErrorContext, "{ `@`(getClass(\"ClassUnionRepresentation\"), c(\"virtual\", \"foo\")) }");
+        assertEval("{ getClass(\"ClassUnionRepresentation\")@virtual }");
+        assertEval("{ getClass(\"ClassUnionRepresentation\")@.S3Class }");
+        assertEval("{ c(42)@.Data }");
+        assertEval("{ x<-42; `@`(x, \".Data\") }");
+        assertEval("{ x<-42; `@`(x, .Data) }");
+        assertEval("{ x<-42; slot(x, \".Data\") }");
+        assertEval("{ setClass(\"foo\", contains=\"numeric\"); x<-new(\"foo\"); res<-x@.Data; removeClass(\"foo\"); res }");
+        assertEval("{ setClass(\"foo\", contains=\"numeric\"); x<-new(\"foo\"); res<-slot(x, \".Data\"); removeClass(\"foo\"); res }");
+        assertEval(Output.IgnoreErrorContext, "{ getClass(\"ClassUnionRepresentation\")@foo }");
+        assertEval(Output.IgnoreErrorContext, "{ c(42)@foo }");
+        assertEval(Output.IgnoreErrorContext, " { x<-42; attr(x, \"foo\")<-7; x@foo }");
+        assertEval("{ x<-42; attr(x, \"foo\")<-7; slot(x, \"foo\") }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-c(42); class(x)<-\"bar\"; x@foo }");
+        assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, \"virtual\") }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, virtual) }");
+        assertEval("{ x<-function() 42; attr(x, \"foo\")<-7; y<-asS4(x); y@foo }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@`(x, foo) }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo }");
+        assertEval("{ x<-paste0(\".\", \"Data\"); y<-42; slot(y, x) }");
+    }
+
+    @Test
+    public void testSlotUpdate() {
+        assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); x@virtual<-TRUE; x@virtual }");
+        assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, \"virtual\", check=TRUE)<-TRUE; x@virtual }");
+        assertEval("{ x<-initialize@valueClass; initialize@valueClass<-\"foo\"; initialize@valueClass<-x }");
+
+        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y@foo<-42 }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; slot(y, \"foo\")<-42 }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y<-asS4(x); y@foo<-42 }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@<-`(x, foo, \"bar\") }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo<-\"bar\" }");
+
+    }
+
+    @Test
+    public void testConversions() {
+        assertEval("{ x<-42; isS4(x) }");
+        assertEval("{ x<-42; y<-asS4(x); isS4(y) }");
+        assertEval("{ isS4(NULL) }");
+        assertEval("{ asS4(NULL); isS4(NULL) }");
+        assertEval("{  asS4(7:42) }");
+    }
+
+    @Test
+    public void testAllocation() {
+        assertEval("{ new(\"numeric\") }");
+        assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j=42) }");
+
+    }
+
+    @Test
+    public void testClassCreation() {
+        // output slightly different from GNU R even though we use R's "show" method to print it
+        assertEval(Ignored.OutputFormatting, "{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }");
+
+        assertEval("{ setClass(\"foo\"); setClass(\"bar\", representation(j = \"numeric\"), contains = \"foo\"); is.null(getClass(\"foo\")@prototype) }");
+    }
+
+    @Test
+    public void testMethods() {
+        // output slightly different from GNU R even though we use R's "show" method to print it
+        assertEval(Ignored.OutputFormatting, "{ setGeneric(\"gen\", function(object) standardGeneric(\"gen\")); res<-print(gen); removeGeneric(\"gen\"); res }");
+        assertEval(Ignored.OutputFormatting, "{ gen<-function(object) 0; setGeneric(\"gen\"); res<-print(gen); removeGeneric(\"gen\"); res }");
+
+        assertEval("{ gen<-function(object) 0; setGeneric(\"gen\"); setClass(\"foo\", representation(d=\"numeric\")); setMethod(\"gen\", signature(object=\"foo\"), function(object) object@d); res<-print(gen(new(\"foo\", d=42))); removeGeneric(\"gen\"); res }");
+
+        assertEval("{ setClass(\"foo\", representation(d=\"numeric\")); setClass(\"bar\",  contains=\"foo\"); setGeneric(\"gen\", function(o) standardGeneric(\"gen\")); setMethod(\"gen\", signature(o=\"foo\"), function(o) \"FOO\"); setMethod(\"gen\", signature(o=\"bar\"), function(o) \"BAR\"); res<-print(c(gen(new(\"foo\", d=7)), gen(new(\"bar\", d=42)))); removeGeneric(\"gen\"); res }");
+
+        assertEval("{ setGeneric(\"gen\", function(o) standardGeneric(\"gen\")); res<-print(setGeneric(\"gen\", function(o) standardGeneric(\"gen\"))); removeGeneric(\"gen\"); res }");
+
+        assertEval("{ setClass(\"foo\"); setMethod(\"diag<-\", \"foo\", function(x, value) 42); removeMethod(\"diag<-\", \"foo\"); removeGeneric(\"diag<-\"); removeClass(\"foo\") }");
+    }
+
+    @Test
+    public void testInternalDispatch() {
+        assertEval("setClass('foo', representation(d='numeric')); setMethod(`$`, signature('foo'), function(x, name) 'FOO'); obj <- new('foo'); obj$asdf");
+
+    }
+
+    @Test
+    public void testStdGeneric() {
+        assertEval("{ standardGeneric(42) }");
+        assertEval("{ standardGeneric(character()) }");
+        assertEval("{ standardGeneric(\"\") }");
+        assertEval("{ standardGeneric(\"foo\", 42) }");
+        assertEval("{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
+    }
+
+    @Override
+    public String getTestDir() {
+        return "S4";
+    }
+}
-- 
GitLab


From e91e5343ef61f83a48ced86a752cae6c4ff35ea0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 7 Mar 2017 14:19:26 +0100
Subject: [PATCH 119/402] Added S4 test package to list of test generation
 packages. Started to implement S4 dispatch.

---
 .../truffle/r/nodes/function/RCallNode.java   |  26 +-
 .../oracle/truffle/r/runtime/RRuntime.java    |   2 +
 .../truffle/r/runtime/data/RVector.java       |  15 +
 .../truffle/r/test/ExpectedTestOutput.test    | 293 ++++++++++++++++++
 .../com/oracle/truffle/r/test/S4/TestS4.java  |  12 +-
 mx.fastr/mx_fastr.py                          |   2 +-
 6 files changed, 341 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 00da0b6a7e..3cdbd5354d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -86,14 +86,17 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RFastPathNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -279,8 +282,12 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     @Cached("createWithError()") S3FunctionLookupNode dispatchLookup,
                     @Cached("createIdentityProfile()") ValueProfile builtinProfile,
                     @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile,
                     @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile,
-                    @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode) {
+                    @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode,
+                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile, //
+                    @Cached("createEqualityProfile()") ValueProfile attrProfiles,
+                    @Cached("new()") PromiseCheckHelperNode promiseHelper) {
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         Object dispatchObject = dispatchArgument.execute(frame);
         // Cannot dispatch on REmpty
@@ -289,6 +296,23 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         }
         FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject);
         try {
+            if (internalDispatchCall == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                internalDispatchCall = insert(FunctionDispatchNodeGen.create(this, false, slot));
+            }
+
+            if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) {
+                RList list = (RList) promiseHelper.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList"));
+// int index = list.getElementIndexByName(attrProfiles, builtin.getName());
+                int index = 0;
+                if (index != -1) {
+                    RFunction basicFun = (RFunction) list.getDataAt(index);
+                    Object result = internalDispatchCall.execute(frame, basicFun, lookupVarArgs(frame), null, null);
+                    if (result != RRuntime.DEFERRED_DEFAULT_MARKER) {
+                        return result;
+                    }
+                }
+            }
             RStringVector type = classHierarchyNode.execute(dispatchObject);
             S3Args s3Args;
             RFunction resultFunction;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 364e2d8484..0db9b9784f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -164,6 +164,8 @@ public class RRuntime {
 
     public static final String DOT_SIG_ARGS = ".SigArgs";
 
+    public static final RSymbol DEFERRED_DEFAULT_MARKER = new RSymbol("__Deferred_Default_Marker__");
+
     public static final String R_TARGET = "target";
     public static final String R_DOT_TARGET = ".target";
     public static final String R_DEFINED = "defined";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index e0d3de6980..8783733318 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -203,6 +204,20 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return -1;
     }
 
+    @TruffleBoundary
+    public final int getElementIndexByName(ValueProfile profile, String name) {
+        if (getNames() == null) {
+            return -1;
+        }
+        RStringVector names = getNamesFromAttrs();
+        for (int i = 0; i < names.getLength(); i++) {
+            if (names.getDataAt(i).equals(name)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     /**
      * Find the first element in the names list that {@code name} is a prefix of, and return its
      * index. If there are no names, or none is found, or there are multiple inexact matches, return
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 83b6bca2e5..4f2f013d10 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
@@ -1,3 +1,296 @@
+##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
+#{ new("numeric") }
+numeric(0)
+
+##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
+#{ setClass("foo", representation(j="numeric")); new("foo", j=42) }
+An object of class "foo"
+Slot "j":
+[1] 42
+
+
+##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#
+#{ setClass("foo"); setClass("bar", representation(j = "numeric"), contains = "foo"); is.null(getClass("foo")@prototype) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#Ignored.OutputFormatting#
+#{ setClass("foo", representation(j="numeric")); getClass("foo") }
+Class "foo" [in ".GlobalEnv"]
+
+Slots:
+
+Name:        j
+Class: numeric
+
+##com.oracle.truffle.r.test.S4.TestS4.testConversions#
+#{  asS4(7:42) }
+ [1]  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+[26] 32 33 34 35 36 37 38 39 40 41 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testConversions#
+#{ asS4(NULL); isS4(NULL) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestS4.testConversions#
+#{ isS4(NULL) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testConversions#
+#{ x<-42; isS4(x) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testConversions#
+#{ x<-42; y<-asS4(x); isS4(y) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestS4.testInternalDispatch#
+#setClass('foo', representation(d='numeric')); setMethod(`$`, signature('foo'), function(x, name) 'FOO'); obj <- new('foo'); obj$asdf
+[1] "$"
+[1] "FOO"
+
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
+#{ gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res }
+function (object)
+standardGeneric("gen")
+<environment: 0x2983900>
+attr(,"generic")
+[1] "gen"
+attr(,"generic")attr(,"package")
+[1] ".GlobalEnv"
+attr(,"package")
+[1] ".GlobalEnv"
+attr(,"group")
+list()
+attr(,"valueClass")
+character(0)
+attr(,"signature")
+[1] "object"
+attr(,"default")
+Method Definition (Class "derivedDefaultMethod"):
+
+function (object)
+0
+
+Signatures:
+        object
+target  "ANY"
+defined "ANY"
+attr(,"skeleton")
+(function (object)
+0)(object)
+attr(,"class")
+[1] "standardGeneric"
+attr(,"class")attr(,"package")
+[1] "methods"
+standardGeneric for "gen" defined from package ".GlobalEnv"
+
+function (object)
+standardGeneric("gen")
+<environment: 0x2983900>
+Methods may be defined for arguments: object
+Use  showMethods("gen")  for currently available ones.
+
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ gen<-function(object) 0; setGeneric("gen"); setClass("foo", representation(d="numeric")); setMethod("gen", signature(object="foo"), function(object) object@d); res<-print(gen(new("foo", d=42))); removeGeneric("gen"); res }
+[1] 42
+[1] 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ setClass("foo"); setMethod("diag<-", "foo", function(x, value) 42); removeMethod("diag<-", "foo"); removeGeneric("diag<-"); removeClass("foo") }
+Creating a generic function for ‘diag<-’ from package ‘base’ in the global environment
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ setClass("foo", representation(d="numeric")); setClass("bar",  contains="foo"); setGeneric("gen", function(o) standardGeneric("gen")); setMethod("gen", signature(o="foo"), function(o) "FOO"); setMethod("gen", signature(o="bar"), function(o) "BAR"); res<-print(c(gen(new("foo", d=7)), gen(new("bar", d=42)))); removeGeneric("gen"); res }
+[1] "FOO" "BAR"
+[1] "FOO" "BAR"
+
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res }
+[1] "gen"
+[1] "gen"
+
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
+#{ setGeneric("gen", function(object) standardGeneric("gen")); res<-print(gen); removeGeneric("gen"); res }
+function(object) standardGeneric("gen")
+<environment: 0x11f3000>
+attr(,"generic")
+[1] "gen"
+attr(,"generic")attr(,"package")
+[1] ".GlobalEnv"
+attr(,"package")
+[1] ".GlobalEnv"
+attr(,"group")
+list()
+attr(,"valueClass")
+character(0)
+attr(,"signature")
+[1] "object"
+attr(,"default")
+`\001NULL\001`
+attr(,"skeleton")
+(function (object)
+stop("invalid call in method dispatch to 'gen' (no default method)",
+    domain = NA))(object)
+attr(,"class")
+[1] "standardGeneric"
+attr(,"class")attr(,"package")
+[1] "methods"
+standardGeneric for "gen" defined from package ".GlobalEnv"
+
+function (object)
+standardGeneric("gen")
+<environment: 0x11f3000>
+Methods may be defined for arguments: object
+Use  showMethods("gen")  for currently available ones.
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+# { x<-42; attr(x, "foo")<-7; x@foo }
+Error: trying to get slot "foo" from an object of a basic class ("numeric") with no slots
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ `@`(getClass("ClassUnionRepresentation"), "virtual") }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ `@`(getClass("ClassUnionRepresentation"), c("virtual", "foo")) }
+Error: invalid type or length for slot name
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ `@`(getClass("ClassUnionRepresentation"), virtual) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ c(42)@.Data }
+[1] 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ c(42)@foo }
+Error: trying to get slot "foo" from an object of a basic class ("numeric") with no slots
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ getClass("ClassUnionRepresentation")@.S3Class }
+[1] "classRepresentation"
+attr(,"package")
+[1] "methods"
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ getClass("ClassUnionRepresentation")@foo }
+Error: no slot of name "foo" for this object of class "classRepresentation"
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ getClass("ClassUnionRepresentation")@virtual }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ setClass("foo", contains="numeric"); x<-new("foo"); res<-slot(x, ".Data"); removeClass("foo"); res }
+numeric(0)
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ setClass("foo", contains="numeric"); x<-new("foo"); res<-x@.Data; removeClass("foo"); res }
+numeric(0)
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-42; `@`(x, ".Data") }
+[1] 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-42; `@`(x, .Data) }
+[1] 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-42; attr(x, "foo")<-7; slot(x, "foo") }
+[1] 7
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-42; slot(x, ".Data") }
+[1] 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ x<-NULL; `@`(x, foo) }
+Error: trying to get slot "foo" from an object of a basic class ("NULL") with no slots
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ x<-NULL; x@foo }
+Error: trying to get slot "foo" from an object of a basic class ("NULL") with no slots
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ x<-c(42); class(x)<-"bar"; x@foo }
+Error: trying to get slot "foo" from an object (class "bar") that is not an S4 object
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo }
+[1] 7
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-getClass("ClassUnionRepresentation"); slot(x, "virtual") }
+[1] FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
+#{ x<-getClass("ClassUnionRepresentation"); slot(x, virtual) }
+Error in slot(x, virtual) : object 'virtual' not found
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ x<-paste0(".", "Data"); y<-42; slot(y, x) }
+[1] 42
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
+#{ x<-NULL; `@<-`(x, foo, "bar") }
+Error in (function (cl, name, valueClass)  :
+  ‘foo’ is not a slot in class “NULL”
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
+#{ x<-NULL; x@foo<-"bar" }
+Error in (function (cl, name, valueClass)  :
+  ‘foo’ is not a slot in class “NULL”
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
+#{ x<-function() 42; attr(x, "foo")<-7; slot(y, "foo")<-42 }
+Error in slot(y, "foo") <- 42 : object 'y' not found
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
+#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo<-42 }
+Error in (function (cl, name, valueClass)  :
+  ‘foo’ is not a slot in class “function”
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
+#{ x<-function() 42; attr(x, "foo")<-7; y@foo<-42 }
+Error in y@foo <- 42 : object 'y' not found
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
+#{ x<-getClass("ClassUnionRepresentation"); slot(x, "virtual", check=TRUE)<-TRUE; x@virtual }
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
+#{ x<-getClass("ClassUnionRepresentation"); x@virtual<-TRUE; x@virtual }
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
+#{ x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x }
+
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+#{ standardGeneric("") }
+Error in standardGeneric("") :
+  argument to 'standardGeneric' must be a non-empty character string
+
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+#{ standardGeneric("foo", 42) }
+Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
+
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+#{ standardGeneric(42) }
+Error in standardGeneric(42) :
+  argument to 'standardGeneric' must be a non-empty character string
+
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+#{ standardGeneric(character()) }
+Error in standardGeneric(character()) :
+  argument to 'standardGeneric' must be a non-empty character string
+
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext#
+#{ x<-42; class(x)<-character(); standardGeneric("foo", x) }
+Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Arg.testArg1#
 #argv <- list(1+2i);Arg(argv[[1]]);
 [1] 1.107149
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 4719890c6b..821615e7d7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -24,14 +24,16 @@ package com.oracle.truffle.r.test.S4;
 
 import org.junit.Test;
 
-import com.oracle.truffle.r.test.TestRBase;
+import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestBase.Ignored;
+import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop LineLength
 
 /**
  * Tests for the S4 object model implementation.
  */
-public class TestS4 extends TestRBase {
+public class TestS4 extends TestBase {
     @Test
     public void testSlotAccess() {
         assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), virtual) }");
@@ -123,11 +125,7 @@ public class TestS4 extends TestRBase {
         assertEval("{ standardGeneric(character()) }");
         assertEval("{ standardGeneric(\"\") }");
         assertEval("{ standardGeneric(\"foo\", 42) }");
-        assertEval("{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
     }
 
-    @Override
-    public String getTestDir() {
-        return "S4";
-    }
 }
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index b61e314d5c..782257b532 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -404,7 +404,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data']))
+    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data', 'S4']))
 
 def _simple_unit_tests():
     return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
-- 
GitLab


From 2aea478ac78f5ed101fb07b9c64a4dd94788ef99 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 9 Mar 2017 17:51:20 +0100
Subject: [PATCH 120/402] Added tests for the S4 class system. Modified
 'do.call' such that Bioconductor's "Biogenerics" package can be installed.
 Fixed a bug in "seq.int" which did not specialize correctly in some cases.

---
 .../truffle/r/nodes/builtin/base/DoCall.java  | 23 ++---
 .../truffle/r/nodes/builtin/base/R/do.call.R  |  6 ++
 .../r/nodes/builtin/base/SeqFunctions.java    |  6 +-
 .../truffle/r/runtime/data/RVector.java       | 14 ---
 .../truffle/r/test/ExpectedTestOutput.test    | 85 +++++++++++++++++--
 .../oracle/truffle/r/test/S4/R/NextMethod.R   | 24 ++++++
 .../oracle/truffle/r/test/S4/R/NextMethod1.R  | 44 ++++++++++
 .../com/oracle/truffle/r/test/S4/R/dispatch.R | 10 +++
 .../com/oracle/truffle/r/test/S4/TestS4.java  | 37 ++++++--
 .../r/test/builtins/TestBuiltin_lgamma.java   |  2 +-
 10 files changed, 206 insertions(+), 45 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 8a56fb21ff..adf2cc9288 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -56,7 +56,6 @@ import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
@@ -69,7 +68,7 @@ import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 // TODO Implement completely, this is a simple implementation that works when the envir argument is ignored
-@RBuiltin(name = "do.call", visibility = CUSTOM, kind = RBuiltinKind.SUBSTITUTE, parameterNames = {"what", "args", "quote", "envir"}, behavior = COMPLEX)
+@RBuiltin(name = ".fastr.do.call", visibility = CUSTOM, kind = RBuiltinKind.INTERNAL, parameterNames = {"what", "args", "quote", "envir"}, behavior = COMPLEX)
 public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNodeChildren {
 
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
@@ -84,7 +83,7 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
         casts.arg("what").defaultError(Message.MUST_BE_STRING_OR_FUNCTION, "what").mustBe(instanceOf(RFunction.class).or(stringValue()));
         casts.arg("args").mustBe(RAbstractListVector.class, Message.SECOND_ARGUMENT_LIST);
         casts.arg("quote").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
-        casts.arg("envir").allowMissing().mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir");
+        casts.arg("envir").mustNotBeMissing().mustBe(REnvironment.class, Message.MUST_BE_ENVIRON, "envir");
     }
 
     protected static Get createGet() {
@@ -111,24 +110,14 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
     }
 
     @Specialization(limit = "3", guards = {"what.getLength() == 1", "read.getIdentifier() == what.getDataAt(0)"})
-    protected Object doCallCached(VirtualFrame frame, @SuppressWarnings("unused") RAbstractStringVector what, RList argsAsList, boolean quote, RMissing env,
+    protected Object doCallCached(VirtualFrame frame, @SuppressWarnings("unused") RAbstractStringVector what, RList argsAsList, boolean quote, REnvironment env,
                     @Cached("createRead(what)") ReadVariableNode read) {
         RFunction func = (RFunction) read.execute(frame);
         return doCall(frame, func, argsAsList, quote, env);
     }
 
     @Specialization(replaces = "doCallCached")
-    protected Object doCall(VirtualFrame frame, RAbstractStringVector what, RList argsAsList, boolean quote, RMissing env) {
-        if (what.getLength() != 1) {
-            CompilerDirectives.transferToInterpreter();
-            throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
-        }
-        RFunction func = ReadVariableNode.lookupFunction(what.getDataAt(0), frame.materialize());
-        return doCall(frame, func, argsAsList, quote, env);
-    }
-
-    @Specialization
-    protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, boolean quote, @SuppressWarnings("unused") Object env) {
+    protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, boolean quote, REnvironment env) {
         /*
          * To re-create the illusion of a normal call, turn the values in argsAsList into promises.
          */
@@ -151,14 +140,14 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
                 if (arg instanceof RLanguage) {
                     containsRLanguageProfile.enter();
                     RLanguage lang = (RLanguage) arg;
-                    argValues[i] = createRLanguagePromise(frame.materialize(), lang);
+                    argValues[i] = createRLanguagePromise(env.getFrame().materialize(), lang);
                 } else if (arg instanceof RSymbol) {
                     containsRSymbolProfile.enter();
                     RSymbol symbol = (RSymbol) arg;
                     if (symbol.getName().isEmpty()) {
                         argValues[i] = REmpty.instance;
                     } else {
-                        argValues[i] = createLookupPromise(frame.materialize(), symbol);
+                        argValues[i] = createLookupPromise(env.getFrame().materialize(), symbol);
                     }
                 }
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R
new file mode 100644
index 0000000000..93881fdb0b
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R
@@ -0,0 +1,6 @@
+do.call <- function(what, args, quote = FALSE, envir = parent.frame())
+{
+    if (!is.list(args))
+		stop("second argument must be a list")
+    .Internal(.fastr.do.call(what, args, quote, envir))
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 1bb90b5933..5b86993957 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -12,7 +12,10 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
@@ -420,7 +423,8 @@ public final class SeqFunctions {
         private static final double FLT_EPSILON = 1.19209290e-7;
 
         static {
-            Casts.noCasts(SeqInt.class);
+            Casts casts = new Casts(SeqInt.class);
+            casts.arg("length.out").allowMissing().mapIf(nullValue(), missingConstant());
         }
 
         protected abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 8783733318..82eec933b6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -204,20 +204,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return -1;
     }
 
-    @TruffleBoundary
-    public final int getElementIndexByName(ValueProfile profile, String name) {
-        if (getNames() == null) {
-            return -1;
-        }
-        RStringVector names = getNamesFromAttrs();
-        for (int i = 0; i < names.getLength(); i++) {
-            if (names.getDataAt(i).equals(name)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
     /**
      * Find the first element in the names list that {@code name} is a prefix of, and return its
      * index. If there are no names, or none is found, or there are multiple inexact matches, return
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 4f2f013d10..d79d09f5c5 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
@@ -1,7 +1,41 @@
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod.R") }
+foo.bar(A, D)
+foo.bar(C, D)
+
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod1.R") }
+foo.bar(A, D)
+foo.bar(B, D)
+foo.bar(A, D)
+foo.bar(C, D)
+foo.bar(C, E)
+foo.bar(A, D)
+foo.bar(B, D)
+
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/dispatch.R") }
+Creating a generic function from function ‘foo.bar’ in the global environment
+[1] 1
+[1] 2
+[1] 3
+[1] "primitive, A, B"
+[1] "primitive, B, A"
+
 ##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
 #{ new("numeric") }
 numeric(0)
 
+##com.oracle.truffle.r.test.S4.TestS4.testAllocation#Output.IgnoreErrorContext#
+#{ setClass("foo", representation(j="numeric")); new("foo", inexisting=42) }
+Error in initialize(value, ...) :
+  invalid name for slot of class “foo”: inexisting
+
+##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
+#{ setClass("foo", representation(j="numeric")); new("foo", j='text') }
+Error in validObject(.Object) :
+  invalid class “foo” object: invalid object for slot "j" in class "foo": got class "character", should be or extend class "numeric"
+
 ##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
 #{ setClass("foo", representation(j="numeric")); new("foo", j=42) }
 An object of class "foo"
@@ -48,6 +82,11 @@ Class: numeric
 [1] "$"
 [1] "FOO"
 
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#setGeneric('do.call', signature = c('what', 'args'))
+Creating a new generic function for ‘do.call’ in the global environment
+[1] "do.call"
+
 ##com.oracle.truffle.r.test.S4.TestS4.testMethods#Ignored.OutputFormatting#
 #{ gen<-function(object) 0; setGeneric("gen"); res<-print(gen); removeGeneric("gen"); res }
 function (object)
@@ -105,6 +144,13 @@ Creating a generic function for ‘diag<-’ from package ‘base’ in the glob
 [1] "FOO" "BAR"
 [1] "FOO" "BAR"
 
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ setClass('A'); setClass('A1', contains = 'A'); setClass('A2', contains = 'A1'); setGeneric('foo', function(a, b) standardGeneric('foo')); setMethod('foo', signature('A1', 'A2'), function(a, b) '1-2'); setMethod('foo', signature('A2', 'A1'), function(a, b) '2-1'); foo(new('A2'), new('A2')) }
+Note: method with signature ‘A2#A1’ chosen for function ‘foo’,
+ target signature ‘A2#A2’.
+ "A1#A2" would also be valid
+[1] "2-1"
+
 ##com.oracle.truffle.r.test.S4.TestS4.testMethods#
 #{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res }
 [1] "gen"
@@ -144,6 +190,21 @@ standardGeneric("gen")
 Methods may be defined for arguments: object
 Use  showMethods("gen")  for currently available ones.
 
+##com.oracle.truffle.r.test.S4.TestS4.testObjectValidity#
+#{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = 1) }
+An object of class "SingleInt"
+Slot "n":
+[1] 1
+
+
+##com.oracle.truffle.r.test.S4.TestS4.testObjectValidity#
+#{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = c(1, 2)) }
+Error in validObject(.Object) : invalid class “SingleInt” object: FALSE
+
+##com.oracle.truffle.r.test.S4.TestS4.testObjectValueSemantics#
+#{ setClass('WrappedIntVec', representation(n = 'numeric')); x0 <- new('WrappedIntVec', n = 1); x1 <- x0; x1@n <- 2; x0@n == x1@n }
+[1] FALSE
+
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#Output.IgnoreErrorContext#
 # { x<-42; attr(x, "foo")<-7; x@foo }
 Error: trying to get slot "foo" from an object of a basic class ("numeric") with no slots
@@ -190,6 +251,19 @@ numeric(0)
 #{ setClass("foo", contains="numeric"); x<-new("foo"); res<-x@.Data; removeClass("foo"); res }
 numeric(0)
 
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ setClass('Person', representation(name = 'character', age = 'numeric')); getSlots('Person') }
+       name         age
+"character"   "numeric"
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ setClass('Person', representation(name = 'character', age = 'numeric')); hadley <- new('Person', name = 'Hadley'); hadley@age }
+numeric(0)
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ setClass('Person', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); hadley <- new('Person', name = 'Hadley'); hadley@age }
+[1] NA
+
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
 #{ x<-42; `@`(x, ".Data") }
 [1] 42
@@ -249,13 +323,14 @@ Error in (function (cl, name, valueClass)  :
 Error in slot(y, "foo") <- 42 : object 'y' not found
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo<-42 }
+#{ x<-function() 42; attr(x, "foo")<-7; x@foo<-42 }
 Error in (function (cl, name, valueClass)  :
   ‘foo’ is not a slot in class “function”
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#Output.IgnoreErrorContext#
-#{ x<-function() 42; attr(x, "foo")<-7; y@foo<-42 }
-Error in y@foo <- 42 : object 'y' not found
+#{ x<-function() 42; attr(x, "foo")<-7; y<-asS4(x); y@foo<-42 }
+Error in (function (cl, name, valueClass)  :
+  ‘foo’ is not a slot in class “function”
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
 #{ x<-getClass("ClassUnionRepresentation"); slot(x, "virtual", check=TRUE)<-TRUE; x@virtual }
@@ -273,7 +348,7 @@ Error in y@foo <- 42 : object 'y' not found
 Error in standardGeneric("") :
   argument to 'standardGeneric' must be a non-empty character string
 
-##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#Output.IgnoreErrorContext#
 #{ standardGeneric("foo", 42) }
 Error: expected a generic function or a primitive for dispatch, got an object of class "numeric"
 
@@ -30855,7 +30930,7 @@ numeric(0)
        41        42
  7.352977  9.355336
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma9#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma9#
 #argv <- list(Inf);do.call('lgamma', argv)
 [1] Inf
 Warning message:
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R
new file mode 100644
index 0000000000..5a9f104559
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod.R
@@ -0,0 +1,24 @@
+setClass("A")
+setClass("B", contains = "A")
+setClass("C", contains = "A")
+
+setClass("D", representation(name = "character"))
+
+setGeneric("foo.bar", function(x, y) {
+   standardGeneric("foo.bar")
+ })
+ 
+ setMethod("foo.bar", 
+  signature(x = "C", y = "D"),
+  function(x, y) {  
+   callNextMethod()
+   message("foo.bar(C, D)")
+  })
+  
+ setMethod("foo.bar", 
+  signature(x = "A", y = "D"), 
+  function(x, y) {
+    message("foo.bar(A, D)")
+  })
+
+foo.bar(new("C"), new("D"))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R
new file mode 100644
index 0000000000..86e89df733
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/NextMethod1.R
@@ -0,0 +1,44 @@
+setClass("A")
+setClass("B", contains = "A")
+setClass("C", contains = "A")
+
+setClass("D", representation(id = "numeric"))
+setClass("E", contains = "D")
+
+
+setGeneric("foo.bar", function(x, y) {
+   standardGeneric("foo.bar")
+ })
+ 
+ setMethod("foo.bar", 
+  signature(x = "C", y = "D"),
+  function(x, y) {  
+   callNextMethod()
+   message("foo.bar(C, D)")
+  })
+  
+ setMethod("foo.bar", 
+  signature(x = "A", y = "D"), 
+  function(x, y) {
+    message("foo.bar(A, D)")
+  })
+  
+  setMethod("foo.bar", 
+  signature(x = "B", y = "D"),
+  function(x, y) {
+    callNextMethod()
+    message("foo.bar(B, D)")
+  })
+
+foo.bar(new("B"), new("D"))
+
+setMethod("foo.bar", 
+  signature(x = "C", y = "E"),
+  function(x, y) {
+    callNextMethod()
+    message("foo.bar(C, E)")
+})
+
+foo.bar(new("C"), new("E"))
+
+foo.bar(new("B"), new("E"))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R
new file mode 100644
index 0000000000..d9a3c518fa
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/dispatch.R
@@ -0,0 +1,10 @@
+foo.bar <- function(x, y, z) { print(x); print(y); print(z) }
+
+setClass("A", representation(a = "numeric"))
+setClass("B", representation(b = "logical"))
+setMethod("foo.bar", signature = list(y = "A", z = "B"), function(x, y, z) { print("primitive, A, B") })
+setMethod("foo.bar", signature = list(y = "B", z = "A"), function(x, y, z) { print("primitive, B, A") })
+
+foo.bar(1, 2, 3)
+foo.bar(1, new("A"), new("B"))
+foo.bar(1, new("B"), new("A"))
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 821615e7d7..90ffa12daf 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -24,16 +24,20 @@ package com.oracle.truffle.r.test.S4;
 
 import org.junit.Test;
 
-import com.oracle.truffle.r.test.TestBase;
-import com.oracle.truffle.r.test.TestBase.Ignored;
-import com.oracle.truffle.r.test.TestBase.Output;
+import com.oracle.truffle.r.test.TestRBase;
 
 // Checkstyle: stop LineLength
 
 /**
  * Tests for the S4 object model implementation.
  */
-public class TestS4 extends TestBase {
+public class TestS4 extends TestRBase {
+
+    @Override
+    protected String getTestDir() {
+        return "S4";
+    }
+
     @Test
     public void testSlotAccess() {
         assertEval("{ `@`(getClass(\"ClassUnionRepresentation\"), virtual) }");
@@ -58,6 +62,9 @@ public class TestS4 extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@`(x, foo) }");
         assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo }");
         assertEval("{ x<-paste0(\".\", \"Data\"); y<-42; slot(y, x) }");
+        assertEval("{ setClass('Person', representation(name = 'character', age = 'numeric')); getSlots('Person') }");
+        assertEval("{ setClass('Person', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); hadley <- new('Person', name = 'Hadley'); hadley@age }");
+        assertEval("{ setClass('Person', representation(name = 'character', age = 'numeric')); hadley <- new('Person', name = 'Hadley'); hadley@age }");
     }
 
     @Test
@@ -66,7 +73,7 @@ public class TestS4 extends TestBase {
         assertEval("{ x<-getClass(\"ClassUnionRepresentation\"); slot(x, \"virtual\", check=TRUE)<-TRUE; x@virtual }");
         assertEval("{ x<-initialize@valueClass; initialize@valueClass<-\"foo\"; initialize@valueClass<-x }");
 
-        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y@foo<-42 }");
+        assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; x@foo<-42 }");
         assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; slot(y, \"foo\")<-42 }");
         assertEval(Output.IgnoreErrorContext, "{ x<-function() 42; attr(x, \"foo\")<-7; y<-asS4(x); y@foo<-42 }");
         assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@<-`(x, foo, \"bar\") }");
@@ -87,7 +94,8 @@ public class TestS4 extends TestBase {
     public void testAllocation() {
         assertEval("{ new(\"numeric\") }");
         assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j=42) }");
-
+        assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j='text') }");
+        assertEval(Output.IgnoreErrorContext, "{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", inexisting=42) }");
     }
 
     @Test
@@ -111,6 +119,10 @@ public class TestS4 extends TestBase {
         assertEval("{ setGeneric(\"gen\", function(o) standardGeneric(\"gen\")); res<-print(setGeneric(\"gen\", function(o) standardGeneric(\"gen\"))); removeGeneric(\"gen\"); res }");
 
         assertEval("{ setClass(\"foo\"); setMethod(\"diag<-\", \"foo\", function(x, value) 42); removeMethod(\"diag<-\", \"foo\"); removeGeneric(\"diag<-\"); removeClass(\"foo\") }");
+
+        assertEval("{ setClass('A'); setClass('A1', contains = 'A'); setClass('A2', contains = 'A1'); setGeneric('foo', function(a, b) standardGeneric('foo')); setMethod('foo', signature('A1', 'A2'), function(a, b) '1-2'); setMethod('foo', signature('A2', 'A1'), function(a, b) '2-1'); foo(new('A2'), new('A2')) }");
+
+        assertEval("setGeneric('do.call', signature = c('what', 'args'))");
     }
 
     @Test
@@ -124,8 +136,19 @@ public class TestS4 extends TestBase {
         assertEval("{ standardGeneric(42) }");
         assertEval("{ standardGeneric(character()) }");
         assertEval("{ standardGeneric(\"\") }");
-        assertEval("{ standardGeneric(\"foo\", 42) }");
+        assertEval(Output.IgnoreErrorContext, "{ standardGeneric(\"foo\", 42) }");
         assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
     }
 
+    @Test
+    public void testObjectValidity() {
+        assertEval("{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = c(1, 2)) }");
+        assertEval("{ check <- function(object) length(object@n) == 1; setClass('SingleInt', representation(n = 'numeric'), validity = check); new('SingleInt', n = 1) }");
+    }
+
+    @Test
+    public void testObjectValueSemantics() {
+        assertEval("{ setClass('WrappedIntVec', representation(n = 'numeric')); x0 <- new('WrappedIntVec', n = 1); x1 <- x0; x1@n <- 2; x0@n == x1@n }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
index 30e927da8e..8d9f865b07 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
@@ -56,7 +56,7 @@ public class TestBuiltin_lgamma extends TestBase {
 
     @Test
     public void testlgamma9() {
-        assertEval(Output.IgnoreWarningContext, "argv <- list(Inf);do.call('lgamma', argv)");
+        assertEval("argv <- list(Inf);do.call('lgamma', argv)");
     }
 
     @Test
-- 
GitLab


From e26dee4c066008f8dad92849a2ee9d8ac0635405 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 13 Mar 2017 13:06:16 +0100
Subject: [PATCH 121/402] Changes in RCallNode and StandardGeneric to support
 R5 (reference classes). Implemented function 'makeActiveBinding'. Added tests
 for active bindings.

---
 .../r/nodes/builtin/base/EnvFunctions.java    | 50 ++++++++++--
 .../truffle/r/nodes/builtin/base/R/do.call.R  |  1 +
 .../r/nodes/builtin/base/StandardGeneric.java | 13 +++-
 .../r/nodes/access/BaseWriteVariableNode.java | 32 ++++++++
 .../access/WriteLocalFrameVariableNode.java   | 17 +++-
 .../access/WriteSuperFrameVariableNode.java   | 17 +++-
 .../variables/LocalReadVariableNode.java      | 20 ++++-
 .../access/variables/ReadVariableNode.java    | 10 +++
 .../truffle/r/nodes/function/RCallNode.java   | 26 +++++--
 .../com/oracle/truffle/r/runtime/RError.java  |  6 +-
 .../truffle/r/runtime/data/RTypedValue.java   |  2 +-
 .../r/runtime/env/frame/ActiveBinding.java    | 49 ++++++++++++
 .../env/frame/FrameSlotChangeMonitor.java     | 27 +++++++
 .../truffle/r/test/ExpectedTestOutput.test    | 77 +++++++++++++++++++
 .../truffle/r/test/S4/R/activeBinding0.R      | 16 ++++
 .../truffle/r/test/S4/R/activeBinding1.R      | 14 ++++
 .../truffle/r/test/S4/R/activeBinding2.R      | 16 ++++
 .../truffle/r/test/S4/R/activeBinding3.R      | 18 +++++
 .../com/oracle/truffle/r/test/S4/TestS4.java  | 15 ++++
 .../r/test/builtins/TestBuiltin_lgamma.java   |  2 +-
 20 files changed, 403 insertions(+), 25 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 17f87b4f05..f21d4fbd3c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -42,11 +42,15 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RRootNode;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -79,6 +83,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 /**
@@ -600,11 +605,38 @@ public class EnvFunctions {
             casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
-        @SuppressWarnings("unused")
+        private BranchProfile frameSlotBranchProfile;
+
+        @TruffleBoundary
         @Specialization
-        protected Object makeActiveBinding(Object sym, Object fun, Object env) {
-            // TODO implement
-            throw RError.nyi(this, "makeActiveBinding");
+        protected Object makeActiveBinding(RSymbol sym, RFunction fun, REnvironment env) {
+            if (frameSlotBranchProfile == null) {
+                frameSlotBranchProfile = BranchProfile.create();
+            }
+
+            final String name = sym.getName();
+            Object binding = env.get(name);
+            final MaterializedFrame frame = env.getFrame();
+            if (binding == null) {
+                if (!env.isLocked()) {
+                    FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), name, FrameSlotKind.Object);
+                    FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(fun), false, frameSlotBranchProfile);
+                    binding = ReadVariableNode.lookupAny(name, frame, true);
+                    assert binding != null;
+                    assert binding instanceof ActiveBinding;
+                } else {
+                    throw error(RError.Message.CANNOT_ADD_BINDINGS);
+                }
+            } else if (!ActiveBinding.isActiveBinding(binding)) {
+                throw error(RError.Message.SYMBOL_HAS_REGULAR_BINDING);
+            } else if (env.bindingIsLocked(name)) {
+                throw error(RError.Message.CANNOT_CHANGE_LOCKED_ACTIVE_BINDING);
+            } else {
+                // update active binding
+                FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(name);
+                FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(fun), false, frameSlotBranchProfile);
+            }
+            return RNull.instance;
         }
     }
 
@@ -617,11 +649,13 @@ public class EnvFunctions {
             casts.arg("env").mustBe(REnvironment.class, Message.NOT_AN_ENVIRONMENT);
         }
 
-        @SuppressWarnings("unused")
         @Specialization
-        protected Object bindingIsActive(Object sym, Object env) {
-            // TODO implement
-            throw RError.nyi(this, "bindingIsActive");
+        protected Object bindingIsActive(RSymbol sym, REnvironment env) {
+            Object binding = ReadVariableNode.lookupAny(sym.getName(), env.getFrame(), true);
+            if (binding == null) {
+                throw error(RError.Message.NO_BINDING_FOR, sym.getName());
+            }
+            return RDataFactory.createLogicalVectorFromScalar(ActiveBinding.isActiveBinding(binding));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R
index 93881fdb0b..ffbeb252c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/do.call.R
@@ -1,3 +1,4 @@
+# 'do.call' needs to be a function for S4 but we do not use 'enquote' for performance reasons
 do.call <- function(what, args, quote = FALSE, envir = parent.frame())
 {
     if (!is.list(args))
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
index c6e061a795..4a6f412f95 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
@@ -82,7 +82,14 @@ public abstract class StandardGeneric extends RBuiltinNode {
     }
 
     private Object stdGenericInternal(VirtualFrame frame, String fname, RFunction fdef) {
-        MaterializedFrame fnFrame = fdef.getEnclosingFrame();
+        RFunction def = fdef;
+        if (def.isBuiltin()) {
+            def = RContext.getInstance().getPrimitiveMethodsInfo().getPrimGeneric(def.getRBuiltin().getPrimMethodIndex());
+            if (def == null) {
+                return RRuntime.DEFERRED_DEFAULT_MARKER;
+            }
+        }
+        MaterializedFrame fnFrame = def.getEnclosingFrame();
         REnvironment mtable = (REnvironment) readMTableFirst.execute(frame, fnFrame);
         if (mtable == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -90,7 +97,7 @@ public abstract class StandardGeneric extends RBuiltinNode {
             // and this slow path should not be executed again
             REnvironment methodsEnv = REnvironment.getRegisteredNamespace("methods");
             RFunction currentFunction = ReadVariableNode.lookupFunction(".getMethodsTable", methodsEnv.getFrame(), true, true);
-            mtable = (REnvironment) RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, fdef);
+            mtable = (REnvironment) RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, def);
         }
         RList sigArgs = (RList) readSigARgs.execute(null, fnFrame);
         int sigLength = (int) castIntScalar.execute(readSigLength.execute(null, fnFrame));
@@ -102,7 +109,7 @@ public abstract class StandardGeneric extends RBuiltinNode {
             collectArgumentsNode = insert(CollectGenericArgumentsNodeGen.create(sigArgs.getDataWithoutCopying(), sigLength));
         }
         RStringVector classes = collectArgumentsNode.execute(frame, sigArgs, sigLength);
-        Object ret = dispatchGeneric.executeObject(frame, mtable, classes, fdef, fname);
+        Object ret = dispatchGeneric.executeObject(frame, mtable, classes, def, fname);
         return ret;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index 24f773ecef..c343b3c130 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -28,11 +28,17 @@ import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 @NodeChild(value = "rhs", type = RNode.class)
@@ -153,4 +159,30 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
         }
         return false;
     }
+
+    /**
+     * Handles an assignment to an active binding.
+     * 
+     * @param execFrame The frame to be used for executing the function associated with the symbol.
+     * @param lookupFrame The frame to lookup the symbol (must not be {@code null}).
+     * @param value The value to set.
+     * @param frameSlot The frame slot of the value.
+     * @param invalidateProfile The invalidation profile.
+     */
+    protected static Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile) {
+        Object object;
+        try {
+            object = lookupFrame.getObject(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            object = null;
+        }
+
+        if (object != null && ActiveBinding.isActiveBinding(object)) {
+            ActiveBinding binding = (ActiveBinding) object;
+            return RContext.getEngine().evalFunction(binding.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), null, value);
+        } else {
+            FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, value, false, invalidateProfile);
+        }
+        return value;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
index 19807b04e4..e319aeab36 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.access;
 
+import com.oracle.truffle.api.Assumption;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -53,6 +56,7 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode
 
     private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
     private final BranchProfile invalidateProfile = BranchProfile.create();
+    @CompilationFinal private Assumption containsNoActiveBinding;
 
     protected WriteLocalFrameVariableNode(Object name, Mode mode) {
         super(name);
@@ -87,8 +91,17 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode
     @Specialization
     protected Object doObject(VirtualFrame frame, Object value,
                     @Cached("findOrAddFrameSlot(frame, Object)") FrameSlot frameSlot) {
-        Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), mode, false);
-        FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile);
+        if (containsNoActiveBinding == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            containsNoActiveBinding = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(frame.getFrameDescriptor());
+        }
+        if (containsNoActiveBinding != null && containsNoActiveBinding.isValid()) {
+            Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), mode, false);
+            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile);
+        } else {
+            // it's a local variable lookup; so use 'frame' for both, executing and looking up
+            return handleActiveBinding(frame, frame, value, frameSlot, invalidateProfile);
+        }
         return value;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
index 8d5de24ba4..7cd8ff8d00 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
@@ -24,7 +24,9 @@ package com.oracle.truffle.r.nodes.access;
 
 import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.findOrAddFrameSlot;
 
+import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.FrameSlot;
@@ -73,6 +75,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile();
 
         private final Mode mode;
+        @CompilationFinal private Assumption containsNoActiveBinding;
 
         public ResolvedWriteSuperFrameVariableNode(Object name, Mode mode) {
             super(name);
@@ -97,10 +100,18 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         }
 
         @Specialization
-        protected void doObject(Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
+        protected void doObject(VirtualFrame frame, Object value, MaterializedFrame enclosingFrame, FrameSlot frameSlot) {
             MaterializedFrame profiledFrame = enclosingFrameProfile.profile(enclosingFrame);
-            Object newValue = shareObjectValue(profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true);
-            FrameSlotChangeMonitor.setObjectAndInvalidate(profiledFrame, frameSlot, newValue, true, invalidateProfile);
+            if (containsNoActiveBinding == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                containsNoActiveBinding = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(profiledFrame.getFrameDescriptor());
+            }
+            if (containsNoActiveBinding != null && containsNoActiveBinding.isValid()) {
+                Object newValue = shareObjectValue(profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true);
+                FrameSlotChangeMonitor.setObjectAndInvalidate(profiledFrame, frameSlot, newValue, true, invalidateProfile);
+            } else {
+                handleActiveBinding(frame, profiledFrame, value, frameSlot, invalidateProfile);
+            }
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
index 90211045df..c9ae8a382b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,15 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
+import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 public final class LocalReadVariableNode extends Node {
 
@@ -53,6 +59,7 @@ public final class LocalReadVariableNode extends Node {
 
     @CompilationFinal private FrameSlot frameSlot;
     @CompilationFinal private Assumption notInFrame;
+    @CompilationFinal private Assumption containsNoActiveBindingAssumption;
 
     private final ValueProfile frameProfile = ValueProfile.createClassProfile();
 
@@ -107,6 +114,17 @@ public final class LocalReadVariableNode extends Node {
         if (isNullProfile.profile(result == null) || isMissingProfile.profile(result == RMissing.instance)) {
             return null;
         }
+
+        if (containsNoActiveBindingAssumption == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            containsNoActiveBindingAssumption = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(profiledVariableFrame.getFrameDescriptor());
+        }
+        // special treatment for active binding: call bound function
+        if (containsNoActiveBindingAssumption != null && !containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) {
+            ActiveBinding binding = (ActiveBinding) result;
+            result = RContext.getEngine().evalFunction(binding.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
+        }
+
         if (forceResult) {
             if (isPromiseProfile == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index 2e8a35d214..aea93d821c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -52,12 +52,15 @@ import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
+import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.StableValue;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -70,6 +73,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameAndSlotLookupResult;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.LookupResult;
@@ -131,6 +136,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
     @CompilationFinal private boolean needsCopying;
 
     private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile copyProfile;
     private final BranchProfile unexpectedMissingProfile = BranchProfile.create();
     private final ValueProfile superEnclosingFrameProfile = ValueProfile.createClassProfile();
@@ -230,6 +236,10 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
             }
             result = promiseHelper.evaluate(frame, (RPromise) result);
         }
+        if (isActiveBindingProfile.profile(ActiveBinding.isActiveBinding(result))) {
+            ActiveBinding binding = (ActiveBinding) result;
+            result = RContext.getEngine().evalFunction(binding.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
+        }
         return result;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 3cdbd5354d..d380dda31d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -285,8 +285,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile,
                     @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile,
                     @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode,
-                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile, //
-                    @Cached("createEqualityProfile()") ValueProfile attrProfiles,
+                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile,
                     @Cached("new()") PromiseCheckHelperNode promiseHelper) {
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         Object dispatchObject = dispatchArgument.execute(frame);
@@ -303,8 +302,8 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
 
             if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) {
                 RList list = (RList) promiseHelper.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList"));
-// int index = list.getElementIndexByName(attrProfiles, builtin.getName());
-                int index = 0;
+                // TODO create a node that looksup the name in the names attribute
+                int index = list.getElementIndexByName(builtin.getName());
                 if (index != -1) {
                     RFunction basicFun = (RFunction) list.getDataAt(index);
                     Object result = internalDispatchCall.execute(frame, basicFun, lookupVarArgs(frame), null, null);
@@ -344,14 +343,31 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     @Cached("createWithError()") S3FunctionLookupNode dispatchLookup,
                     @Cached("createIdentityProfile()") ValueProfile builtinProfile,
                     @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile,
                     @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile,
                     @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode,
                     @Cached("createUninitializedExplicitCall()") FunctionDispatch call,
+                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile,
                     @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode) {
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         RArgsValuesAndNames argAndNames = (RArgsValuesAndNames) explicitArgs.execute(frame);
 
-        RStringVector type = argAndNames.isEmpty() ? null : classHierarchyNode.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(0)));
+        Object dispatchObject = argAndNames.getArgument(0);
+
+        if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) {
+            RList list = (RList) promiseHelperNode.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList"));
+            // TODO create a node that looksup the name in the names attribute
+            int index = list.getElementIndexByName(builtin.getName());
+            if (index != -1) {
+                RFunction basicFun = (RFunction) list.getDataAt(index);
+                Object result = call.execute(frame, basicFun, argAndNames, null, null);
+                if (result != RRuntime.DEFERRED_DEFAULT_MARKER) {
+                    return result;
+                }
+            }
+        }
+
+        RStringVector type = argAndNames.isEmpty() ? null : classHierarchyNode.execute(promiseHelperNode.checkEvaluate(frame, dispatchObject));
         S3Args s3Args;
         RFunction resultFunction;
         if (implicitTypeProfile.profile(type != null)) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 5fd5c8dd71..489b131144 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -857,7 +857,11 @@ public final class RError extends RuntimeException {
         INVALID_VARIABLE_NAMES("invalid variable names"),
         INVALID_EXPRESSION("invalid expression in '%s'"),
         INVALID_EXPRESSION_TYPE("expression must not be type '%s'"),
-        NOT_IN_DERIVATIVE_TABLE("Function '%s' is not in the derivatives table");
+        NOT_IN_DERIVATIVE_TABLE("Function '%s' is not in the derivatives table"),
+        CANNOT_ADD_BINDINGS("cannot add bindings to a locked environment"),
+        SYMBOL_HAS_REGULAR_BINDING("symbol already has a regular binding"),
+        CANNOT_CHANGE_LOCKED_ACTIVE_BINDING("cannot change active binding if binding is locked"),
+        NO_BINDING_FOR("no binding for \"%s\"");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
index d66dda64a7..153949e45e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
new file mode 100644
index 0000000000..e426a71a4b
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.env.frame;
+
+import java.util.Objects;
+
+import com.oracle.truffle.r.runtime.data.RFunction;
+
+/**
+ * Represent an active binding of a function. This requires special treatment when reading and
+ * writing variables.
+ */
+public class ActiveBinding {
+
+    private final RFunction function;
+
+    public ActiveBinding(RFunction fun) {
+        this.function = Objects.requireNonNull(fun);
+    }
+
+    public RFunction getFunction() {
+        return function;
+    }
+
+    public static boolean isActiveBinding(Object binding) {
+        return binding instanceof ActiveBinding;
+    }
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index a3a7abc4f0..6f1f1de9b9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -184,6 +184,7 @@ public final class FrameSlotChangeMonitor {
 
         private WeakReference<FrameDescriptor> enclosingFrameDescriptor = new WeakReference<>(null);
         private Assumption enclosingFrameDescriptorAssumption = Truffle.getRuntime().createAssumption("enclosing frame descriptor");
+        private Assumption containsNoActiveBindingAssumption = Truffle.getRuntime().createAssumption("contains no active binding");
 
         private FrameDescriptorMetaData(String name, MaterializedFrame singletonFrame) {
             this.name = name;
@@ -208,6 +209,10 @@ public final class FrameSlotChangeMonitor {
         public Assumption getEnclosingFrameDescriptorAssumption() {
             return enclosingFrameDescriptorAssumption;
         }
+
+        public Assumption getContainsNoActiveBindingAssumption() {
+            return containsNoActiveBindingAssumption;
+        }
     }
 
     private static final WeakHashMap<FrameDescriptor, FrameDescriptorMetaData> frameDescriptors = new WeakHashMap<>();
@@ -607,6 +612,7 @@ public final class FrameSlotChangeMonitor {
     }
 
     public static void setObjectAndInvalidate(Frame frame, FrameSlot frameSlot, Object newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
+        assert !ActiveBinding.isActiveBinding(newValue);
         frame.setObject(frameSlot, newValue);
         FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
         if (info.needsInvalidation()) {
@@ -615,6 +621,16 @@ public final class FrameSlotChangeMonitor {
         checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
     }
 
+    public static void setActiveBinding(Frame frame, FrameSlot frameSlot, ActiveBinding newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
+        frame.setObject(frameSlot, newValue);
+        FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+        if (info.needsInvalidation()) {
+            info.setValue(newValue, frameSlot);
+        }
+        checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
+        getContainsNoActiveBindingAssumption(frame.getFrameDescriptor()).invalidate();
+    }
+
     /**
      * Initializes the internal data structures for a newly created frame descriptor that is
      * intended to be used for a non-function frame (and thus will only ever be used for one frame).
@@ -632,6 +648,17 @@ public final class FrameSlotChangeMonitor {
         return frameDescriptors.get(descriptor).getEnclosingFrameDescriptorAssumption();
     }
 
+    public static synchronized Assumption getContainsNoActiveBindingAssumption(FrameDescriptor descriptor) {
+        CompilerAsserts.neverPartOfCompilation();
+        final FrameDescriptorMetaData frameDescriptorMetaData = frameDescriptors.get(descriptor);
+        return frameDescriptorMetaData != null ? frameDescriptorMetaData.getContainsNoActiveBindingAssumption() : null;
+    }
+
+    public static synchronized boolean isContainsNoActiveBindingAssumptionValid(FrameDescriptor descriptor) {
+        Assumption assumption = getContainsNoActiveBindingAssumption(descriptor);
+        return assumption != null ? assumption.isValid() : true;
+    }
+
     public static synchronized StableValue<Object> getStableValueAssumption(FrameDescriptor descriptor, FrameSlot frameSlot, Object value) {
         CompilerAsserts.neverPartOfCompilation();
         StableValue<Object> stableValue = getFrameSlotInfo(frameSlot).getStableValue();
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 d79d09f5c5..783947f033 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
@@ -13,6 +13,27 @@ foo.bar(C, E)
 foo.bar(A, D)
 foo.bar(B, D)
 
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding0.R") }
+get
+[1] 1
+set
+get
+[1] 2
+
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding1.R") }
+get
+1
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding2.R") }
+
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding3.R") }
+set
+get
+[1] 3
+
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/dispatch.R") }
 Creating a generic function from function ‘foo.bar’ in the global environment
@@ -22,6 +43,62 @@ Creating a generic function from function ‘foo.bar’ in the global environmen
 [1] "primitive, A, B"
 [1] "primitive, B, A"
 
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#.Internal(bindingIsActive(as.name('someSymbol4'), .GlobalEnv))
+Error: no binding for "someSymbol4"
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#bindingIsActive('someSymbol3', .GlobalEnv)
+Error in bindingIsActive("someSymbol3", .GlobalEnv) :
+  no binding for "someSymbol3"
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#Output.IgnoreErrorContext#
+#lockEnvironment(.GlobalEnv); makeActiveBinding('someSymbol1', function(x) { x }, .GlobalEnv)
+Error in makeActiveBinding("someSymbol1", function(x) { :
+  cannot add bindings to a locked environment
+Error during wrapup: cannot add bindings to a locked environment
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get0') else print('set0'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1; makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get1') else print('set1'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1
+[1] "get0"
+NULL
+[1] "set0"
+[1] "get1"
+NULL
+[1] "set1"
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#makeActiveBinding('someSymbol2', function(x) { x }, .GlobalEnv); bindingIsActive('someSymbol2', .GlobalEnv)
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#makeActiveBinding('someSymbol6', function(x) { x }, .GlobalEnv); lockBinding('someSymbol6', .GlobalEnv); makeActiveBinding('someSymbol6', function(x) { print('hello') }, .GlobalEnv)
+Error in makeActiveBinding("someSymbol6", function(x) { :
+  cannot change active binding if binding is locked
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#Ignored.Unknown#
+#makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1
+[1] "get0"
+[1] "set0"
+[1] "get1"
+[1] "set1"
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#makeActiveBinding('someSymbol8', function(x) { print('hello') }, .GlobalEnv); someSymbol9 <- 'world'; print(someSymbol8); print(someSymbol9)
+[1] "hello"
+[1] "hello"
+[1] "world"
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#someSymbol0 <- 1; makeActiveBinding('someSymbol0', function(x) { x }, .GlobalEnv)
+Error in makeActiveBinding("someSymbol0", function(x) { :
+  symbol already has a regular binding
+
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#someSymbol5 <- 0; lockBinding('someSymbol5', .GlobalEnv); makeActiveBinding('someSymbol5', function(x) { x }, .GlobalEnv)
+Error in makeActiveBinding("someSymbol5", function(x) { :
+  symbol already has a regular binding
+
 ##com.oracle.truffle.r.test.S4.TestS4.testAllocation#
 #{ new("numeric") }
 numeric(0)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R
new file mode 100644
index 0000000000..1eb24d8376
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding0.R
@@ -0,0 +1,16 @@
+f <- local( {
+    x <- 1
+    function(v) {
+       if (missing(v))
+           cat("get\n")
+       else {
+           cat("set\n")
+           x <<- v
+       }
+       x
+    }
+})
+makeActiveBinding("fred", f, .GlobalEnv)
+print(fred)
+fred <- 2
+print(fred)
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R
new file mode 100644
index 0000000000..dd71ebe2c4
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding1.R
@@ -0,0 +1,14 @@
+f <- local( {
+    x <- 1
+    function(v) {
+       if (missing(v))
+           cat("get\n")
+       else {
+           cat("set\n")
+           x <<- v
+       }
+       x
+    }
+})
+makeActiveBinding("fred", f, .GlobalEnv)
+cat(fred)
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R
new file mode 100644
index 0000000000..11070d3a0f
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding2.R
@@ -0,0 +1,16 @@
+f <- local( {
+    x <- 1
+    function(v) {
+       if (missing(v))
+           cat("get\n")
+       else {
+           cat("set\n")
+           x <<- v
+       }
+       x
+    }
+})
+makeActiveBinding("fred", f, .GlobalEnv)
+foo <- function() {
+	fred + 1
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R
new file mode 100644
index 0000000000..b54876d335
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/activeBinding3.R
@@ -0,0 +1,18 @@
+f <- local( {
+    x <- 1
+    function(v) {
+       if (missing(v))
+           cat("get\n")
+       else {
+           cat("set\n")
+           x <<- v
+       }
+       x
+    }
+})
+makeActiveBinding("fred", f, .GlobalEnv)
+foo <- function(x) {
+	fred <<- x
+}
+foo(3)
+print(fred)
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 90ffa12daf..57b4ced08e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -151,4 +151,19 @@ public class TestS4 extends TestRBase {
         assertEval("{ setClass('WrappedIntVec', representation(n = 'numeric')); x0 <- new('WrappedIntVec', n = 1); x1 <- x0; x1@n <- 2; x0@n == x1@n }");
     }
 
+    @Test
+    public void testActiveBindings() {
+        assertEval("someSymbol0 <- 1; makeActiveBinding('someSymbol0', function(x) { x }, .GlobalEnv)");
+        assertEval(Output.IgnoreErrorContext, "lockEnvironment(.GlobalEnv); makeActiveBinding('someSymbol1', function(x) { x }, .GlobalEnv)");
+        assertEval("makeActiveBinding('someSymbol2', function(x) { x }, .GlobalEnv); bindingIsActive('someSymbol2', .GlobalEnv)");
+        assertEval("bindingIsActive('someSymbol3', .GlobalEnv)");
+        assertEval(".Internal(bindingIsActive(as.name('someSymbol4'), .GlobalEnv))");
+        assertEval("someSymbol5 <- 0; lockBinding('someSymbol5', .GlobalEnv); makeActiveBinding('someSymbol5', function(x) { x }, .GlobalEnv)");
+        assertEval("makeActiveBinding('someSymbol6', function(x) { x }, .GlobalEnv); lockBinding('someSymbol6', .GlobalEnv); makeActiveBinding('someSymbol6', function(x) { print('hello') }, .GlobalEnv)");
+        assertEval(Ignored.Unknown,
+                        "makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1");
+        assertEval("makeActiveBinding('someSymbol8', function(x) { print('hello') }, .GlobalEnv); someSymbol9 <- 'world'; print(someSymbol8); print(someSymbol9)");
+        assertEval("makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get0') else print('set0'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1; makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get1') else print('set1'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
index 8d9f865b07..144683f652 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
-- 
GitLab


From 25cd31f20706e320bfd9ec95497fbfd34e926e1b Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 13 Mar 2017 18:25:27 +0100
Subject: [PATCH 122/402] Added more tests for R5. Rcpp can now be installed.

---
 .../r/nodes/builtin/base/EnvFunctions.java    |  4 +-
 .../r/nodes/builtin/base/UpdateSubstr.java    |  5 +-
 .../r/nodes/function/ClassHierarchyNode.java  |  7 ++
 .../com/oracle/truffle/r/runtime/RError.java  |  3 +-
 .../r/runtime/env/frame/ActiveBinding.java    | 14 +++-
 .../truffle/r/test/ExpectedTestOutput.test    | 76 +++++++++++++++++++
 .../com/oracle/truffle/r/test/S4/TestR5.java  | 63 +++++++++++++++
 7 files changed, 167 insertions(+), 5 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index f21d4fbd3c..9293a46bb2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -620,7 +620,7 @@ public class EnvFunctions {
             if (binding == null) {
                 if (!env.isLocked()) {
                     FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), name, FrameSlotKind.Object);
-                    FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(fun), false, frameSlotBranchProfile);
+                    FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(sym.getRType(), fun), false, frameSlotBranchProfile);
                     binding = ReadVariableNode.lookupAny(name, frame, true);
                     assert binding != null;
                     assert binding instanceof ActiveBinding;
@@ -634,7 +634,7 @@ public class EnvFunctions {
             } else {
                 // update active binding
                 FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(name);
-                FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(fun), false, frameSlotBranchProfile);
+                FrameSlotChangeMonitor.setActiveBinding(frame, slot, new ActiveBinding(sym.getRType(), fun), false, frameSlotBranchProfile);
             }
             return RNull.instance;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
index b5955ec823..87164398f9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -51,7 +53,8 @@ public abstract class UpdateSubstr extends RBuiltinNode {
     private final BranchProfile everSeenIllegalRange = BranchProfile.create();
 
     static {
-        Casts.noCasts(UpdateSubstr.class);
+        Casts casts = new Casts(UpdateSubstr.class);
+        casts.arg("x").mustBe(nullValue().not().and(stringValue()), RError.Message.REPLACING_IN_NON_CHAR_OBJ).asStringVector();
     }
 
     private static boolean rangeOk(String x, int start, int stop) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index dd4a98c595..0f2c213f20 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -53,6 +53,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class ClassHierarchyNode extends UnaryNode {
@@ -149,6 +150,12 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return obj instanceof RTypedValue;
     }
 
+    @Specialization(guards = "!isRTypedValue(object)")
+    protected RStringVector getClassHrActiveBinding(@SuppressWarnings("unused") ActiveBinding object) {
+        // TODO return appropriate class hierarchy
+        return withImplicitTypes ? RIntVector.implicitClassHeader : null;
+    }
+
     @Specialization(guards = "!isRTypedValue(object)")
     protected RStringVector getClassHrTruffleObject(@SuppressWarnings("unused") TruffleObject object) {
         return truffleObjectClassHeader;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 489b131144..fff8fc28c2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -861,7 +861,8 @@ public final class RError extends RuntimeException {
         CANNOT_ADD_BINDINGS("cannot add bindings to a locked environment"),
         SYMBOL_HAS_REGULAR_BINDING("symbol already has a regular binding"),
         CANNOT_CHANGE_LOCKED_ACTIVE_BINDING("cannot change active binding if binding is locked"),
-        NO_BINDING_FOR("no binding for \"%s\"");
+        NO_BINDING_FOR("no binding for \"%s\""),
+        REPLACING_IN_NON_CHAR_OBJ("replacing substrings in a non-character object");
 
         public final String message;
         final boolean hasArgs;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
index e426a71a4b..2e6b16a3a9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.env.frame;
 
 import java.util.Objects;
 
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RFunction;
 
 /**
@@ -32,9 +33,11 @@ import com.oracle.truffle.r.runtime.data.RFunction;
  */
 public class ActiveBinding {
 
+    private final RType expectedType;
     private final RFunction function;
 
-    public ActiveBinding(RFunction fun) {
+    public ActiveBinding(RType expectedType, RFunction fun) {
+        this.expectedType = Objects.requireNonNull(expectedType);
         this.function = Objects.requireNonNull(fun);
     }
 
@@ -42,8 +45,17 @@ public class ActiveBinding {
         return function;
     }
 
+    public RType getExpectedType() {
+        return expectedType;
+    }
+
     public static boolean isActiveBinding(Object binding) {
         return binding instanceof ActiveBinding;
     }
 
+    @Override
+    public String toString() {
+        return "active binding";
+    }
+
 }
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 783947f033..6c0a446e06 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
@@ -1,3 +1,79 @@
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#{ Person <- setRefClass('Person'); Person$new() }
+Reference class object of class "Person"
+
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#Ignored.ImplementationError#
+#{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(1) }
+Reference class object of class "Foo"
+Field "a":
+numeric(0)
+Warning message:
+In methods::initRefFields(.Object, classDef, selfEnv, list(...)) :
+  unnamed arguments to $new() must be objects from a reference class; got an object of class “numeric”
+
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(a = 1) }
+Reference class object of class "Foo"
+Field "a":
+[1] 1
+
+##com.oracle.truffle.r.test.S4.TestR5.testAttributes#
+#{ Person <- setRefClass('Person'); Person$methods() }
+ [1] ".objectPackage" ".objectParent"  "callSuper"      "copy"
+ [5] "export"         "field"          "getClass"       "getRefClass"
+ [9] "import"         "initFields"     "show"           "trace"
+[13] "untrace"        "usingMethods"
+
+##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign#
+#clazz <- setRefClass('Foo', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a
+[1] "hello"
+Error: invalid assignment for reference class field ‘a’, should be from class “character” or a subclass (was class “numeric”)
+
+##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign#
+#clazz <- setRefClass('Foo', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a
+[1] 10
+Error: invalid assignment for reference class field ‘a’, should be from class “numeric” or a subclass (was class “character”)
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)
+Reference class object of class "Foo"
+Field "a":
+[1] 5
+Field "b":
+[1] 6
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')
+[1] 1
+[1] 5
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Output.IgnoreErrorContext#
+#{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$accessors() }
+Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
+  replacing substrings in a non-character object
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }
+code for methods in class “Foo” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] 3
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }
+[1] "Foo"
+attr(,"package")
+[1] ".GlobalEnv"
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}
+[1] 1
+
+##com.oracle.truffle.r.test.S4.TestR5.testReferenceSemantics#
+#fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a
+[1] 1
+[1] 1
+[1] 999
+[1] 999
+
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod.R") }
 foo.bar(A, D)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
new file mode 100644
index 0000000000..92307732b4
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.S4;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestR5 extends TestBase {
+
+    @Test
+    public void testAllocation() {
+        assertEval("{ Person <- setRefClass('Person'); Person$new() }");
+        assertEval("{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(a = 1) }");
+        assertEval(Ignored.ImplementationError, "{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(1) }");
+    }
+
+    @Test
+    public void testAttributes() {
+        assertEval("{ Person <- setRefClass('Person'); Person$methods() }");
+    }
+
+    @Test
+    public void testReferenceSemantics() {
+        assertEval("fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a");
+    }
+
+    @Test
+    public void testInstanceMethods() {
+        assertEval("{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }");
+        assertEval("{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}");
+        assertEval("clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')");
+        assertEval("clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)");
+        assertEval(Output.IgnoreErrorContext, "{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$accessors() }");
+        assertEval("{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }");
+    }
+
+    @Test
+    public void testCheckedAssign() {
+        assertEval("clazz <- setRefClass('Foo', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a");
+        assertEval("clazz <- setRefClass('Foo', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a");
+    }
+}
-- 
GitLab


From e5e404cc29481251341045c38c5444537b1412bf Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 14 Mar 2017 18:04:13 +0100
Subject: [PATCH 123/402] Integrated handling of active bindings into frame
 access. Added more tests for R5.

---
 .../r/nodes/builtin/base/EnvFunctions.java    |   6 +-
 .../r/nodes/access/BaseWriteVariableNode.java |   8 +-
 .../variables/LocalReadVariableNode.java      |   7 +-
 .../access/variables/ReadVariableNode.java    |   7 +-
 .../r/nodes/function/ClassHierarchyNode.java  |   9 +-
 .../truffle/r/nodes/function/RCallNode.java   |  17 ++-
 .../r/runtime/PrimitiveMethodsInfo.java       |   4 +-
 .../r/runtime/env/frame/ActiveBinding.java    |  12 ++
 .../env/frame/FrameSlotChangeMonitor.java     |  12 ++
 .../env/frame/REnvTruffleFrameAccess.java     |  23 +++-
 .../truffle/r/test/ExpectedTestOutput.test    | 113 +++++++++++++-----
 .../com/oracle/truffle/r/test/S4/TestR5.java  |  42 +++++--
 .../com/oracle/truffle/r/test/S4/TestS4.java  |   1 +
 13 files changed, 185 insertions(+), 76 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 9293a46bb2..164c83ff25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -614,9 +614,9 @@ public class EnvFunctions {
                 frameSlotBranchProfile = BranchProfile.create();
             }
 
-            final String name = sym.getName();
-            Object binding = env.get(name);
-            final MaterializedFrame frame = env.getFrame();
+            String name = sym.getName();
+            MaterializedFrame frame = env.getFrame();
+            Object binding = ReadVariableNode.lookupAny(name, frame, true);
             if (binding == null) {
                 if (!env.isLocked()) {
                     FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), name, FrameSlotKind.Object);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index c343b3c130..509456715b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -32,11 +32,8 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
-import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RShareable;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -162,7 +159,7 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
 
     /**
      * Handles an assignment to an active binding.
-     * 
+     *
      * @param execFrame The frame to be used for executing the function associated with the symbol.
      * @param lookupFrame The frame to lookup the symbol (must not be {@code null}).
      * @param value The value to set.
@@ -178,8 +175,7 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
         }
 
         if (object != null && ActiveBinding.isActiveBinding(object)) {
-            ActiveBinding binding = (ActiveBinding) object;
-            return RContext.getEngine().evalFunction(binding.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), null, value);
+            return ((ActiveBinding) object).writeValue(value);
         } else {
             FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, value, false, invalidateProfile);
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
index c9ae8a382b..c5cf895eeb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
@@ -34,13 +34,9 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
-import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
@@ -121,8 +117,7 @@ public final class LocalReadVariableNode extends Node {
         }
         // special treatment for active binding: call bound function
         if (containsNoActiveBindingAssumption != null && !containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) {
-            ActiveBinding binding = (ActiveBinding) result;
-            result = RContext.getEngine().evalFunction(binding.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
+            return ((ActiveBinding) result).readValue();
         }
 
         if (forceResult) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index aea93d821c..2820805cbd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -52,15 +52,12 @@ import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.StableValue;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -73,7 +70,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameAndSlotLookupResult;
@@ -237,8 +233,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
             result = promiseHelper.evaluate(frame, (RPromise) result);
         }
         if (isActiveBindingProfile.profile(ActiveBinding.isActiveBinding(result))) {
-            ActiveBinding binding = (ActiveBinding) result;
-            result = RContext.getEngine().evalFunction(binding.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
+            return ((ActiveBinding) result).readValue();
         }
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index 0f2c213f20..119494163d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -150,10 +150,11 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return obj instanceof RTypedValue;
     }
 
-    @Specialization(guards = "!isRTypedValue(object)")
-    protected RStringVector getClassHrActiveBinding(@SuppressWarnings("unused") ActiveBinding object) {
-        // TODO return appropriate class hierarchy
-        return withImplicitTypes ? RIntVector.implicitClassHeader : null;
+    @TruffleBoundary
+    @Specialization
+    protected RStringVector getClassHrActiveBinding(ActiveBinding object) {
+        Object result = RContext.getEngine().evalFunction(object.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
+        return execute(result);
     }
 
     @Specialization(guards = "!isRTypedValue(object)")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index d380dda31d..94e738e581 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -418,6 +418,8 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile,
                     @Cached("createBinaryProfile()") ConditionProfile summaryGroupNaRmProfile,
                     @Cached("createBinaryProfile()") ConditionProfile summaryGroupProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile,
                     @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode,
                     @Cached("createUninitializedExplicitCall()") FunctionDispatch call,
                     @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode) {
@@ -437,7 +439,20 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
             typeXIdx = 1;
         }
 
-        RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, args[typeXIdx]));
+        Object dispatchObject = promiseHelperNode.checkEvaluate(frame, args[typeXIdx]);
+
+        if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) {
+            RList list = (RList) promiseHelperNode.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList"));
+            int index = list.getElementIndexByName(builtin.getName());
+            if (index != -1) {
+                RFunction basicFun = (RFunction) list.getDataAt(index);
+                Object result = call.execute(frame, basicFun, new RArgsValuesAndNames(args, argsSignature), null, null);
+                if (result != RRuntime.DEFERRED_DEFAULT_MARKER) {
+                    return result;
+                }
+            }
+        }
+        RStringVector typeX = classHierarchyNodeX.execute(dispatchObject);
         Result resultX = null;
         if (implicitTypeProfileX.profile(typeX != null)) {
             resultX = dispatchLookupX.execute(frame, builtin.getName(), typeX, dispatch.getGroupGenericName(), frame.materialize(), getBaseEnvFrameNode.execute());
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java
index 6aa68c5ba2..76d5a6bea1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -52,7 +52,7 @@ public class PrimitiveMethodsInfo {
     }
 
     public RFunction getPrimGeneric(int index) {
-        return primGenerics[index];
+        return index < primGenerics.length ? primGenerics[index] : null;
     }
 
     public void setPrimGeneric(int index, RFunction generic) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
index 2e6b16a3a9..694e6332c5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
@@ -24,8 +24,12 @@ package com.oracle.truffle.r.runtime.env.frame;
 
 import java.util.Objects;
 
+import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
  * Represent an active binding of a function. This requires special treatment when reading and
@@ -58,4 +62,12 @@ public class ActiveBinding {
         return "active binding";
     }
 
+    public Object writeValue(Object value) {
+        return RContext.getEngine().evalFunction(function, REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), null, value);
+    }
+
+    public Object readValue() {
+        return RContext.getEngine().evalFunction(function, REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 6f1f1de9b9..1211aea3fc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -467,6 +467,9 @@ public final class FrameSlotChangeMonitor {
         @CompilationFinal private StableValue<Object> stableValue;
         private int invalidationCount;
 
+        // TODO @CompilationFinal ?
+        @CompilationFinal private boolean activeBinding;
+
         FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier) {
             if (isSingletonFrame) {
                 stableValue = new StableValue<>(null, identifier.toString());
@@ -506,6 +509,7 @@ public final class FrameSlotChangeMonitor {
             if (stableValue != null && stableValue.getValue() != value) {
                 invalidateStableValue(value, slot);
             }
+            activeBinding = ActiveBinding.isActiveBinding(value);
         }
 
         private void invalidateStableValue(Object value, FrameSlot slot) {
@@ -524,6 +528,10 @@ public final class FrameSlotChangeMonitor {
         public StableValue<Object> getStableValue() {
             return stableValue;
         }
+
+        public boolean isActiveBinding() {
+            return activeBinding;
+        }
     }
 
     /**
@@ -678,4 +686,8 @@ public final class FrameSlotChangeMonitor {
     public static boolean isValidFrameDescriptor(FrameDescriptor frameDesc) {
         return getMetaData(frameDesc) != null;
     }
+
+    public static boolean isActiveBinding(FrameSlot slot) {
+        return ((FrameSlotInfoImpl) slot.getInfo()).isActiveBinding();
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
index da58110d0b..6259785656 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
+import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -70,7 +71,12 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
         if (slot == null) {
             return null;
         } else {
-            return frame.getValue(slot);
+            Object value = frame.getValue(slot);
+            // TODO this could have tremendous performance impact !
+            if (ActiveBinding.isActiveBinding(value)) {
+                return ((ActiveBinding) value).readValue();
+            }
+            return value;
         }
     }
 
@@ -103,7 +109,18 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
                 FrameSlotChangeMonitor.setDoubleAndInvalidate(frame, slot, (double) value, false, null);
                 break;
             case Object:
-                FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, value, false, null);
+                Object object;
+                try {
+                    object = frame.getObject(slot);
+                } catch (FrameSlotTypeException e) {
+                    object = null;
+                }
+
+                if (object != null && ActiveBinding.isActiveBinding(object)) {
+                    ((ActiveBinding) object).writeValue(value);
+                } else {
+                    FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, value, false, null);
+                }
                 break;
             case Illegal:
                 break;
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 6c0a446e06..53f17c5ae3 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
@@ -1,74 +1,118 @@
 ##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
-#{ Person <- setRefClass('Person'); Person$new() }
-Reference class object of class "Person"
+#{ DummyClass0 <- setRefClass('DummyClass0'); DummyClass0$new() }
+Reference class object of class "DummyClass0"
+
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#{ DummyClass1 <- setRefClass('DummyClass1'); is(DummyClass1, 'refClass') }
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#{ DummyClass2 <- setRefClass('DummyClass2'); obj <- DummyClass2$new(); is(obj, 'refObject') }
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#{ fooClass <- setRefClass('Foo6R5', fields = list( a = 'numeric')); fooClass$new(a = 1) }
+Reference class object of class "Foo6R5"
+Field "a":
+[1] 1
 
 ##com.oracle.truffle.r.test.S4.TestR5.testAllocation#Ignored.ImplementationError#
-#{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(1) }
-Reference class object of class "Foo"
+#{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }
+Reference class object of class "Foo7R5"
 Field "a":
 numeric(0)
 Warning message:
 In methods::initRefFields(.Object, classDef, selfEnv, list(...)) :
   unnamed arguments to $new() must be objects from a reference class; got an object of class “numeric”
 
-##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
-#{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(a = 1) }
-Reference class object of class "Foo"
-Field "a":
-[1] 1
-
 ##com.oracle.truffle.r.test.S4.TestR5.testAttributes#
-#{ Person <- setRefClass('Person'); Person$methods() }
+#{ clazz <- setRefClass('Foo13R5'); clazz$methods() }
  [1] ".objectPackage" ".objectParent"  "callSuper"      "copy"
  [5] "export"         "field"          "getClass"       "getRefClass"
  [9] "import"         "initFields"     "show"           "trace"
 [13] "untrace"        "usingMethods"
 
 ##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign#
-#clazz <- setRefClass('Foo', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a
+#clazz <- setRefClass('Foo10R5', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a
+[1] 10
+Error: invalid assignment for reference class field ‘a’, should be from class “numeric” or a subclass (was class “character”)
+
+##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign#
+#clazz <- setRefClass('Foo11R5', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a
 [1] "hello"
 Error: invalid assignment for reference class field ‘a’, should be from class “character” or a subclass (was class “numeric”)
 
 ##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign#
-#clazz <- setRefClass('Foo', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a
-[1] 10
-Error: invalid assignment for reference class field ‘a’, should be from class “numeric” or a subclass (was class “character”)
+#clazz <- setRefClass('Foo8R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj))
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestR5.testCheckedAssign#
+#clazz <- setRefClass('Foo9R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj)); obj$a <- 123; bindingIsActive('a', as.environment(obj))
+[1] TRUE
+[1] TRUE
+
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
+#A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a
+[1] 1
+
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
+#A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()
+code for methods in class “A1R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] "hello"
+
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
+#A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()
+code for methods in class “A2R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+code for methods in class “B2R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] "world"
+
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#Ignored.ImplementationError#
+#A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()
+code for methods in class “A3R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+code for methods in class “B3R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] "hello"
+[1] "world"
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')
+[1] 1
+[1] 5
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)
-Reference class object of class "Foo"
+#clazz <- setRefClass('Foo3R5', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)
+Reference class object of class "Foo3R5"
 Field "a":
 [1] 5
 Field "b":
 [1] 6
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')
+#{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }
+code for methods in class “Foo0R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] 3
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }
+code for methods in class “Foo12R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] 1
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}
 [1] 1
-[1] 5
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Output.IgnoreErrorContext#
-#{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$accessors() }
+#{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }
 Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
   replacing substrings in a non-character object
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }
-code for methods in class “Foo” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-[1] 3
-
-##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }
-[1] "Foo"
+#{ clazz <- setRefClass('Foo5R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }
+[1] "Foo5R5"
 attr(,"package")
 [1] ".GlobalEnv"
 
-##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}
-[1] 1
-
 ##com.oracle.truffle.r.test.S4.TestR5.testReferenceSemantics#
-#fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a
+#fooClass <- setRefClass('Foo12R5', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a
 [1] 1
 [1] 1
 [1] 999
@@ -165,6 +209,11 @@ Error in makeActiveBinding("someSymbol6", function(x) { :
 [1] "hello"
 [1] "world"
 
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
+#makeActiveBinding('var_a', function(x) { if(missing(x)) { print('get'); return(123) } else { print('set'); return(x) } }, .GlobalEnv); inherits(var_a, 'numeric')
+[1] "get"
+[1] TRUE
+
 ##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
 #someSymbol0 <- 1; makeActiveBinding('someSymbol0', function(x) { x }, .GlobalEnv)
 Error in makeActiveBinding("someSymbol0", function(x) { :
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index 92307732b4..1c77e45d27 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -26,38 +26,54 @@ import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
 
+// Checkstyle: stop LineLength
+
 public class TestR5 extends TestBase {
 
     @Test
     public void testAllocation() {
-        assertEval("{ Person <- setRefClass('Person'); Person$new() }");
-        assertEval("{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(a = 1) }");
-        assertEval(Ignored.ImplementationError, "{ fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); fooClass$new(1) }");
+        assertEval("{ DummyClass0 <- setRefClass('DummyClass0'); DummyClass0$new() }");
+        assertEval("{ DummyClass1 <- setRefClass('DummyClass1'); is(DummyClass1, 'refClass') }");
+        assertEval("{ DummyClass2 <- setRefClass('DummyClass2'); obj <- DummyClass2$new(); is(obj, 'refObject') }");
+        assertEval("{ fooClass <- setRefClass('Foo6R5', fields = list( a = 'numeric')); fooClass$new(a = 1) }");
+        assertEval(Ignored.ImplementationError, "{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }");
     }
 
     @Test
     public void testAttributes() {
-        assertEval("{ Person <- setRefClass('Person'); Person$methods() }");
+        assertEval("{ clazz <- setRefClass('Foo13R5'); clazz$methods() }");
     }
 
     @Test
     public void testReferenceSemantics() {
-        assertEval("fooClass <- setRefClass('Foo', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a");
+        assertEval("fooClass <- setRefClass('Foo12R5', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a");
     }
 
     @Test
     public void testInstanceMethods() {
-        assertEval("{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }");
-        assertEval("{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}");
-        assertEval("clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')");
-        assertEval("clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)");
-        assertEval(Output.IgnoreErrorContext, "{ clazz <- setRefClass('Foo', c('a', 'b')); clazz$accessors() }");
-        assertEval("{ clazz <- setRefClass('Foo', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }");
+        assertEval("{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }");
+        assertEval("{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}");
+        assertEval("clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')");
+        assertEval("clazz <- setRefClass('Foo3R5', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)");
+        assertEval(Output.IgnoreErrorContext, "{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }");
+        assertEval("{ clazz <- setRefClass('Foo5R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }");
+        assertEval("{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
     }
 
     @Test
     public void testCheckedAssign() {
-        assertEval("clazz <- setRefClass('Foo', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a");
-        assertEval("clazz <- setRefClass('Foo', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a");
+        assertEval("clazz <- setRefClass('Foo8R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj))");
+        assertEval("clazz <- setRefClass('Foo9R5', fields = list(a = 'numeric')); obj <- clazz$new(); bindingIsActive('a', as.environment(obj)); obj$a <- 123; bindingIsActive('a', as.environment(obj))");
+        assertEval("clazz <- setRefClass('Foo10R5', fields = list(a = 'numeric')); obj <- clazz$new(); obj$a <- 10; obj$a; obj$a <- 'hello'; obj$a");
+        assertEval("clazz <- setRefClass('Foo11R5', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a");
+    }
+
+    @Test
+    public void testInheritance() {
+        assertEval("A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a");
+        assertEval("A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()");
+        assertEval("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()");
+        assertEval(Ignored.ImplementationError,
+                        "A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 57b4ced08e..a18472473c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -164,6 +164,7 @@ public class TestS4 extends TestRBase {
                         "makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1");
         assertEval("makeActiveBinding('someSymbol8', function(x) { print('hello') }, .GlobalEnv); someSymbol9 <- 'world'; print(someSymbol8); print(someSymbol9)");
         assertEval("makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get0') else print('set0'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1; makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get1') else print('set1'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1");
+        assertEval("makeActiveBinding('var_a', function(x) { if(missing(x)) { print('get'); return(123) } else { print('set'); return(x) } }, .GlobalEnv); inherits(var_a, 'numeric')");
     }
 
 }
-- 
GitLab


From dfa41d785266ebc1cfea5ed2e6e72e75c23609ee Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 15 Mar 2017 11:16:02 +0100
Subject: [PATCH 124/402] Fixed: Bug in "environment<-" that broke R5. Added
 test for this bug.

---
 .../truffle/r/nodes/builtin/base/EnvFunctions.java     |  9 ++++++++-
 .../com/oracle/truffle/r/test/ExpectedTestOutput.test  | 10 +++++++++-
 .../src/com/oracle/truffle/r/test/S4/TestR5.java       |  3 +--
 .../r/test/builtins/TestBuiltin_environmentassign.java |  6 +++++-
 4 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 164c83ff25..4511b49779 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -67,6 +67,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.VirtualEvalFrame;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -417,7 +418,13 @@ public class EnvFunctions {
             RRootNode root = (RRootNode) fun.getTarget().getRootNode();
             RootCallTarget target = root.duplicateWithNewFrameDescriptor();
             FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame);
-            return RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame);
+
+            RFunction newFunction = RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame);
+            if (fun.getAttributes() != null) {
+                newFunction.initAttributes(RAttributesLayout.copy(fun.getAttributes()));
+            }
+            newFunction.setTypedValueInfo(fun.getTypedValueInfo());
+            return newFunction;
         }
 
         @Specialization
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 53f17c5ae3..c0b29986fe 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
@@ -66,7 +66,7 @@ code for methods in class “A2R5” was not checked for suspicious field assign
 code for methods in class “B2R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 [1] "world"
 
-##com.oracle.truffle.r.test.S4.TestR5.testInheritance#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
 #A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()
 code for methods in class “A3R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 code for methods in class “B3R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
@@ -22756,6 +22756,10 @@ Error in environment(e1) <- 3 : replacement object is not an environment
 Error in environment(f) <- new.env() :
   attempt to set an attribute on NULL
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1#
+#{ f <- asS4(function(x) x+1); r <- isS4(f); environment(f) <- new.env(); r && isS4(f) }
+[1] TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1#
 #{ f <- function() x; f2 <- f; e <- new.env(); assign('x', 2, envir=e); x <- 1; environment(f) <- e; c(f(), f2())}
 [1] 2 1
@@ -22767,6 +22771,10 @@ Error in environment(f) <- new.env() :
 #{ f <- function() {}; environment(f) <- NULL }
 Error in environment(f) <- NULL : use of NULL environment is defunct
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1#
+#{ jh <- function(x) x+1; attributes(jh) <- list(myMetaData ='hello'); environment(jh) <- new.env(); attr(jh, 'myMetaData') }
+[1] "hello"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testEval#
 #eval('foo')
 [1] "foo"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index 1c77e45d27..548eeb08dd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -73,7 +73,6 @@ public class TestR5 extends TestBase {
         assertEval("A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a");
         assertEval("A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()");
         assertEval("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()");
-        assertEval(Ignored.ImplementationError,
-                        "A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
+        assertEval("A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java
index af8ec8a7f4..d68f1fea48 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -32,5 +32,9 @@ public class TestBuiltin_environmentassign extends TestBase {
         assertEval("{ f <- function() x; f2 <- f; e <- new.env(); assign('x', 2, envir=e); x <- 1; environment(f) <- e; c(f(), f2())}");
 
         assertEval("{ f <- NULL; environment(f) <- new.env() }");
+
+        // changing the environment must not change metadata
+        assertEval("{ f <- asS4(function(x) x+1); r <- isS4(f); environment(f) <- new.env(); r && isS4(f) }");
+        assertEval("{ jh <- function(x) x+1; attributes(jh) <- list(myMetaData ='hello'); environment(jh) <- new.env(); attr(jh, 'myMetaData') }");
     }
 }
-- 
GitLab


From e6ae8fffb02c334ccadee7ebef620c8789b7a28c Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 15 Mar 2017 13:13:06 +0100
Subject: [PATCH 125/402] Fixed: Env2list could not handle RS4Object.

---
 .../oracle/truffle/r/nodes/builtin/base/EnvFunctions.java    | 5 +++++
 .../src/com/oracle/truffle/r/test/ExpectedTestOutput.test    | 4 ++++
 .../src/com/oracle/truffle/r/test/S4/TestR5.java             | 1 +
 3 files changed, 10 insertions(+)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 4511b49779..c2b77e78ef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -767,6 +767,11 @@ public class EnvFunctions {
             return env;
         }
 
+        @Specialization
+        Object copy(RS4Object o) {
+            return o.copy();
+        }
+
         @Fallback
         Object copy(@SuppressWarnings("unused") Object o) {
             throw RInternalError.unimplemented("copying of object in the environment not supported");
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 c0b29986fe..a869640799 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
@@ -73,6 +73,10 @@ code for methods in class “B3R5” was not checked for suspicious field assign
 [1] "hello"
 [1] "world"
 
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
+#{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }
+code for methods in class “B4R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
 #clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index 548eeb08dd..bce46a1c84 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -74,5 +74,6 @@ public class TestR5 extends TestBase {
         assertEval("A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()");
         assertEval("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()");
         assertEval("A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
+        assertEval("{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }");
     }
 }
-- 
GitLab


From c7034275f662d0559f81145ef32fc4f975dbaeb8 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 16 Mar 2017 15:39:44 +0100
Subject: [PATCH 126/402] Added more tests for reference classes.

---
 .../truffle/r/test/ExpectedTestOutput.test    | 135 +++++++++++++++++-
 .../oracle/truffle/r/test/S4/R/refClasses0.R  |  84 +++++++++++
 .../oracle/truffle/r/test/S4/R/refClasses1.R  |   5 +
 .../oracle/truffle/r/test/S4/R/refClasses2.R  |  25 ++++
 .../com/oracle/truffle/r/test/S4/TestR5.java  |  41 +++++-
 5 files changed, 287 insertions(+), 3 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R

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 a869640799..44f31002f3 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
@@ -1,3 +1,8 @@
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#env0 <- new.env(); setRefClass('Foo17R5', where = env0); ls(topenv(parent.frame()), all.names = T); ls(env0, all.names = T)
+[1] "env0"
+[1] ".__C__Foo17R5"          ".__global__"            ".requireCachedGenerics"
+
 ##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
 #{ DummyClass0 <- setRefClass('DummyClass0'); DummyClass0$new() }
 Reference class object of class "DummyClass0"
@@ -16,7 +21,7 @@ Reference class object of class "Foo6R5"
 Field "a":
 [1] 1
 
-##com.oracle.truffle.r.test.S4.TestR5.testAllocation#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
 #{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }
 Reference class object of class "Foo7R5"
 Field "a":
@@ -25,6 +30,10 @@ Warning message:
 In methods::initRefFields(.Object, classDef, selfEnv, list(...)) :
   unnamed arguments to $new() must be objects from a reference class; got an object of class “numeric”
 
+##com.oracle.truffle.r.test.S4.TestR5.testAllocation#
+#{ setRefClass('Foo16R5'); ls(topenv(parent.frame()), all.names = T) }
+[1] ".__C__Foo16R5"          ".__global__"            ".requireCachedGenerics"
+
 ##com.oracle.truffle.r.test.S4.TestR5.testAttributes#
 #{ clazz <- setRefClass('Foo13R5'); clazz$methods() }
  [1] ".objectPackage" ".objectParent"  "callSuper"      "copy"
@@ -51,6 +60,79 @@ Error: invalid assignment for reference class field ‘a’, should be from clas
 [1] TRUE
 [1] TRUE
 
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)
+code for methods in class “Foo21R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+NULL
+code for methods in class “Foo21R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] 3
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo14R5'); obj <- clazz$new(); obj$inexistingMethod() }
+Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
+  ‘inexistingMethod’ is not a valid field or method name for reference class “Foo14R5”
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(); obj$a }
+An object of class "uninitializedField"
+Slot "field":
+[1] "a"
+
+Slot "className":
+[1] "ANY"
+
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(a = 1); print(obj$a); obj$a <- 'hello'; print(obj$a) }
+[1] 1
+[1] "hello"
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo19R5'); clazz$methods('inexistingMethod') }
+NULL
+Warning message:
+In .getMethodDefs(methodDefs[[1]], methodsEnv) :
+  Methods not found: “.objectPackage”, “.objectParent”, “callSuper”, “copy”, “export”, “field”, “getClass”, “getRefClass”, “import”, “initFields”, “show”, “trace”, “untrace”, “usingMethods”
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.IgnoreWhitespace#
+#{ clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo') }
+code for methods in class “Foo20R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+Class method definition for method foo()
+function ()
+NULL
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo22R5'); clazz$fields() }
+NULL
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo23R5', fields = c('a', 'b', 'c')); clazz$fields() }
+    a     b     c
+"ANY" "ANY" "ANY"
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo24R5', fields = list(a = 'numeric')); clazz$fields() }
+        a
+"numeric"
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo25R5', fields = list(a = 'numeric', b = 'character', c = 'raw')); clazz$fields() }
+          a           b           c
+  "numeric" "character"       "raw"
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo26R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a }
+[1] 10
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
+#{ clazz <- setRefClass('Foo27R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a <- 20 }
+Error: invalid replacement: reference class field ‘a’ is read-only
+
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Ignored.ReferenceError#
+#{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() }
+Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
+  replacing substrings in a non-character object
+
 ##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
 #A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a
 [1] 1
@@ -73,6 +155,9 @@ code for methods in class “B3R5” was not checked for suspicious field assign
 [1] "hello"
 [1] "world"
 
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
+#A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0)
+
 ##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
 #{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }
 code for methods in class “B4R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
@@ -100,10 +185,34 @@ code for methods in class “Foo0R5” was not checked for suspicious field assi
 code for methods in class “Foo12R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 [1] 1
 
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo13R5'); obj <- clazz$new(); obj$inexistingMethod() }
+Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
+  ‘inexistingMethod’ is not a valid field or method name for reference class “Foo13R5”
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }
+code for methods in class “Foo15R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] 123
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Ignored.Unknown#
+#{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }
+code for methods in class “Foo18R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] "fun"
+[1] "finalizer: 456"
+         used (Mb) gc trigger (Mb) max used (Mb)
+Ncells 247442 13.3     460000 24.6   350000 18.7
+Vcells 455966  3.5    1023718  7.9   784463  6.0
+
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
 #{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}
 [1] 1
 
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }
+code for methods in class “Foo28R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] 1
+
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Output.IgnoreErrorContext#
 #{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }
 Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
@@ -115,6 +224,11 @@ Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
 attr(,"package")
 [1] ".GlobalEnv"
 
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }
+code for methods in class “A6R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] "hello"
+
 ##com.oracle.truffle.r.test.S4.TestR5.testReferenceSemantics#
 #fooClass <- setRefClass('Foo12R5', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a
 [1] 1
@@ -167,6 +281,25 @@ Creating a generic function from function ‘foo.bar’ in the global environmen
 [1] "primitive, A, B"
 [1] "primitive, B, A"
 
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#Output.IgnoreErrorContext#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses0.R") }
+Error : invalid assignment for reference class field ‘aa’, should be from class “integer” or a subclass (was class “character”)
+code for methods in class “myRefClass3” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+Error : invalid assignment for reference class field ‘dd’, should be from class “numeric” or a subclass (was class “character”)
+code for methods in class “myRefClass4” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+code for methods in class “myRefClass5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+code for methods in class “myRefClass6” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses1.R") }
+code for methods in class “A5R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+code for methods in class “B5R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+[1] "A5R5$foo"
+
+##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses2.R") }
+code for methods in class “MatrixClass” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+
 ##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
 #.Internal(bindingIsActive(as.name('someSymbol4'), .GlobalEnv))
 Error: no binding for "someSymbol4"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R
new file mode 100644
index 0000000000..62a83df43e
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses0.R
@@ -0,0 +1,84 @@
+#IgnoreErrorContext
+# Create a new reference class, and an instance of it
+gen <- setRefClass("myRefClass", fields=list(aa="integer", bb="ANY"))
+x <- gen$new(aa=123L, bb=3.4)
+# Extract and set a field
+x$aa
+x$aa <- 456L
+## Not run: 
+# Generate an error on trying to set the field to a non-integer
+try(x$aa <- "notAnInteger")
+## End(Not run)
+# Can put any value in a field of type "ANY"
+x$bb <- "foo"
+# One way to create a new object:
+# Call the "new" method on a refObjectGenerator object
+xClass <- getRefClass("myRefClass")
+x <- xClass$new(aa=123L, bb=3.4)
+
+# A second way to create a new object:
+# Use the refObjectGenerator as a function
+xClass <- getRefClass("myRefClass")
+x <- xClass(aa=123L, bb=3.4)
+
+# A third way to create a new object:
+# Call the "new" function with the class name
+x <- new("myRefClass", aa=123L, bb=3.4)
+
+# Make reference class inheriting from the above class
+gen2 <- setRefClass("myRefClass2", contains="myRefClass",
+    fields=list(cc="character"))
+# Create instance specifying fields (including inherited ones)
+x2 <- gen2$new(aa=1L, bb=2.3, cc="foo")
+
+# Define reference class with a method
+gen3 <- setRefClass("myRefClass3", fields=list(dd="numeric"),
+    methods=list(getval=function() dd,
+        setval=function(value) dd <<- value))
+x3 <- gen3$new(dd=1.2)
+# Call methods to extract/set value of "dd" field
+x3$getval()     # returns 1.2
+x3$setval(3.4)
+x3$getval()     # now returns 3.4
+## Not run: 
+# Gives error if you try to set field to incorrect class
+try(x3$setval("foo"))
+## End(Not run)
+
+# Define subclass of the above class with a method calling callSuper
+gen4 <- setRefClass("myRefClass4", contains="myRefClass3",
+    methods=list(getval=function() 2*callSuper()))
+x4 <- gen4$new(dd=100)
+x4$getval() # returns 200
+
+# Define method with an "initialize" method modifying field values
+#   field "x" is set to twice the specified value, defaulting to 100
+#   field "y" is set to "none" if not specified explicitly
+gen5 <- setRefClass("myRefClass5", fields=list(x="numeric",y="character"),
+    methods=list(initialize=function(..., x=100L)
+        {x <<- 2*x; y <<- "none"; callSuper(...)}))
+gen5$new()        # initializes field "x" to 200, "y" to "none"
+gen5$new(x=10)    # initializes field "x" to 20, "y" to "none"
+gen5$new(y="abc") # initializes field "x" to 200, "y" to "abc"
+
+# Define a field as a function used for an active binding
+gen6 <- setRefClass("myRefClass6",
+    methods=list(initialize=function(...)
+        {saveVal <<- 0; numSet <<- 0; callSuper(...)}),
+        fields=list(saveVal="numeric", numSet="numeric", value=function(value) {
+            if(missing(value)) {
+                saveVal
+            } else {
+                numSet <<- numSet+1
+                saveVal <<- value
+                value
+      }}))
+x6 <- gen6$new()
+x6$value    # returns 0
+x6$numSet   # returns 0
+x6$value <- 123
+x6$value    # returns 123
+x6$numSet   # returns 1
+x6$value <- 456
+x6$value    # returns 456
+x6$numSet   # returns 2
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R
new file mode 100644
index 0000000000..73ac4e62b8
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses1.R
@@ -0,0 +1,5 @@
+setRefClass('A5R5', methods = list(foo = function() { print('A5R5$foo') }))
+setRefClass('B5R5', methods = list(foo = function() { print('B5R5$foo') }))
+C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5'))
+obj <- C5R5$new()
+obj$foo()
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R
new file mode 100644
index 0000000000..3d8561e950
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/R/refClasses2.R
@@ -0,0 +1,25 @@
+MatrixClass = setRefClass(
+Class = "MatrixClass",
+fields = list(
+dataMat = "matrix",
+detMat ="numeric",
+inverseMat = "matrix"))
+
+MatrixClass$methods(
+initialize = function(extMat = diag(1), ...){
+
+dataMat <<- extMat
+
+detMat <<- det(dataMat)
+if(abs(detMat) > 1e-7 ){
+inverseMat <<- solve(dataMat)
+}else{
+inverseMat <<- NULL
+}
+
+callSuper(...)
+})
+
+extMat = diag(3) * c(1,2,3)
+newMat = MatrixClass$new(extMat)
+newMat
\ No newline at end of file
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index bce46a1c84..f9955dfb45 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,9 @@ public class TestR5 extends TestBase {
         assertEval("{ DummyClass1 <- setRefClass('DummyClass1'); is(DummyClass1, 'refClass') }");
         assertEval("{ DummyClass2 <- setRefClass('DummyClass2'); obj <- DummyClass2$new(); is(obj, 'refObject') }");
         assertEval("{ fooClass <- setRefClass('Foo6R5', fields = list( a = 'numeric')); fooClass$new(a = 1) }");
-        assertEval(Ignored.ImplementationError, "{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }");
+        assertEval("{ fooClass <- setRefClass('Foo7R5', fields = list( a = 'numeric')); fooClass$new(1) }");
+        assertEval("{ setRefClass('Foo16R5'); ls(topenv(parent.frame()), all.names = T) }");
+        assertEval("env0 <- new.env(); setRefClass('Foo17R5', where = env0); ls(topenv(parent.frame()), all.names = T); ls(env0, all.names = T)");
     }
 
     @Test
@@ -58,6 +60,15 @@ public class TestR5 extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }");
         assertEval("{ clazz <- setRefClass('Foo5R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }");
         assertEval("{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
+        assertEval("{ clazz <- setRefClass('Foo13R5'); obj <- clazz$new(); obj$inexistingMethod() }");
+        assertEval("{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
+
+        // constructor
+        assertEval("{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }");
+        assertEval("{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }");
+
+        assertEval(Ignored.Unknown,
+                        "{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }");
     }
 
     @Test
@@ -68,6 +79,31 @@ public class TestR5 extends TestBase {
         assertEval("clazz <- setRefClass('Foo11R5', fields = list(a = 'character')); obj <- clazz$new(); obj$a <- 'hello'; obj$a; obj$a <- 10; obj$a");
     }
 
+    @Test
+    public void testFieldAccess() {
+        assertEval("{ clazz <- setRefClass('Foo14R5'); obj <- clazz$new(); obj$inexistingMethod() }");
+        assertEval("{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(); obj$a }");
+        assertEval("{ clazz <- setRefClass('Foo14R5', fields = c('a')); obj <- clazz$new(a = 1); print(obj$a); obj$a <- 'hello'; print(obj$a) }");
+
+        // list/modify methods
+        assertEval("{ clazz <- setRefClass('Foo19R5'); clazz$methods('inexistingMethod') }");
+        assertEval(Output.IgnoreWhitespace, "{ clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo') }");
+        assertEval("clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)");
+
+        // list available fields
+        assertEval("{ clazz <- setRefClass('Foo22R5'); clazz$fields() }");
+        assertEval("{ clazz <- setRefClass('Foo23R5', fields = c('a', 'b', 'c')); clazz$fields() }");
+        assertEval("{ clazz <- setRefClass('Foo24R5', fields = list(a = 'numeric')); clazz$fields() }");
+        assertEval("{ clazz <- setRefClass('Foo25R5', fields = list(a = 'numeric', b = 'character', c = 'raw')); clazz$fields() }");
+
+        // make field read-only; one assignment is allowed
+        assertEval("{ clazz <- setRefClass('Foo26R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a }");
+        assertEval("{ clazz <- setRefClass('Foo27R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a <- 20 }");
+
+        // generate getter and setter
+        assertEval(Ignored.ReferenceError, "{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() }");
+    }
+
     @Test
     public void testInheritance() {
         assertEval("A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a");
@@ -75,5 +111,6 @@ public class TestR5 extends TestBase {
         assertEval("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()");
         assertEval("A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
         assertEval("{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }");
+        assertEval("A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0)");
     }
 }
-- 
GitLab


From 716011a2ca4e66aa20f6007310675bf546a60833 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 17 Mar 2017 13:14:47 +0100
Subject: [PATCH 127/402] Removed unnecessary frame accesses.

---
 .../r/nodes/access/BaseWriteVariableNode.java | 16 +++++-----
 .../env/frame/REnvTruffleFrameAccess.java     | 30 ++++++++++++-------
 2 files changed, 28 insertions(+), 18 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index 509456715b..ab139b59ce 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -167,14 +167,14 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
      * @param invalidateProfile The invalidation profile.
      */
     protected static Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile) {
-        Object object;
-        try {
-            object = lookupFrame.getObject(frameSlot);
-        } catch (FrameSlotTypeException e) {
-            object = null;
-        }
-
-        if (object != null && ActiveBinding.isActiveBinding(object)) {
+        Object object = null;
+        if (FrameSlotChangeMonitor.isActiveBinding(frameSlot)) {
+            try {
+                object = lookupFrame.getObject(frameSlot);
+            } catch (FrameSlotTypeException e) {
+                // ignore
+            }
+            assert object != null && ActiveBinding.isActiveBinding(object);
             return ((ActiveBinding) object).writeValue(value);
         } else {
             FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, value, false, invalidateProfile);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
index 6259785656..44cf86ac90 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
@@ -28,7 +28,10 @@ import java.util.HashSet;
 import java.util.Set;
 import java.util.regex.Pattern;
 
+import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
@@ -55,6 +58,8 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
      */
     private Set<String> lockedBindings;
 
+    @CompilationFinal private Assumption containsNoActiveBindingAssumption;
+
     public REnvTruffleFrameAccess(MaterializedFrame frame) {
         this.frame = frame;
     }
@@ -71,9 +76,14 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
         if (slot == null) {
             return null;
         } else {
+
             Object value = frame.getValue(slot);
-            // TODO this could have tremendous performance impact !
-            if (ActiveBinding.isActiveBinding(value)) {
+            if (containsNoActiveBindingAssumption == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                containsNoActiveBindingAssumption = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(fd);
+            }
+            // special treatment for active binding: call bound function
+            if (containsNoActiveBindingAssumption != null && !containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(value)) {
                 return ((ActiveBinding) value).readValue();
             }
             return value;
@@ -109,14 +119,14 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
                 FrameSlotChangeMonitor.setDoubleAndInvalidate(frame, slot, (double) value, false, null);
                 break;
             case Object:
-                Object object;
-                try {
-                    object = frame.getObject(slot);
-                } catch (FrameSlotTypeException e) {
-                    object = null;
-                }
-
-                if (object != null && ActiveBinding.isActiveBinding(object)) {
+                if (FrameSlotChangeMonitor.isActiveBinding(slot)) {
+                    Object object;
+                    try {
+                        object = frame.getObject(slot);
+                    } catch (FrameSlotTypeException e) {
+                        object = null;
+                    }
+                    assert (object != null && ActiveBinding.isActiveBinding(object));
                     ((ActiveBinding) object).writeValue(value);
                 } else {
                     FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, value, false, null);
-- 
GitLab


From f81ae45fd0296a9f7ecfdcd653ac3f97a915529a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 17 Mar 2017 13:16:56 +0100
Subject: [PATCH 128/402] Fixed: Expected attributes for generic functions but
 builtins may not have any.

---
 .../truffle/r/nodes/objects/LoadMethod.java   | 53 ++++++++++---------
 .../truffle/r/test/ExpectedTestOutput.test    |  4 ++
 .../com/oracle/truffle/r/test/S4/TestS4.java  |  2 +
 3 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
index 449eabf4bd..236289defb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
@@ -71,33 +71,38 @@ abstract class LoadMethod extends RBaseNode {
                     @Cached("createClassProfile()") ValueProfile regFrameAccessProfile,
                     @Cached("createClassProfile()") ValueProfile methodsFrameAccessProfile) {
         DynamicObject attributes = fdef.getAttributes();
-        assert attributes != null; // should have at least class attribute
+        assert fdef.isBuiltin() || attributes != null;
         int found;
-        Object nextMethodAttr = nextMethodAttrAccess.execute(attributes);
-        // it's an optimization only where it's expected that either 2 or 4 attributes total will be
-        // present - anything else triggers execution of a generic S4 function
-        if (noNextMethodAttr.profile(nextMethodAttr == null)) {
-            found = 4; // class attribute plus three others are expected
-            Object targetAttr = targetAttrAccess.execute(attributes);
-            if (noTargetAttr.profile(targetAttr == null)) {
-                found--;
+        if (attributes != null) {
+            Object nextMethodAttr = nextMethodAttrAccess.execute(attributes);
+            // it's an optimization only where it's expected that either 2 or 4 attributes total
+            // will be
+            // present - anything else triggers execution of a generic S4 function
+            if (noNextMethodAttr.profile(nextMethodAttr == null)) {
+                found = 4; // class attribute plus three others are expected
+                Object targetAttr = targetAttrAccess.execute(attributes);
+                if (noTargetAttr.profile(targetAttr == null)) {
+                    found--;
+                } else {
+                    writeRTarget.execute(frame, targetAttr);
+                }
+                Object definedAttr = definedAttrAccess.execute(attributes);
+                if (noDefinedAttr.profile(definedAttr == null)) {
+                    found--;
+                } else {
+                    writeRDefined.execute(frame, definedAttr);
+                }
+                Object sourceAttr = sourceAttrAccess.execute(attributes);
+                if (sourceAttr == null) {
+                    noSourceAttr.enter();
+                    found--;
+                }
             } else {
-                writeRTarget.execute(frame, targetAttr);
-            }
-            Object definedAttr = definedAttrAccess.execute(attributes);
-            if (noDefinedAttr.profile(definedAttr == null)) {
-                found--;
-            } else {
-                writeRDefined.execute(frame, definedAttr);
-            }
-            Object sourceAttr = sourceAttrAccess.execute(attributes);
-            if (sourceAttr == null) {
-                noSourceAttr.enter();
-                found--;
+                found = 2; // next method attribute and class attribute
+                writeRNextMethod.execute(frame, nextMethodAttr);
             }
         } else {
-            found = 2; // next method attribute and class attribute
-            writeRNextMethod.execute(frame, nextMethodAttr);
+            found = 0;
         }
 
         writeRMethod.execute(frame, fdef);
@@ -109,7 +114,7 @@ abstract class LoadMethod extends RBaseNode {
         }
         assert !fname.equals(RRuntime.R_LOAD_METHOD_NAME);
         RFunction ret;
-        if (moreAttributes.profile(found < fdef.getAttributes().size())) {
+        if (fdef.getAttributes() != null && moreAttributes.profile(found < fdef.getAttributes().size())) {
             RFunction currentFunction;
             REnvironment methodsEnv = (REnvironment) methodsEnvRead.execute(frame, REnvironment.getNamespaceRegistry().getFrame(regFrameAccessProfile));
             if (loadMethodFind == null) {
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 44f31002f3..f633dc5882 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
@@ -490,6 +490,10 @@ Note: method with signature ‘A2#A1’ chosen for function ‘foo’,
  "A1#A2" would also be valid
 [1] "2-1"
 
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }
+[1] 10
+
 ##com.oracle.truffle.r.test.S4.TestS4.testMethods#
 #{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res }
 [1] "gen"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index a18472473c..938981f0e0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -123,6 +123,8 @@ public class TestS4 extends TestRBase {
         assertEval("{ setClass('A'); setClass('A1', contains = 'A'); setClass('A2', contains = 'A1'); setGeneric('foo', function(a, b) standardGeneric('foo')); setMethod('foo', signature('A1', 'A2'), function(a, b) '1-2'); setMethod('foo', signature('A2', 'A1'), function(a, b) '2-1'); foo(new('A2'), new('A2')) }");
 
         assertEval("setGeneric('do.call', signature = c('what', 'args'))");
+
+        assertEval("{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }");
     }
 
     @Test
-- 
GitLab


From 82c719b32fb7f50cc0a8602a24b4aa485ba635de Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 17 Mar 2017 14:56:07 +0100
Subject: [PATCH 129/402] Added test.

---
 .../oracle/truffle/r/runtime/context/RContext.java   |  1 +
 .../oracle/truffle/r/test/ExpectedTestOutput.test    | 12 ++++++++----
 .../src/com/oracle/truffle/r/test/S4/TestS4.java     |  7 ++++---
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 7edb1892a2..ccf6e7e7b1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -710,6 +710,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
         s4ExtendsTable.put(key, value);
     }
 
+    @TruffleBoundary
     public PrimitiveMethodsInfo getPrimitiveMethodsInfo() {
         if (primitiveMethodsInfo == null) {
             // shared contexts do not run concurrently with their parent and re-use primitive
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 f633dc5882..e829bc96b3 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
@@ -595,17 +595,21 @@ numeric(0)
 numeric(0)
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ setClass('Person', representation(name = 'character', age = 'numeric')); getSlots('Person') }
+#{ setClass('A0', representation(name = 'character', age = 'numeric')); getSlots('A0') }
        name         age
 "character"   "numeric"
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ setClass('Person', representation(name = 'character', age = 'numeric')); hadley <- new('Person', name = 'Hadley'); hadley@age }
+#{ setClass('A1', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); obj <- new('A1', name = 'FastR'); obj@age }
+[1] NA
+
+##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
+#{ setClass('A2', representation(name = 'character', age = 'numeric')); obj <- new('A2', name = 'FastR'); obj@age }
 numeric(0)
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
-#{ setClass('Person', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); hadley <- new('Person', name = 'Hadley'); hadley@age }
-[1] NA
+#{ setClass('A3', representation(name = 'character', age = 'numeric')); obj <- new('A3', name = 'FastR'); slot(obj, 'age') <- 5; obj@age }
+[1] 5
 
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotAccess#
 #{ x<-42; `@`(x, ".Data") }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 938981f0e0..7632dfa95c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -62,9 +62,10 @@ public class TestS4 extends TestRBase {
         assertEval(Output.IgnoreErrorContext, "{ x<-NULL; `@`(x, foo) }");
         assertEval(Output.IgnoreErrorContext, "{ x<-NULL; x@foo }");
         assertEval("{ x<-paste0(\".\", \"Data\"); y<-42; slot(y, x) }");
-        assertEval("{ setClass('Person', representation(name = 'character', age = 'numeric')); getSlots('Person') }");
-        assertEval("{ setClass('Person', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); hadley <- new('Person', name = 'Hadley'); hadley@age }");
-        assertEval("{ setClass('Person', representation(name = 'character', age = 'numeric')); hadley <- new('Person', name = 'Hadley'); hadley@age }");
+        assertEval("{ setClass('A0', representation(name = 'character', age = 'numeric')); getSlots('A0') }");
+        assertEval("{ setClass('A1', representation(name = 'character', age = 'numeric'), prototype(name = NA_character_, age = NA_real_)); obj <- new('A1', name = 'FastR'); obj@age }");
+        assertEval("{ setClass('A2', representation(name = 'character', age = 'numeric')); obj <- new('A2', name = 'FastR'); obj@age }");
+        assertEval("{ setClass('A3', representation(name = 'character', age = 'numeric')); obj <- new('A3', name = 'FastR'); slot(obj, 'age') <- 5; obj@age }");
     }
 
     @Test
-- 
GitLab


From eeca21c887da7ae7aa72174f6ad5fa5aee7de1ac Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Mon, 20 Mar 2017 12:24:39 +0100
Subject: [PATCH 130/402] PipelineReturnException handling fixed and other
 minor fixes

---
 .../CastBuilderTest.java                      | 27 ++++++++++++++-----
 .../CastUtilsTest.java                        |  2 +-
 .../ResultTypesAnalyserTest.java              |  5 ++--
 .../SampleCollectorTest.java                  |  5 ++--
 .../{builtin => castsTests}/TypeExprTest.java |  2 +-
 .../builtin/casts/PipelineToCastNode.java     |  2 +-
 .../r/nodes/unary/ChainedCastNode.java        | 15 ++++++++---
 .../oracle/truffle/r/runtime/RRuntime.java    |  4 +--
 8 files changed, 43 insertions(+), 19 deletions(-)
 rename com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/{builtin => castsTests}/CastBuilderTest.java (97%)
 rename com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/{builtin => castsTests}/CastUtilsTest.java (99%)
 rename com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/{builtin => castsTests}/ResultTypesAnalyserTest.java (99%)
 rename com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/{builtin => castsTests}/SampleCollectorTest.java (99%)
 rename com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/{builtin => castsTests}/TypeExprTest.java (99%)

diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
similarity index 97%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
index 0e432013b9..7a3a51a35b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
@@ -78,6 +78,9 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
@@ -93,6 +96,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -331,10 +335,10 @@ public class CastBuilderTest {
     public void testFindFirstWithoutDefaultValue() {
         arg.asIntegerVector().findFirst();
 
-        assertCastFail(RNull.instance, "argument is of length zero");
-        assertCastFail(RMissing.instance, "argument is of length zero");
-        assertCastFail(RDataFactory.createIntVector(0), "argument is of length zero");
-        assertCastFail(RDataFactory.createList(), "argument is of length zero");
+        assertCastFail(RNull.instance, "invalid 'x' argument");
+        assertCastFail(RMissing.instance, "invalid 'x' argument");
+        assertCastFail(RDataFactory.createIntVector(0), "invalid 'x' argument");
+        assertCastFail(RDataFactory.createList(), "invalid 'x' argument");
         assertEquals(1, cast(1));
         assertEquals(1, cast(RDataFactory.createIntVector(new int[]{1, 2}, true)));
         assertEquals(1, cast("1"));
@@ -399,7 +403,7 @@ public class CastBuilderTest {
         arg.asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         assertEquals(Boolean.TRUE, cast(RRuntime.LOGICAL_TRUE));
         assertEquals(Boolean.FALSE, cast(RRuntime.LOGICAL_FALSE));
-        assertEquals(Boolean.FALSE, cast(RRuntime.LOGICAL_NA));
+        assertEquals(Boolean.TRUE, cast(RRuntime.LOGICAL_NA));
         assertEquals(Boolean.TRUE, cast(RDataFactory.createLogicalVector(new byte[]{RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_FALSE}, true)));
         assertEquals(Boolean.FALSE, cast(RDataFactory.createLogicalVector(0)));
         testPipeline(NO_FILTER_EXPECT_EMPTY_SAMPLES);
@@ -872,6 +876,17 @@ public class CastBuilderTest {
         Assert.assertEquals(RError.Message.NA_INTRODUCED_COERCION.message, CastNode.getLastWarning());
     }
 
+    private static final RFunction DUMMY_FUNCTION = RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, null, null, null);
+
+    @Test
+    public void testReturnIfFunction() {
+        arg.allowNull().returnIf(instanceOf(RFunction.class)).asVector(false);
+        RFunction f = DUMMY_FUNCTION;
+        Object o = cast(f);
+        assertEquals(f, o);
+        testPipeline();
+    }
+
     /**
      * Casts given object using the configured pipeline in {@link #arg}.
      */
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java
index 00c93678c1..6b0be76aef 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastUtilsTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastUtilsTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import java.io.Serializable;
 import java.lang.reflect.Type;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
index d45c80d6e1..3cfa577f86 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
@@ -62,12 +62,13 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.oracle.truffle.r.nodes.builtin.CastBuilderTest.DummyBuiltin;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.casts.MarkLookup;
 import com.oracle.truffle.r.nodes.casts.ResultTypesAnalyser;
 import com.oracle.truffle.r.nodes.casts.TypeExpr;
+import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
index 52e252a035..38f3f15c26 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/SampleCollectorTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
@@ -57,10 +57,11 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.oracle.truffle.r.nodes.builtin.CastBuilderTest.DummyBuiltin;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder;
 import com.oracle.truffle.r.nodes.casts.SamplesCollector;
+import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java
similarity index 99%
rename from com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
rename to com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java
index a016195821..c9fa1f4d53 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/TypeExprTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/TypeExprTest.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
+package com.oracle.truffle.r.nodes.castsTests;
 
 import static com.oracle.truffle.r.nodes.casts.Not.negateType;
 import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index d00f5c16cb..1a2e496913 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -147,7 +147,7 @@ public final class PipelineToCastNode {
                     prevCastNode = node;
                 } else {
                     CastNode finalPrevCastNode = prevCastNode;
-                    prevCastNode = new ChainedCastNode(finalPrevCastNode, node);
+                    prevCastNode = new ChainedCastNode(finalPrevCastNode, node, currCastStep.getNext() == null);
                 }
             }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
index fb0da67ec9..ba239b34fe 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ChainedCastNode.java
@@ -37,17 +37,24 @@ public final class ChainedCastNode extends CastNode {
     @Child private CastNode firstCast;
     @Child private CastNode secondCast;
 
-    public ChainedCastNode(CastNode firstCast, CastNode secondCast) {
+    private final boolean isFirstNode;
+
+    public ChainedCastNode(CastNode firstCast, CastNode secondCast, boolean isFirstNode) {
         this.firstCast = firstCast;
         this.secondCast = secondCast;
+        this.isFirstNode = isFirstNode;
     }
 
     @Override
     public Object execute(Object value) {
-        try {
+        if (isFirstNode) {
+            try {
+                return secondCast.execute(firstCast.execute(value));
+            } catch (PipelineReturnException ex) {
+                return ex.getResult();
+            }
+        } else {
             return secondCast.execute(firstCast.execute(value));
-        } catch (PipelineReturnException ex) {
-            return ex.getResult();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 364e2d8484..2c4d20041d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -277,8 +277,8 @@ public class RRuntime {
         return b == LOGICAL_TRUE;
     }
 
-    public static boolean fromLogical(byte b, boolean naValue) {
-        return naValue ? b != LOGICAL_FALSE : b == LOGICAL_TRUE;
+    public static boolean fromLogical(byte b, boolean naReplacement) {
+        return naReplacement ? b != LOGICAL_FALSE : b == LOGICAL_TRUE;
     }
 
     // conversions from logical
-- 
GitLab


From 4eeb67a2e39d3ee3124db3ec18215dacf1c9b8da Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Mon, 20 Mar 2017 12:32:52 +0100
Subject: [PATCH 131/402] Minor fixes of issues found when working on
 prophet/shiny/knitr packages

---
 .../oracle/truffle/r/nodes/builtin/base/AsCall.java |  4 ++++
 .../oracle/truffle/r/nodes/builtin/base/Call.java   | 11 +++++++++++
 .../oracle/truffle/r/nodes/builtin/base/Eval.java   |  5 +++++
 .../src/com/oracle/truffle/r/runtime/RType.java     |  3 ++-
 .../oracle/truffle/r/test/ExpectedTestOutput.test   | 13 +++++++++++++
 .../truffle/r/test/builtins/TestBuiltin_eval.java   |  8 +++++++-
 .../test/builtins/TestBuiltin_extract_replace.java  |  8 +++++++-
 documentation/dev/testing.md                        | 10 ++++++----
 8 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index 136f10c14c..c374db6cb7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -68,6 +68,10 @@ public abstract class AsCall extends RBuiltinNode {
             return Call.makeCallSourceUnavailable(((RAbstractStringVector) x.getDataAt(0)).getDataAt(0), avn);
         } else if (x.getDataAt(0) instanceof RFunction) {
             return Call.makeCallSourceUnavailable((RFunction) x.getDataAt(0), avn);
+        } else if (x.getDataAt(0) instanceof Integer) {
+            return Call.makeCallSourceUnavailable((Integer) x.getDataAt(0), avn);
+        } else if (x.getDataAt(0) instanceof Double) {
+            return Call.makeCallSourceUnavailable((Double) x.getDataAt(0), avn);
         } else {
             throw RInternalError.unimplemented();
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index ed84a24405..5f04839d3b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.RASTUtils;
+import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -105,6 +106,16 @@ public abstract class Call extends RBuiltinNode {
         return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.createFunctionLookup(RSyntaxNode.LAZY_DEPARSE, name), true, args);
     }
 
+    @TruffleBoundary
+    protected static RLanguage makeCallSourceUnavailable(int i, RArgsValuesAndNames args) {
+        return makeCall0(ConstantNode.create(i), true, args);
+    }
+
+    @TruffleBoundary
+    protected static RLanguage makeCallSourceUnavailable(double d, RArgsValuesAndNames args) {
+        return makeCall0(ConstantNode.create(d), true, args);
+    }
+
     @TruffleBoundary
     protected static RLanguage makeCallSourceUnavailable(RFunction function, RArgsValuesAndNames args) {
         return makeCall0(function, true, args);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
index 3367d84ad0..00e8d03e3f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RExpression;
@@ -146,6 +147,8 @@ public abstract class Eval extends RBuiltinNode {
         REnvironment environment = envCast.execute(frame, envir, enclos);
         try {
             return RContext.getEngine().eval(expr, environment, rCaller);
+        } catch (ReturnException ret) {
+            return ret.getResult();
         } finally {
             visibility.executeAfterCall(frame, rCaller);
         }
@@ -157,6 +160,8 @@ public abstract class Eval extends RBuiltinNode {
         REnvironment environment = envCast.execute(frame, envir, enclos);
         try {
             return RContext.getEngine().eval(expr, environment, rCaller);
+        } catch (ReturnException ret) {
+            return ret.getResult();
         } finally {
             visibility.executeAfterCall(frame, rCaller);
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
index 9ee98c9d78..9487504ff9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -98,6 +98,7 @@ public enum RType {
             case Character:
             case Raw:
             case List:
+            case Expression:
                 return true;
             default:
                 return false;
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 5fc5fb2db8..6124052917 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
@@ -22281,6 +22281,11 @@ x
 #{ ne <- new.env(); evalq(x <- 1, ne); ls(ne) }
 [1] "x"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testReturnInEvalExpr#
+#f1 <- function(x) { eval(quote(if(x>2){return()}else 1)); 10 };f1(5);f1(0)
+[1] 10
+[1] 10
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testWithEnvirAndEnclose#
 #a <- 1; lang <- quote(list(a)); eval(lang, NULL, NULL)
 Error in eval(expr, envir, enclos) : object 'a' not found
@@ -22908,6 +22913,14 @@ Levels: A B C D E
 #tmp <- c(1,8,NA,3); pivot <- c(1,2,4,3); tmp[pivot] <- tmp; tmp
 [1]  1  8  3 NA
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceExpressionInLanguage#Ignored.OutputFormatting#
+#e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1
+(x^2)(y, 2)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceExpressionInLanguage#
+#e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1[[1]]==e1[[1]]
+[1] TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceInLanguagePreservesAttributes#
 #f <- quote(a+b); attr(f, 'mya') <- 42; f[[2]] <- quote(q); f
 q + b
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java
index a87bc5a748..d1b9210eb8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -60,4 +60,10 @@ public class TestBuiltin_eval extends TestBase {
         assertEval("a <- 1; lang <- quote(list(a)); eval(lang, new.env(), new.env())");
         assertEval(Output.IgnoreErrorMessage, "y <- 2; x <- 2 ; eval(quote(x+y), c(-1, -2))");
     }
+
+    @Test
+    public void testReturnInEvalExpr() {
+        assertEval("f1 <- function(x) { eval(quote(if(x>2){return()}else 1)); 10 };f1(5);f1(0)");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java
index f841282b01..3745256f04 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,4 +42,10 @@ public class TestBuiltin_extract_replace extends TestBase {
     public void replaceInLanguagePreservesAttributes() {
         assertEval("f <- quote(a+b); attr(f, 'mya') <- 42; f[[2]] <- quote(q); f");
     }
+
+    @Test
+    public void replaceExpressionInLanguage() {
+        assertEval("e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1[[1]]==e1[[1]]");
+        assertEval(Ignored.OutputFormatting, "e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1");
+    }
 }
diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index 0e6ed21eab..cb82ac7ec8 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -54,7 +54,7 @@ Package developers can provide tests in several ways. To enable the full set of
 
 ### Package Installation and Testing
 
-Package installation and testing is partly handled by a R script `install.packages.R` in the `com.oracle.truffle.r.test.packages` project and partly by an `mx` script. There are two relevant `mx` commands, `installpkgs` and `pkgtest`. The former is simply a wrapper to `install.packages.R`, whereas `pkgtest` contains additional code to gather and compare test outputs.
+Package installation and testing is partly handled by a R script `r/install.packages.R` in the `com.oracle.truffle.r.test.packages` project and partly by an `mx` script. There are two relevant `mx` commands, `installpkgs` and `pkgtest`. The former is simply a wrapper to `install.packages.R`, whereas `pkgtest` contains additional code to gather and compare test outputs.
 
 #### The install.packages.R script
 
@@ -93,9 +93,11 @@ Key concepts are discussed below.
 
 ##### Package Blacklist
 
-There are many packages that cannot be installed due to either missing functionality or fundamental limitations in FastR and this set is seeded from a a DCF file, `initial.package.blacklist`, in the `com.oracle.truffle.r.test.packages` project. `install.packages` operates in two modes, either creating a complete blacklist from an initial blacklist or reading a previously created blacklist file. In the latter case, if the blacklist file does not exist, it will be created. The complete blacklist file can specified in three ways:
+There are many packages that cannot be installed due to either missing functionality or fundamental limitations in FastR and this set is seeded from a a DCF file, `initial.package.blacklist`, in the `com.oracle.truffle.r.test.packages` project. `install.packages` operates in two modes, either creating a complete blacklist from an initial blacklist or reading a previously created blacklist file. In the latter case, if the blacklist file does not exist, it will be created. The complete blacklist file can be specified in three ways:
 
 1. using the command line argument `--blacklist-file`; if omitted defaults to the file `package.blacklist`
+2. TODO
+3. TODO
 
 ##### CRAN Mirror
 Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with the command line argument `--cran-mirror` or the environment variable `CRAN_MIRROR`.  The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. It also implies `CRAN`.
@@ -106,9 +108,9 @@ The directory in which to install the package can be specified either by setting
 ##### Specifying packages to Install
 If the `--pkg-filelist` argument is provided then the associated file should contain a list of packages to install, one per line. Otherwise if a package pattern argument is given, then all packages matching the (R) regular expression are candidates for installation, otherwise all available packages are candidates, computed by invoking the `available.packages()` function. The candidate set can be adjusted with additional options.  The `--use-installed.pkgs` option will cause `install.packages` to analyze the package installation directory for existing successfully installed packages and remove those from the candidate set. Some convenience options implicitly set `--pkg-filelist`, namely:
 
-    --ok-only: sets it to the file `com.oracle.truffle.r.test.packages.ok.packages`. This file is a list of packages that are known to install.
+    --ok-only: sets it to the file `com.oracle.truffle.r.test.packages/ok.packages`. This file is a list of packages that are known to install.
 
-N.B. The is file is updated only occasionally. Regressions, bug fixes, can render it inaccurate.
+N.B. This file is updated only occasionally. Regressions, bug fixes, can render it inaccurate.
 
 Two options are designed to be used for a daily package testing run. These are based on the day of the year and install/test a rolling set of packages:
 
-- 
GitLab


From 9e53d51aa9e7a1b1a79fe9bae35e14987563ef07 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 21 Mar 2017 09:41:20 +0100
Subject: [PATCH 132/402] Cleanups

---
 .../truffle/r/engine/interop/RFunctionMR.java |  9 ++++--
 .../r/nodes/builtin/base/UpdateSubstr.java    |  2 +-
 .../r/nodes/access/BaseWriteVariableNode.java | 19 +++++++------
 .../access/WriteLocalFrameVariableNode.java   |  6 ++--
 .../access/WriteSuperFrameVariableNode.java   |  3 +-
 .../variables/LocalReadVariableNode.java      |  2 +-
 .../r/nodes/function/ClassHierarchyNode.java  |  8 ------
 .../env/frame/FrameSlotChangeMonitor.java     | 20 +------------
 .../env/frame/REnvTruffleFrameAccess.java     | 28 ++++++-------------
 9 files changed, 35 insertions(+), 62 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index 8001e76066..18e449ccd9 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -41,6 +41,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 @MessageResolution(receiverType = RFunction.class, language = TruffleRLanguage.class)
 public class RFunctionMR {
@@ -54,8 +55,12 @@ public class RFunctionMR {
     @Resolve(message = "EXECUTE")
     public abstract static class RFunctionExecuteNode extends Node {
         private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("R interop frame");
-        private final Object argsIdentifier = new Object();
-        private final FrameSlot slot = emptyFrameDescriptor.addFrameSlot(argsIdentifier, FrameSlotKind.Object);
+        private static final Object argsIdentifier = new Object();
+        private static final FrameSlot slot = emptyFrameDescriptor.addFrameSlot(argsIdentifier, FrameSlotKind.Object);
+
+        static {
+            FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<function>", emptyFrameDescriptor);
+        }
 
         @Child private RCallBaseNode call = RCallNode.createExplicitCall(argsIdentifier);
         @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
index 87164398f9..c986eecf12 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index ab139b59ce..2cb9365d10 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -166,15 +166,16 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
      * @param frameSlot The frame slot of the value.
      * @param invalidateProfile The invalidation profile.
      */
-    protected static Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile) {
-        Object object = null;
-        if (FrameSlotChangeMonitor.isActiveBinding(frameSlot)) {
-            try {
-                object = lookupFrame.getObject(frameSlot);
-            } catch (FrameSlotTypeException e) {
-                // ignore
-            }
-            assert object != null && ActiveBinding.isActiveBinding(object);
+    protected static Object handleActiveBinding(VirtualFrame execFrame, Frame lookupFrame, Object value, FrameSlot frameSlot, BranchProfile invalidateProfile,
+                    ConditionProfile isActiveBindingProfile) {
+        Object object;
+        try {
+            object = lookupFrame.getObject(frameSlot);
+        } catch (FrameSlotTypeException e) {
+            object = null;
+        }
+
+        if (isActiveBindingProfile.profile(object != null && ActiveBinding.isActiveBinding(object))) {
             return ((ActiveBinding) object).writeValue(value);
         } else {
             FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, value, false, invalidateProfile);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
index e319aeab36..8e953b8420 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -56,6 +57,7 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode
 
     private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
     private final BranchProfile invalidateProfile = BranchProfile.create();
+    private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile();
     @CompilationFinal private Assumption containsNoActiveBinding;
 
     protected WriteLocalFrameVariableNode(Object name, Mode mode) {
@@ -95,12 +97,12 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode
             CompilerDirectives.transferToInterpreterAndInvalidate();
             containsNoActiveBinding = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(frame.getFrameDescriptor());
         }
-        if (containsNoActiveBinding != null && containsNoActiveBinding.isValid()) {
+        if (containsNoActiveBinding.isValid()) {
             Object newValue = shareObjectValue(frame, frameSlot, storedObjectProfile.profile(value), mode, false);
             FrameSlotChangeMonitor.setObjectAndInvalidate(frame, frameSlot, newValue, false, invalidateProfile);
         } else {
             // it's a local variable lookup; so use 'frame' for both, executing and looking up
-            return handleActiveBinding(frame, frame, value, frameSlot, invalidateProfile);
+            return handleActiveBinding(frame, frame, value, frameSlot, invalidateProfile, isActiveBindingProfile);
         }
         return value;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
index 7cd8ff8d00..bbc7d82a5b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
@@ -73,6 +73,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         private final ValueProfile storedObjectProfile = ValueProfile.createClassProfile();
         private final BranchProfile invalidateProfile = BranchProfile.create();
         private final ValueProfile enclosingFrameProfile = ValueProfile.createClassProfile();
+        private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile();
 
         private final Mode mode;
         @CompilationFinal private Assumption containsNoActiveBinding;
@@ -110,7 +111,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
                 Object newValue = shareObjectValue(profiledFrame, frameSlot, storedObjectProfile.profile(value), mode, true);
                 FrameSlotChangeMonitor.setObjectAndInvalidate(profiledFrame, frameSlot, newValue, true, invalidateProfile);
             } else {
-                handleActiveBinding(frame, profiledFrame, value, frameSlot, invalidateProfile);
+                handleActiveBinding(frame, profiledFrame, value, frameSlot, invalidateProfile, isActiveBindingProfile);
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
index c5cf895eeb..5e1b476097 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
@@ -116,7 +116,7 @@ public final class LocalReadVariableNode extends Node {
             containsNoActiveBindingAssumption = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(profiledVariableFrame.getFrameDescriptor());
         }
         // special treatment for active binding: call bound function
-        if (containsNoActiveBindingAssumption != null && !containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) {
+        if (!containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) {
             return ((ActiveBinding) result).readValue();
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index 119494163d..dd4a98c595 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -53,7 +53,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class ClassHierarchyNode extends UnaryNode {
@@ -150,13 +149,6 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return obj instanceof RTypedValue;
     }
 
-    @TruffleBoundary
-    @Specialization
-    protected RStringVector getClassHrActiveBinding(ActiveBinding object) {
-        Object result = RContext.getEngine().evalFunction(object.getFunction(), REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), RDataFactory.createEmptyStringVector());
-        return execute(result);
-    }
-
     @Specialization(guards = "!isRTypedValue(object)")
     protected RStringVector getClassHrTruffleObject(@SuppressWarnings("unused") TruffleObject object) {
         return truffleObjectClassHeader;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 1211aea3fc..0f4f3a09ad 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -467,9 +467,6 @@ public final class FrameSlotChangeMonitor {
         @CompilationFinal private StableValue<Object> stableValue;
         private int invalidationCount;
 
-        // TODO @CompilationFinal ?
-        @CompilationFinal private boolean activeBinding;
-
         FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier) {
             if (isSingletonFrame) {
                 stableValue = new StableValue<>(null, identifier.toString());
@@ -509,7 +506,6 @@ public final class FrameSlotChangeMonitor {
             if (stableValue != null && stableValue.getValue() != value) {
                 invalidateStableValue(value, slot);
             }
-            activeBinding = ActiveBinding.isActiveBinding(value);
         }
 
         private void invalidateStableValue(Object value, FrameSlot slot) {
@@ -528,10 +524,6 @@ public final class FrameSlotChangeMonitor {
         public StableValue<Object> getStableValue() {
             return stableValue;
         }
-
-        public boolean isActiveBinding() {
-            return activeBinding;
-        }
     }
 
     /**
@@ -658,13 +650,7 @@ public final class FrameSlotChangeMonitor {
 
     public static synchronized Assumption getContainsNoActiveBindingAssumption(FrameDescriptor descriptor) {
         CompilerAsserts.neverPartOfCompilation();
-        final FrameDescriptorMetaData frameDescriptorMetaData = frameDescriptors.get(descriptor);
-        return frameDescriptorMetaData != null ? frameDescriptorMetaData.getContainsNoActiveBindingAssumption() : null;
-    }
-
-    public static synchronized boolean isContainsNoActiveBindingAssumptionValid(FrameDescriptor descriptor) {
-        Assumption assumption = getContainsNoActiveBindingAssumption(descriptor);
-        return assumption != null ? assumption.isValid() : true;
+        return frameDescriptors.get(descriptor).getContainsNoActiveBindingAssumption();
     }
 
     public static synchronized StableValue<Object> getStableValueAssumption(FrameDescriptor descriptor, FrameSlot frameSlot, Object value) {
@@ -686,8 +672,4 @@ public final class FrameSlotChangeMonitor {
     public static boolean isValidFrameDescriptor(FrameDescriptor frameDesc) {
         return getMetaData(frameDesc) != null;
     }
-
-    public static boolean isActiveBinding(FrameSlot slot) {
-        return ((FrameSlotInfoImpl) slot.getInfo()).isActiveBinding();
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
index 44cf86ac90..2c62896ff5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
@@ -28,10 +28,7 @@ import java.util.HashSet;
 import java.util.Set;
 import java.util.regex.Pattern;
 
-import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
@@ -58,8 +55,6 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
      */
     private Set<String> lockedBindings;
 
-    @CompilationFinal private Assumption containsNoActiveBindingAssumption;
-
     public REnvTruffleFrameAccess(MaterializedFrame frame) {
         this.frame = frame;
     }
@@ -76,14 +71,9 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
         if (slot == null) {
             return null;
         } else {
-
             Object value = frame.getValue(slot);
-            if (containsNoActiveBindingAssumption == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                containsNoActiveBindingAssumption = FrameSlotChangeMonitor.getContainsNoActiveBindingAssumption(fd);
-            }
             // special treatment for active binding: call bound function
-            if (containsNoActiveBindingAssumption != null && !containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(value)) {
+            if (ActiveBinding.isActiveBinding(value)) {
                 return ((ActiveBinding) value).readValue();
             }
             return value;
@@ -119,14 +109,14 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
                 FrameSlotChangeMonitor.setDoubleAndInvalidate(frame, slot, (double) value, false, null);
                 break;
             case Object:
-                if (FrameSlotChangeMonitor.isActiveBinding(slot)) {
-                    Object object;
-                    try {
-                        object = frame.getObject(slot);
-                    } catch (FrameSlotTypeException e) {
-                        object = null;
-                    }
-                    assert (object != null && ActiveBinding.isActiveBinding(object));
+                Object object;
+                try {
+                    object = frame.getObject(slot);
+                } catch (FrameSlotTypeException e) {
+                    object = null;
+                }
+
+                if (object != null && ActiveBinding.isActiveBinding(object)) {
                     ((ActiveBinding) object).writeValue(value);
                 } else {
                     FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, value, false, null);
-- 
GitLab


From 906c4d5f809120d84670b689417c1de07bda3891 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Mon, 20 Mar 2017 16:05:32 +0100
Subject: [PATCH 133/402] Fix: temporary shareable should not be 'value' of
 explicit RPromise

---
 .../truffle/r/nodes/function/PromiseHelperNode.java   | 11 +++++++++++
 .../com/oracle/truffle/r/test/ExpectedTestOutput.test |  8 ++++++++
 .../r/test/library/base/TestPromiseOptimizations.java |  8 +++++++-
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index 5dfa524184..aa95117cb5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -50,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
+import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
@@ -237,6 +238,16 @@ public class PromiseHelperNode extends RBaseNode {
                     return promise.getValue();
                 }
                 Object obj = generateValueDefaultSlowPath(frame, promise);
+                // if the value is temporary, we increment the reference count. The reason is that
+                // temporary values are considered available to be reused and altered (e.g. as a
+                // result of arithmetic operation), which is what we do not want to happen to a
+                // value that we are saving as the promise result.
+                if (obj instanceof RShareable) {
+                    RShareable shareable = (RShareable) obj;
+                    if (shareable.isTemporary()) {
+                        shareable.incRefCount();
+                    }
+                }
                 promise.setValue(obj);
                 return obj;
             }
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 83b6bca2e5..914b2734b3 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
@@ -77177,6 +77177,10 @@ Error in get("x") : object 'x' not found
 #{ x <- function(){3} ; gg <- function() { assign("x", 4) ; g <- function() { if (FALSE) { x <- 2 } ; f <- function() { h <- function() { x() } ; h() } ; f() } ; g() } ; gg() }
 [1] 3
 
+##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization#
+#{ delayedAssign('x', c(1,2,3)); x/180; x }
+[1] 1 2 3
+
 ##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization#
 #{ f <- function(x) { assign('e', function() {x}, parent.frame()) } ; a <- 1 ; f( a ) ; a <- 10 ; e() }
 [1] 10
@@ -77217,6 +77221,10 @@ Error in get("x") : object 'x' not found
 #{ f <- function(x) { sys.frame(sys.nframe()) } ; a <- 1 ; e <- f( a ) ; a <- 10 ; e$x }
 [1] 10
 
+##com.oracle.truffle.r.test.library.base.TestPromiseOptimizations.testDeoptimization#
+#{ pi/180; pi }
+[1] 3.141593
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testArithmeticUpdate#
 #{ x <- 3 ; f <- function(z) { if (z) { x <- 1 } ; x <- 1L + x ; x } ; f(FALSE) }
 [1] 4
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java
index 07a77a76c6..b15e3ead2c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestPromiseOptimizations.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,5 +61,11 @@ public class TestPromiseOptimizations extends TestBase {
 
         // "delayedAssign" RFunction: (Special case of but handled by: delayedAssign)
         assertEval("{ f <- function(x) { delayedAssign('b', function() {x}, sys.frame(sys.nframe()), parent.frame()); } ; a <- 1 ; f( a ) ; a <- 10 ; b() }");
+
+        // the value of 'pi' promise may look like temporary vector, but the arithmetic operation
+        // must not re-use it for the result
+        assertEval("{ pi/180; pi }");
+        // similar situation as above
+        assertEval("{ delayedAssign('x', c(1,2,3)); x/180; x }");
     }
 }
-- 
GitLab


From 4790b3420b7ba9077eaeb1b72b397bb318bca490 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Mar 2017 11:33:28 +0100
Subject: [PATCH 134/402] fix various formatting issues, tiny fix in D

---
 .../truffle/r/library/grid/GridFunctions.java |  2 --
 .../truffle/r/library/stats/deriv/D.java      |  8 ++---
 .../builtin/base/SerializeFunctions.java      |  5 ++--
 .../r/nodes/castsTests/CastBuilderTest.java   |  2 --
 .../test/ForwardedValuesAnalyserTest.java     |  8 +----
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |  1 -
 .../truffle/r/test/ExpectedTestOutput.test    |  6 +++-
 .../r/test/builtins/TestBuiltin_D.java        |  2 +-
 .../test/builtins/TestBuiltin_asPOSIXlt.java  |  1 -
 .../builtins/TestBuiltin_bitwiseShiftR.java   |  1 -
 .../builtins/TestBuiltin_classassign.java     |  1 -
 .../r/test/builtins/TestBuiltin_deriv.java    | 30 +++++++------------
 .../r/test/library/base/TestConnections.java  |  2 --
 13 files changed, 24 insertions(+), 45 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
index d7a155a96f..a5b48baf87 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
@@ -17,9 +17,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.library.stats.Cdist;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
index 8180a40c81..f0d059510d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/D.java
@@ -37,13 +37,11 @@ import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
@@ -88,6 +86,9 @@ public abstract class D extends RExternalBuiltinNode.Arg2 {
     @TruffleBoundary
     protected Object doD(RExpression expr, String var,
                     @Cached("create()") D dNode) {
+        if (expr.getLength() == 0) {
+            return RRuntime.DOUBLE_NA;
+        }
         return dNode.execute(expr.getDataAt(0), var);
     }
 
@@ -97,5 +98,4 @@ public abstract class D extends RExternalBuiltinNode.Arg2 {
         dExpr = Deriv.addParens(dExpr);
         return RASTUtils.createLanguageElement(dExpr);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
index 7ae7101b3d..7ca7bccf00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
@@ -135,10 +135,11 @@ public class SerializeFunctions {
             return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook);
         }
 
+        @SuppressWarnings("unused")
         @Specialization
         protected Object doSerializeToConn(Object object, int conn, byte asciiLogical, int version, Object refhook) {
-            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 4); // [TODO] implement
-                                                                                // "version" support
+            // TODO: implement "version" support
+            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 4);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
index 7a3a51a35b..5e36f005de 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
@@ -78,8 +78,6 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-import com.oracle.truffle.api.RootCallTarget;
-import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
index ccaa151114..e422add155 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
@@ -22,12 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -36,7 +30,6 @@ import org.junit.Test;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.AndFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.CompareFilter.ScalarValue;
-import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.DoubleFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.MissingFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.NotFilter;
@@ -44,6 +37,7 @@ import com.oracle.truffle.r.nodes.builtin.casts.Filter.NullFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.OrFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.RTypeFilter;
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
+import com.oracle.truffle.r.nodes.builtin.casts.Mapper.MapByteToBoolean;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
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 14b6e3611b..86f784db14 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
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 83b6bca2e5..2768d468a5 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
@@ -158,6 +158,10 @@ Error in df(0) : argument "df1" is missing, with no default
 2 * x * sin(x) + x^2 * cos(x)
 Error in df(0) : argument "df1" is missing, with no default
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
+#D(expression(), 'a')
+[1] NA
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_D.testD#
 #g<-quote(x^2);(df <- D(g, "x"));df(0)
 2 * x
@@ -17825,7 +17829,7 @@ expression({
     .value
 })
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveBasicExpressions2#
 #deriv(~ x^y, c("x","y"), hessian=FALSE)
 expression({
     .expr1 <- x^y
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
index 6fd2878571..1310bf7bd9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_D.java
@@ -35,6 +35,6 @@ public class TestBuiltin_D extends TestBase {
         assertEval("g<-quote(x^2);(df <- D(g, \"x\"));df(0)");
         assertEval("(df <- D(1, \"x\"));df(0)");
         assertEval("x<-1;(df <- D(x, \"x\"));df(0)");
+        assertEval("D(expression(), 'a')");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java
index 782fe19c2e..eec124843f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asPOSIXlt.java
@@ -13,7 +13,6 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
-import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_asPOSIXlt extends TestBase {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
index 436951f231..0f441d89da 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bitwiseShiftR.java
@@ -13,7 +13,6 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
-import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_bitwiseShiftR extends TestBase {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java
index 307c2f258c..28e7365e5a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_classassign.java
@@ -13,7 +13,6 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
-import com.oracle.truffle.r.test.TestBase.Output;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_classassign extends TestBase {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
index 13eae8aaf3..63dfe59737 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
@@ -131,8 +131,7 @@ public class TestBuiltin_deriv extends TestBase {
 
     @Test
     public void testDeriveFunctions1() {
-        deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(Ignored.MissingWarning,
-                        -1);
+        deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(Ignored.MissingWarning, -1);
         assertDerivAndEval1("exp(x)");
         assertDerivAndEval1("cos(x)");
         assertDerivAndEval1("sin(x)");
@@ -166,25 +165,16 @@ public class TestBuiltin_deriv extends TestBase {
         assertDerivAndEval2("x + y");
         deriv2("x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
         deriv2("2*x*y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
-        deriv2("x/y/2").derive(Ignored.OutputFormatting).eval(0,
-                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
-        deriv2("2/x*y").derive(Ignored.OutputFormatting).eval(0,
-                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
-        deriv2("x^y").derive(Ignored.OutputFormatting).eval(0,
-                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
-        deriv2("(x+1)*(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
-                        0);
+        deriv2("x/y/2").derive(Ignored.OutputFormatting).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("2/x*y").derive(Ignored.OutputFormatting).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("x^y").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)*(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
         assertDerivAndEval2("(x+1)-(y+2)");
-        deriv2("-(x+1)+(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
-                        0);
-        deriv2("-(x+1)-(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
-                        0);
-        deriv2("(x+1)/(y+2)").derive(Ignored.OutputFormatting).eval(0,
-                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
-        deriv2("(x+1)*(y+2*(x-1))").derive().eval(0,
-                        0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
-        deriv2("(x+1)^(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0,
-                        0).eval(1, 1);
+        deriv2("-(x+1)+(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("-(x+1)-(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)/(y+2)").derive(Ignored.OutputFormatting).eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)*(y+2*(x-1))").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0);
+        deriv2("(x+1)^(y+2)").derive().eval(0, 0).withHessian().derive(Ignored.OutputFormatting).eval(0, 0).eval(1, 1);
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 16b5b13370..7ef2680d0a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.test.library.base;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -38,7 +37,6 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
 import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel;
 import com.oracle.truffle.r.test.TestBase;
-- 
GitLab


From 9360e080376ff6ec957b255bdb123013ac55cd42 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Mar 2017 11:33:54 +0100
Subject: [PATCH 135/402] update Truffle version

---
 mx.fastr/suite.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index b24b44508b..ea8973c6b8 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -28,7 +28,7 @@ suite = {
     "suites" : [
             {
                "name" : "truffle",
-               "version" : "1350be0c0c0c52b9b2d6136dfc07466d73ab217f",
+               "version" : "e4c752d5477f3177b30ba80af7cd3c3e61329d2e",
                "urls" : [
                     {"url" : "https://github.com/graalvm/truffle", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From ada79d4d4d62e804f7daf9e234f1ed4b43efc2a2 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 9 Mar 2017 12:57:20 +0100
Subject: [PATCH 136/402] use JavaInterop to wrap/unwrap ContextInfo and
 RContext objects

---
 .../r/nodes/builtin/fastr/FastRContext.java        |  6 ++++--
 .../truffle/r/runtime/context/ContextInfo.java     | 14 ++++----------
 .../oracle/truffle/r/runtime/context/RContext.java | 13 ++++---------
 3 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index f05e725df8..58ec42838e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -36,6 +36,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -87,8 +89,8 @@ public class FastRContext {
     public abstract static class Get extends RBuiltinNode {
         @Specialization
         @TruffleBoundary
-        protected Object get() {
-            return RContext.getInstance();
+        protected TruffleObject get() {
+            return JavaInterop.asTruffleObject(RContext.getInstance());
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index 5e7770a8ea..d048d22828 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -25,8 +25,7 @@ package com.oracle.truffle.r.runtime.context;
 import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
@@ -39,7 +38,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
  * Use {@link #createVM()} to apply this information to a newly-built {@link PolyglotEngine}
  * instance (it will be stored in the "fastrContextInfo" global symbol).
  */
-public final class ContextInfo implements TruffleObject {
+public final class ContextInfo {
     public static final String GLOBAL_SYMBOL = "fastrContextInfo";
 
     private static final AtomicInteger contextInfoIds = new AtomicInteger();
@@ -69,13 +68,13 @@ public final class ContextInfo implements TruffleObject {
     }
 
     public PolyglotEngine createVM() {
-        PolyglotEngine newVM = PolyglotEngine.newBuilder().globalSymbol(GLOBAL_SYMBOL, this).build();
+        PolyglotEngine newVM = PolyglotEngine.newBuilder().globalSymbol(GLOBAL_SYMBOL, JavaInterop.asTruffleObject(this)).build();
         this.vm = newVM;
         return newVM;
     }
 
     public PolyglotEngine createVM(PolyglotEngine.Builder builder) {
-        PolyglotEngine newVM = builder.globalSymbol(GLOBAL_SYMBOL, this).build();
+        PolyglotEngine newVM = builder.globalSymbol(GLOBAL_SYMBOL, JavaInterop.asTruffleObject(this)).build();
         this.vm = newVM;
         return newVM;
     }
@@ -150,9 +149,4 @@ public final class ContextInfo implements TruffleObject {
     public PolyglotEngine getVM() {
         return vm;
     }
-
-    @Override
-    public ForeignAccess getForeignAccess() {
-        throw new IllegalStateException("cannot access " + ContextInfo.class.getSimpleName() + " via Truffle");
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 7edb1892a2..28176f1148 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -39,8 +39,8 @@ import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
-import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ExitException;
@@ -97,7 +97,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  *
  * Contexts can be destroyed
  */
-public final class RContext extends ExecutionContext implements TruffleObject {
+public final class RContext extends ExecutionContext {
 
     public static final int CONSOLE_WIDTH = 80;
 
@@ -445,7 +445,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
      * @param isInitial {@code true} if this is the initial (primordial) context.
      */
     private RContext(Env env, Instrumenter instrumenter, boolean isInitial) {
-        ContextInfo initialInfo = (ContextInfo) env.importSymbol(ContextInfo.GLOBAL_SYMBOL);
+        Object initialInfo = env.importSymbol(ContextInfo.GLOBAL_SYMBOL);
         if (initialInfo == null) {
             /*
              * This implies that FastR is being invoked initially from another Truffle language and
@@ -455,7 +455,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
             this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"--no-restore"}, false), false), null,
                             ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out()));
         } else {
-            this.info = initialInfo;
+            this.info = JavaInterop.asJavaObject(ContextInfo.class, (TruffleObject) initialInfo);
         }
 
         this.initial = isInitial;
@@ -834,11 +834,6 @@ public final class RContext extends ExecutionContext implements TruffleObject {
         nameSpaceName = name;
     }
 
-    @Override
-    public ForeignAccess getForeignAccess() {
-        throw new IllegalStateException("cannot access " + RContext.class.getSimpleName() + " via Truffle");
-    }
-
     public interface RCloseable extends Closeable {
         @Override
         void close();
-- 
GitLab


From c2b2eb9d121414c5e31f58a10f9d00e3a5268feb Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Tue, 21 Mar 2017 13:08:37 +0100
Subject: [PATCH 137/402] [GR-2950] Fix a batch of builtins with CP issues

---
 .../builtin/base/BaseGammaFunctions.java      |  13 -
 .../r/nodes/builtin/base/GetFunctions.java    |   3 +-
 .../r/nodes/builtin/base/IntToBits.java       |   2 +-
 .../r/nodes/builtin/base/IntToUtf8.java       |   2 +-
 .../truffle/r/nodes/builtin/base/Lapply.java  |   8 +-
 .../r/nodes/builtin/base/LogFunctions.java    | 333 ++++++++++++++++--
 .../truffle/r/nodes/builtin/base/Missing.java |   5 +
 .../truffle/r/nodes/builtin/base/NChar.java   |   2 +-
 .../truffle/r/nodes/builtin/base/NZChar.java  |   8 +
 .../truffle/r/nodes/builtin/base/PMatch.java  |  25 +-
 .../truffle/r/nodes/builtin/base/Parse.java   |   2 +-
 .../truffle/r/nodes/builtin/base/ReadDCF.java |   5 +-
 .../r/nodes/builtin/base/SortFunctions.java   |  21 +-
 .../nodes/builtin/base/infix/NextBuiltin.java |   6 +
 .../truffle/r/nodes/builtin/InternalNode.java |   3 +-
 .../r/nodes/function/ArgumentMatcher.java     |   6 +-
 .../oracle/truffle/r/runtime/RDeparse.java    |   2 +
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +
 .../r/test/builtins/TestBuiltin_lapply.java   |  22 +-
 .../r/test/builtins/TestBuiltin_log.java      | 138 +++++++-
 .../r/test/builtins/TestBuiltin_mget.java     |   3 +-
 .../r/test/builtins/TestBuiltin_nchar.java    |  10 +
 .../r/test/builtins/TestBuiltin_nzchar.java   |   5 +
 .../r/test/builtins/TestBuiltin_pmatch.java   |   3 +
 .../r/test/builtins/TestBuiltin_sort.java     |  20 ++
 25 files changed, 586 insertions(+), 64 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index 42702fa5b1..496698e6d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -37,10 +37,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.nmath.GammaFunctions;
 import com.oracle.truffle.r.runtime.nmath.RMath;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
@@ -97,16 +94,6 @@ public class BaseGammaFunctions {
             }
             return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
         }
-
-        @Specialization
-        protected RDoubleVector lgamma(RAbstractIntVector x) {
-            return lgamma(RClosures.createIntToDoubleVector(x));
-        }
-
-        @Specialization
-        protected RDoubleVector lgamma(RAbstractLogicalVector x) {
-            return lgamma(RClosures.createLogicalToDoubleVector(x));
-        }
     }
 
     @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index 9ccf4cdf32..42030e3dde 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -253,8 +253,7 @@ public class GetFunctions {
         static {
             Casts casts = new Casts(MGet.class);
             casts.arg("x").mustBe(stringValue()).asStringVector();
-            casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(integerValue()).or(doubleValue()).or(instanceOf(RS4Object.class))).mapIf(integerValue().or(doubleValue()),
-                            chain(asIntegerVector()).with(findFirst().integerElement()).end());
+            casts.arg("envir").mustBe(instanceOf(REnvironment.class).or(instanceOf(RS4Object.class)), RError.Message.MUST_BE_ENVIRON2, "second argument");
             casts.arg("mode").mustBe(stringValue()).asStringVector();
             casts.arg("ifnotfound").mustBe(RAbstractListVector.class);
             casts.arg("inherits").asLogicalVector().findFirst().map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
index 0b85315703..1984f96e01 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
@@ -38,7 +38,7 @@ public abstract class IntToBits extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(IntToBits.class);
-        casts.arg("x").asIntegerVector();
+        casts.arg("x").mustNotBeMissing().asIntegerVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
index 0b617546ed..2c391f761f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
@@ -44,7 +44,7 @@ public abstract class IntToUtf8 extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(IntToUtf8.class);
-        casts.arg("x").asIntegerVector();
+        casts.arg("x").mustNotBeMissing().asIntegerVector();
         casts.arg("multiple").mustNotBeNull().asLogicalVector().findFirst().map(toBoolean());
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index 7f2f3de45e..f9e0d535c6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -74,7 +74,7 @@ public abstract class Lapply extends RBuiltinNode {
         // to make conversion of X parameter 100% correct, we'd need to match semantics of
         // asVector() to whatever GNU R is doing there; still this can be a problem only if the
         // internal is called directly (otherwise, it's guaranteed that it's a vector)
-        casts.arg("X").asVector();
+        casts.arg("X").returnIf(instanceOf(RAbstractVector.class).not()).asVector(false);
         casts.arg("FUN").mustBe(instanceOf(RFunction.class), RError.Message.APPLY_NON_FUNCTION);
     }
 
@@ -86,6 +86,12 @@ public abstract class Lapply extends RBuiltinNode {
         return RDataFactory.createList(result, getNamesNode.getNames(vec));
     }
 
+    @Specialization
+    protected Object lapply(VirtualFrame frame, Object x, RFunction fun) {
+        Object[] result = lapply.execute(frame, x, fun);
+        return RDataFactory.createList(result);
+    }
+
     private static final class ExtractElementInternal extends RSourceSectionNode implements RSyntaxCall {
 
         @Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index e157019c8e..5d2ddfdef3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -34,6 +34,8 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -41,19 +43,26 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
+import java.util.Arrays;
+import java.util.function.Function;
 
 public class LogFunctions {
     @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
     public abstract static class Log extends RBuiltinNode {
 
-        private final NAProfile naProfile = NAProfile.create();
+        private final NAProfile naX = NAProfile.create();
         private final BranchProfile nanProfile = BranchProfile.create();
 
         @Override
@@ -64,54 +73,216 @@ public class LogFunctions {
         static {
             Casts casts = new Casts(Log.class);
             casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
-            casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue()).asDoubleVector().findFirst();
+            casts.arg("base").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue())).mapIf(numericValue(), Predef.asDoubleVector(),
+                            Predef.asComplexVector()).asVector().findFirst();
+        }
+
+        static BinaryMapArithmeticFunctionNode createDivNode() {
+            return new BinaryMapArithmeticFunctionNode(BinaryArithmetic.DIV.createOperation());
         }
 
         @Specialization
-        protected double log(int x, double base) {
-            return logb(x, base);
+        protected double log(byte x, double base,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.DOUBLE_NA;
+            }
+            return logb(x, base, naBase);
         }
 
         @Specialization
-        protected double log(double x, double base) {
-            return logb(x, base);
+        protected double log(int x, double base,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.DOUBLE_NA;
+            }
+            return logb(x, base, naBase);
+        }
+
+        @Specialization
+        protected double log(double x, double base,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.DOUBLE_NA;
+            }
+            return logb(x, base, naBase);
+        }
+
+        @Specialization
+        protected RComplex log(RComplex x, double base,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return x;
+            }
+            return logb(x, RComplex.valueOf(base, 0), divNode, naBase);
+        }
+
+        @Specialization
+        protected RComplex log(byte x, RComplex base,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.createComplexNA();
+            }
+            return logb(RComplex.valueOf(x, 0), base, divNode, naBase);
+        }
+
+        @Specialization
+        protected RComplex log(int x, RComplex base,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.createComplexNA();
+            }
+            return logb(RComplex.valueOf(x, 0), base, divNode, naBase);
+        }
+
+        @Specialization
+        protected RComplex log(double x, RComplex base,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.createComplexNA();
+            }
+            return logb(RComplex.valueOf(x, 0), base, divNode, naBase);
+        }
+
+        @Specialization
+        protected RComplex log(RComplex x, RComplex base,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NAProfile naBase) {
+            if (naX.isNA(x)) {
+                return RRuntime.createComplexNA();
+            }
+            return logb(x, base, divNode, naBase);
         }
 
         @Specialization
         protected RDoubleVector log(RAbstractIntVector vector, double base,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
                         @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode) {
-            double[] resultVector = new double[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                int inputValue = vector.getDataAt(i);
-                double result = RRuntime.DOUBLE_NA;
-                if (!naProfile.isNA(inputValue)) {
-                    result = logb(inputValue, base);
-                }
-                resultVector[i] = result;
-            }
-            return createResult(vector, resultVector, base, copyAttrsNode, getNamesNode, getDimsNode);
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> xNACheck.convertIntToDouble(vector.getDataAt(index)), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
         }
 
         @Specialization
         protected RDoubleVector log(RAbstractDoubleVector vector, double base,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
                         @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode) {
-            double[] doubleVector = new double[vector.getLength()];
-            for (int i = 0; i < vector.getLength(); i++) {
-                double value = vector.getDataAt(i);
-                if (!RRuntime.isNA(value)) {
-                    value = logb(value, base);
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> checkDouble(vector.getDataAt(index), xNACheck), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
+        }
+
+        private double checkDouble(double d, NACheck na) {
+            na.check(d);
+            return d;
+        }
+
+        @Specialization
+        protected RDoubleVector log(RAbstractLogicalVector vector, double base,
+                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
+                        @Cached("create()") GetNamesAttributeNode getNamesNode,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> xNACheck.convertLogicalToDouble(vector.getDataAt(index)), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
+        }
+
+        @Specialization
+        protected RComplexVector log(RAbstractComplexVector vector, double base,
+                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
+                        @Cached("create()") GetNamesAttributeNode getNamesNode,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, RComplex.valueOf(base, 0), copyAttrsNode, getNamesNode, getDimsNode, divNode, xNACheck, baseNACheck);
+        }
+
+        @Specialization
+        protected RAbstractComplexVector log(RAbstractIntVector vector, RComplex base,
+                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
+                        @Cached("create()") GetNamesAttributeNode getNamesNode,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> xNACheck.convertIntToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+        }
+
+        @Specialization
+        protected RAbstractComplexVector log(RAbstractDoubleVector vector, RComplex base,
+                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
+                        @Cached("create()") GetNamesAttributeNode getNamesNode,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> xNACheck.convertDoubleToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+        }
+
+        @Specialization
+        protected RAbstractComplexVector log(RAbstractLogicalVector vector, RComplex base,
+                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
+                        @Cached("create()") GetNamesAttributeNode getNamesNode,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> xNACheck.convertLogicalToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+        }
+
+        @Specialization
+        protected RComplexVector log(RAbstractComplexVector vector, RComplex base,
+                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
+                        @Cached("create()") GetNamesAttributeNode getNamesNode,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
+                        @Cached("create()") NACheck xNACheck,
+                        @Cached("create()") NACheck baseNACheck) {
+            return log(vector, base, index -> checkComplex(vector.getDataAt(index), xNACheck), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+        }
+
+        private RComplex checkComplex(RComplex rc, NACheck xNACheck) {
+            xNACheck.check(rc);
+            return rc;
+        }
+
+        private RDoubleVector log(RAbstractVector vector, double base, Function<Integer, Double> toDouble, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode,
+                        GetDimAttributeNode getDimsNode, NACheck xNACheck, NACheck baseNACheck) {
+            baseNACheck.enable(base);
+            double[] resultVector = new double[vector.getLength()];
+            if (baseNACheck.check(base)) {
+                Arrays.fill(resultVector, 0, resultVector.length, base);
+            } else if (Double.isNaN(base)) {
+                nanProfile.enter();
+                Arrays.fill(resultVector, 0, resultVector.length, Double.NaN);
+            } else {
+                xNACheck.enable(vector);
+                Runnable[] warningResult = new Runnable[1];
+                for (int i = 0; i < vector.getLength(); i++) {
+                    double value = toDouble.apply(i);
+                    if (!naX.isNA(value)) {
+                        resultVector[i] = logb(value, base, warningResult);
+                    } else {
+                        resultVector[i] = value;
+                    }
+                }
+                if (warningResult[0] != null) {
+                    warningResult[0].run();
                 }
-                doubleVector[i] = value;
             }
-            return createResult(vector, doubleVector, base, copyAttrsNode, getNamesNode, getDimsNode);
+            boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA();
+            return createResult(vector, resultVector, complete, copyAttrsNode, getNamesNode, getDimsNode);
         }
 
-        private double logb(double x, double base) {
-            if (naProfile.isNA(base)) {
+        private double logb(double x, double base, NAProfile naBase) {
+            if (naBase.isNA(base)) {
                 return RRuntime.DOUBLE_NA;
             }
 
@@ -119,16 +290,118 @@ public class LogFunctions {
                 nanProfile.enter();
                 return base;
             }
+            Runnable[] warningResult = new Runnable[1];
+            double ret = logb(x, base, warningResult);
+            if (warningResult[0] != null) {
+                warningResult[0].run();
+            }
+            return ret;
+        }
+
+        private double logb(double x, double base, Runnable[] warningResult) {
+            double logx = Math.log(x);
+            if (Double.isNaN(logx)) {
+                warningResult[0] = () -> RError.warning(this, RError.Message.NAN_PRODUCED);
+            }
+            if (base == Math.E) {
+                return logx;
+            }
+
+            double result = logx / Math.log(base);
+            if (warningResult[0] == null && Double.isNaN(result)) {
+                warningResult[0] = () -> RError.warning(RError.SHOW_CALLER, RError.Message.NAN_PRODUCED);
+            }
+
+            return result;
+        }
+
+        private RComplexVector log(RAbstractVector vector, RComplex base, Function<Integer, RComplex> toComplex, BinaryMapArithmeticFunctionNode divNode, GetDimAttributeNode getDimsNode,
+                        GetNamesAttributeNode getNamesNode, CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) {
+            baseNACheck.enable(base);
+            double[] complexVector = new double[vector.getLength() * 2];
+            if (baseNACheck.check(base)) {
+                Arrays.fill(complexVector, 0, complexVector.length, RRuntime.DOUBLE_NA);
+            } else if (Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart())) {
+                nanProfile.enter();
+                Arrays.fill(complexVector, 0, complexVector.length, Double.NaN);
+            } else {
+                xNACheck.enable(vector);
+                boolean seenNaN = false;
+                for (int i = 0; i < vector.getLength(); i++) {
+                    RComplex value = toComplex.apply(i);
+                    if (!naX.isNA(value)) {
+                        RComplex rc = logb(value, base, divNode, false);
+                        seenNaN = isNaN(rc);
+                        fill(complexVector, i * 2, rc);
+                    } else {
+                        fill(complexVector, i * 2, value);
+                    }
+                }
+                if (seenNaN) {
+                    RError.warning(this, RError.Message.NAN_PRODUCED_IN_FUNCTION, "log");
+                }
+            }
+            boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA();
+            return createResult(vector, complexVector, complete, getDimsNode, getNamesNode, copyAttrsNode);
+        }
+
+        private void fill(double[] array, int i, RComplex rc) {
+            array[i] = rc.getRealPart();
+            array[i + 1] = rc.getImaginaryPart();
+        }
+
+        private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, NAProfile naBase) {
+            if (naBase.isNA(base)) {
+                return RRuntime.createComplexNA();
+            }
+            if (isNaN(base)) {
+                nanProfile.enter();
+                return base;
+            }
+            return logb(x, base, div, true);
+        }
+
+        private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, boolean nanWarning) {
+            RComplex logx = logb(x);
+            if (base.getRealPart() == Math.E) {
+                return logx;
+            }
 
-            return Math.log(x) / Math.log(base);
+            RComplex logbase = logb(base);
+            RComplex ret = div.applyComplex(logx, logbase);
+            if (nanWarning && isNaN(ret)) {
+                RError.warning(this, RError.Message.NAN_PRODUCED_IN_FUNCTION, "log");
+            }
+            return ret;
+        }
+
+        private RComplex logb(RComplex x) {
+            double re = x.getRealPart();
+            double im = x.getImaginaryPart();
+
+            double mod = RComplex.abs(re, im);
+            double arg = Math.atan2(im, re);
+
+            return RComplex.valueOf(Math.log(mod), arg);
         }
 
-        private static RDoubleVector createResult(RAbstractVector source, double[] resultData, double base, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode,
+        private static RDoubleVector createResult(RAbstractVector source, double[] resultData, boolean complete, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode,
                         GetDimAttributeNode getDimsNode) {
-            RDoubleVector result = RDataFactory.createDoubleVector(resultData, source.isComplete() && !RRuntime.isNA(base), getDimsNode.getDimensions(source), getNamesNode.getNames(source));
+            RDoubleVector result = RDataFactory.createDoubleVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source));
             copyAttrsNode.execute(source, result);
             return result;
         }
+
+        private RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode,
+                        CopyOfRegAttributesNode copyAttrsNode) {
+            RComplexVector result = RDataFactory.createComplexVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source));
+            copyAttrsNode.execute(source, result);
+            return result;
+        }
+
+        private boolean isNaN(RComplex base) {
+            return Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart());
+        }
     }
 
     @RBuiltin(name = "log10", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
index a7ed208b7c..64f1c93b58 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
@@ -46,6 +46,11 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 @RBuiltin(name = "missing", kind = PRIMITIVE, nonEvalArgs = 0, parameterNames = {"x"}, behavior = COMPLEX)
 public abstract class Missing extends RBuiltinNode {
 
+    static {
+        Casts casts = new Casts(Missing.class);
+        casts.arg("x").allowMissing();
+    }
+
     @Specialization
     protected byte missing(VirtualFrame frame, RPromise promise,
                     @Cached("create(0)") MissingCheckCache cache) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
index 92e5e4f943..7f3e1055f3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
@@ -59,7 +59,7 @@ public abstract class NChar extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(NChar.class);
-        casts.arg("x").allowNull().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false));
+        casts.arg("x").mustNotBeMissing().mapIf(integerValue(), asIntegerVector(), asStringVector(true, false, false));
         casts.arg("type").asStringVector().findFirst().mustBe(lengthGt(0));
         casts.arg("allowNA").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         casts.arg("keepNA").asLogicalVector().findFirst(RRuntime.LOGICAL_NA).map(toBoolean());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index ee7883c4a4..b8ec8ffd1b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -28,10 +28,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -68,4 +70,10 @@ public abstract class NZChar extends RBuiltinNode {
         }
         return RDataFactory.createLogicalVector(result, /* complete: */ keepNA && !hasNA);
     }
+
+    @Specialization
+    protected RLogicalVector rev(@SuppressWarnings("unused") RMissing value, @SuppressWarnings("unused") boolean keepNA) {
+        throw RError.error(this, RError.Message.ARGUMENT_NOT_MATCH, "keepNA", "x");
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
index 55db842837..b9e0292d51 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
@@ -30,11 +29,14 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "pmatch", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "duplicates.ok"}, behavior = PURE)
@@ -46,12 +48,27 @@ public abstract class PMatch extends RBuiltinNode {
 
     static {
         Casts casts = new Casts(PMatch.class);
-        casts.arg("x").asStringVector();
-        casts.arg("table").asStringVector();
-        casts.arg("nomatch").mapNull(constant(RRuntime.INT_NA)).asIntegerVector();
+        casts.arg("x").mustNotBeMissing().asStringVector();
+        casts.arg("table").mustNotBeMissing().asStringVector();
+        casts.arg("nomatch").mustNotBeMissing().mapIf(nullValue(), constant(RRuntime.INT_NA)).asIntegerVector().findFirst();
         casts.arg("duplicates.ok").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
     }
 
+    @Specialization
+    protected RIntVector doPMatch(RNull x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) {
+        return RDataFactory.createEmptyIntVector();
+    }
+
+    @Specialization
+    protected RIntVector doPMatch(RAbstractStringVector x, RNull table, int nomatch, boolean duplicatesOk) {
+        return RDataFactory.createEmptyIntVector();
+    }
+
+    @Specialization
+    protected RIntVector doPMatch(RNull x, RNull table, int nomatch, boolean duplicatesOk) {
+        return RDataFactory.createEmptyIntVector();
+    }
+
     @Specialization
     protected RIntVector doPMatch(RAbstractStringVector x, RAbstractStringVector table, int nomatch, boolean duplicatesOk) {
         int xl = x.getLength();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index 78f3f3d6cd..f4f37e8495 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -105,7 +105,7 @@ public abstract class Parse extends RBuiltinNode {
         // Note: string is captured by the R wrapper and transformed to a file, other types not
         casts.arg("conn").defaultError(MUST_BE_STRING_OR_CONNECTION, "file").mustNotBeNull().asIntegerVector().findFirst();
         casts.arg("n").asIntegerVector().findFirst(RRuntime.INT_NA).replaceNA(-1);
-        casts.arg("text").asStringVector();
+        casts.arg("text").mustNotBeMissing().asStringVector();
         casts.arg("prompt").asStringVector().findFirst("?");
         casts.arg("encoding").mustBe(stringValue()).asStringVector().findFirst();
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
index e888b61de4..c009097405 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
@@ -35,6 +35,7 @@ import java.util.Set;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.DCF;
 import com.oracle.truffle.r.runtime.RError;
@@ -54,8 +55,8 @@ public abstract class ReadDCF extends RBuiltinNode {
     static {
         Casts casts = new Casts(ReadDCF.class);
         casts.arg("conn").defaultError(Message.INVALID_CONNECTION).asIntegerVector().findFirst();
-        casts.arg("fields").mapNull(emptyStringVector()).asStringVector();
-        casts.arg("keepwhite").mapNull(emptyStringVector()).asStringVector();
+        casts.arg("fields").mustNotBeMissing().mapIf(nullValue(), emptyStringVector()).asStringVector();
+        casts.arg("keepwhite").mustNotBeMissing().mapIf(nullValue(), emptyStringVector()).asStringVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index 370208bd12..f06a920474 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -38,8 +38,13 @@ import java.util.Collections;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
+import static com.oracle.truffle.r.runtime.RError.Message.NOT_NUMERIC_VECTOR;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -55,6 +60,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * The internal functions mandated by {@code base/sort.R}. N.B. We use the standard JDK sorting
@@ -200,8 +206,8 @@ public class SortFunctions {
 
         static {
             Casts casts = new Casts(QSort.class);
-            addCastForX(casts);
-            addCastForDecreasing(casts);
+            casts.arg("x").defaultError(NOT_NUMERIC_VECTOR).mustBe(instanceOf(RAbstractListVector.class).not()).mustBe(integerValue().or(doubleValue()));
+            casts.arg("decreasing").mapIf(numericValue().not(), Predef.constant(RRuntime.LOGICAL_TRUE)).asLogicalVector().findFirst().map(toBoolean());
         }
 
         @Specialization
@@ -246,6 +252,17 @@ public class SortFunctions {
         protected RLogicalVector sort(RAbstractLogicalVector vec, Object partial) {
             return jdkSort(vec, false);
         }
+
+        @SuppressWarnings("unused")
+        @Specialization
+        protected RLogicalVector sort(RAbstractComplexVector vec, Object partial) {
+            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1); // [TODO] implement
+        }
+
+        @Specialization
+        protected RNull sort(RNull vec, Object partial) {
+            return RNull.instance;
+        }
     }
 
     /**
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java
index d83ea35129..16830767a1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java
@@ -26,12 +26,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Specialization;
+import static com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts.noCasts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "next", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
 public abstract class NextBuiltin extends RBuiltinNode {
+
+    static {
+        noCasts(NextBuiltin.class);
+    }
+
     @Specialization
     protected Object doIt(@SuppressWarnings("unused") Object x) {
         throw RInternalError.unimplemented();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
index 8d1683a4c1..6b29fde993 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
@@ -147,7 +147,8 @@ public abstract class InternalNode extends OperatorNode {
             // verify the number of arguments
             if (factory.getSignature().getVarArgCount() == 0) {
                 if (callArgs.length != factory.getSignature().getLength()) {
-                    throw RError.error(RError.SHOW_CALLER, Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")", factory.getSignature().getLength());
+                    throw RError.error(RError.SHOW_CALLER, callArgs.length == 1 ? Message.ARGUMENT_PASSED : Message.ARGUMENTS_PASSED, callArgs.length, ".Internal(" + name + ")",
+                                    factory.getSignature().getLength());
                 }
                 for (int i = 0; i < callArgs.length; i++) {
                     if (callArgs[i] instanceof RSyntaxConstant && ((RSyntaxConstant) callArgs[i]).getValue() == REmpty.instance) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index 1cf534c2eb..29f3ee5e58 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -42,6 +42,7 @@ import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments;
+import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -59,6 +60,7 @@ import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * <p>
@@ -270,14 +272,14 @@ public class ArgumentMatcher {
                 // TODO: this error handling code takes many assumptions about the argument types
                 RArgsValuesAndNames varArg = (RArgsValuesAndNames) frame.getObject(frame.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME));
                 RPromise promise = (RPromise) varArg.getArguments()[((VarArgNode) node).getIndex()];
-                return promise.getRep().asRSyntaxNode().getSourceSection().getCode();
+                return RDeparse.deparseSyntaxElement(promise.getRep().asRSyntaxNode());
             } catch (FrameSlotTypeException | ClassCastException e) {
                 throw RInternalError.shouldNotReachHere();
             }
         } else {
             String code;
             if (node.asRSyntaxNode().getSourceSection() != null) {
-                code = node.asRSyntaxNode().getSourceSection().getCode();
+                code = RDeparse.deparseSyntaxElement(node.asRSyntaxNode());
             } else {
                 code = "<unknown>"; // RDeparse.deparseForPrint(node.asRSyntaxNode());
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index c2591fed09..3fe65ddf1d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -682,6 +682,8 @@ public class RDeparse {
                 append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr().asAddress())).append('>');
             } else if (value instanceof REnvironment) {
                 append("<environment>");
+            } else if (value instanceof REmpty) {
+                append("");
             } else if (value instanceof TruffleObject) {
                 append("<truffle object>");
             } else {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index a73c50c1f7..2930d06222 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -338,6 +338,7 @@ public final class RError extends RuntimeException {
         NON_CHARACTER_NAMES("non-character names"),
         NON_NUMERIC_MATH("non-numeric argument to mathematical function"),
         NAN_PRODUCED("NaNs produced"),
+        NAN_PRODUCED_IN_FUNCTION("NaNs produced in function \"%s\""),
         NUMERIC_COMPLEX_MATRIX_VECTOR("requires numeric/complex matrix/vector arguments"),
         NON_CONFORMABLE_ARGS("non-conformable arguments"),
         DATA_VECTOR("'data' must be of a vector type"),
@@ -509,6 +510,7 @@ public final class RError extends RuntimeException {
         ATTRIBUTE_VECTOR_SAME_LENGTH("'%s' attribute [%d] must be the same length as the vector [%d]"),
         SCAN_UNEXPECTED("scan() expected '%s', got '%s'"),
         MUST_BE_ENVIRON("'%s' must be an environment"),
+        MUST_BE_ENVIRON2("%s must be an environment"),
         MUST_BE_INTEGER("'%s' must be an integer"),
         UNUSED_ARGUMENT("unused argument (%s)"),
         UNUSED_ARGUMENTS("unused arguments (%s)"),
@@ -620,6 +622,7 @@ public final class RError extends RuntimeException {
         SUBSCRIPT_TYPES("incompatible types (from %s to %s) in [[ assignment"),
         INCOMPATIBLE_METHODS("incompatible methods (\"%s\", \"%s\") for \"%s\""),
         RECURSIVE_INDEXING_FAILED("recursive indexing failed at level %d"),
+        ARGUMENT_PASSED("%d argument passed to %s which requires %d"),
         ARGUMENTS_PASSED("%d arguments passed to %s which requires %d"),
         ARGUMENT_IGNORED("argument '%s' will be ignored"),
         NOT_CHARACTER_VECTOR("'%s' must be a character vector"),
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java
index 72228b0de6..57999d315e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lapply.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -33,6 +33,26 @@ public class TestBuiltin_lapply extends TestBase {
         assertEval("{ l <- list(list(1),list(2),list(3)); f <- function(a) { lapply(a, function(x) lapply(x, function(y) print(y))) }; f(l)}");
 
         assertEval("{ .Internal(lapply(1:4, 42)) }");
+
+        assertEval("lapply(NULL, function(x){x})");
+        assertEval("lapply(NA, FUN=function(x){x})");
+        assertEval("lapply(FUN=function(x){x})");
+        assertEval("lapply(1:4, NULL)");
+        assertEval("lapply(1:4, NA)");
+        assertEval(Output.IgnoreErrorContext, "lapply(X=1:4)");
+        assertEval("lapply(X=function() {print('test')}, FUN=function(x){x})");
+        assertEval(Output.IgnoreWhitespace, "lapply(X=c(function() {print(\"test1\")}, function() {print(\"test2\")}), FUN=function(x){x})");
+        assertEval("lapply(X=environment(), FUN=function(x){x})");
+
+        assertEval("f <- function(...) { .Internal(lapply(NULL, function(x){x})) }; f()");
+        assertEval("f <- function(...) { .Internal(lapply(NA, FUN=function(x){x})) }; f()");
+        assertEval("f <- function(...) { .Internal(lapply(FUN=function(x){x})) }; f()");
+        assertEval("f <- function(...) { .Internal(lapply(1:4, NULL)) }; f()");
+        assertEval("f <- function(...) { .Internal(lapply(1:4, NA)) }; f()");
+        assertEval("f <- function(...) { .Internal(lapply(X=1:4)) }; f()");
+        assertEval(Output.IgnoreErrorContext, "f <- function(...) { .Internal(lapply(X=function() {print('test')}, FUN=function(x){x})) }; f()");
+        assertEval(Ignored.ImplementationError, "f <- function(...) { .Internal(lapply(X=c(function() {print('test1')}, function() {print('test2')}), FUN=function(x){x})) }; f()");
+        assertEval(Output.IgnoreErrorContext, "f <- function(...) { .Internal(lapply(X=environment(), FUN=function(x){x})) }; f()");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java
index 1cb8f1375e..4e5da9071a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -34,4 +34,140 @@ public class TestBuiltin_log extends TestBase {
         assertEval("{ log(c(2,3), NA) } ");
         assertEval("{ log(c(2,3), 0/0) } ");
     }
+
+    @Test
+    public void testLogLogical() {
+        assertEval("{ log(T) }");
+        assertEval("{ log(c(T)) }");
+        assertEval("{ log(c(T, F)) }");
+        assertEval("{ log(c(T, F), T) }");
+        assertEval("{ log(T, T) }");
+        assertEval("{ log(T, F) }");
+        assertEval("{ log(F, F) }");
+        assertEval("{ log(F, T) }");
+        assertEval("{ log(c(T, T), NA) }");
+        assertEval("{ log(c(T, T), NaN) }");
+    }
+
+    @Test
+    public void testLogInt() {
+        assertEval("{ log(1L) }");
+        assertEval("{ log(-1L) }");
+        assertEval("{ log(0L) }");
+        assertEval("{ log(NA_integer_) }");
+        assertEval("{ log(0L, NA_integer_) }");
+        assertEval("{ log(c(0L, NA_integer_)) }");
+        assertEval("{ log(1L, 1L) }");
+        assertEval("{ log(10L, 1L) }");
+        assertEval("{ log(10L, -1L) }");
+        assertEval("{ log(10L, 10L) }");
+        assertEval("{ log(c(1L, 1L, 0L, 10L), 10L) }");
+        assertEval("{ log(c(1L, 0L, 10L), 1L) }");
+        assertEval("{ log(c(1L, 2L), NA) }");
+        assertEval("{ log(c(1L, 2L), NaN) }");
+        assertEval("{ log(c(1L, 2L, NA)) }");
+    }
+
+    @Test
+    public void testLogDouble() {
+        assertEval("{ log(1.1) }");
+        assertEval("{ log(-1.1) }");
+        assertEval("{ log(0.0) }");
+        assertEval("{ log(NA_real_) }");
+        assertEval("{ log(10, NA_real_) }");
+        assertEval("{ log(c(10, NA_real_)) }");
+        assertEval("{ log(1.0, 1.0) }");
+        assertEval("{ log(10.0, 1.0) }");
+        assertEval("{ log(10.0, -1.0) }");
+        assertEval("{ log(10.0, 10.0) }");
+        assertEval("{ log(c(1.0, 0.0, 10.0), 10.0) }");
+        assertEval("{ log(c(1.0, 0.0, 10.0), 1.0) }");
+        assertEval("{ log(c(1.0, 2.0), NA) }");
+        assertEval("{ log(c(1.0, 2.0), NaN) }");
+        assertEval("{ log(c(1.0, 2.0, NA)) }");
+    }
+
+    @Test
+    public void testLogComplex() {
+        assertEval("{ log(0+0i) }");
+
+        // NaN warnigns
+        assertEval("{ log(0+0i, 0) }");
+        assertEval("{ log(0L, 0+0i) }");
+        assertEval("{ log(0.0, 0+0i) }");
+        assertEval("{ log(F, 0+0i) }");
+        assertEval("{ log(0+0i, 0+0i) }");
+
+        // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi
+        assertEval(Ignored.ImplementationError, "{ log(0+0i, 1) }");
+
+        assertEval("{ log(1+1i) }");
+        assertEval("{ log(complex(real=NA, imaginary=1i)) }");
+        assertEval("{ log(complex(real=1, imaginary=NA)) }");
+        assertEval("{ log(complex(real=NA, imaginary=NA)) }");
+        assertEval("{ log(NA_complex_) }");
+        assertEval("{ log(1+1i, NA_complex_) }");
+        assertEval("{ log(c(1+1i, NA_complex_)) }");
+        assertEval("{ log(1+1i, 0) }");
+
+        // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi
+        assertEval(Ignored.ImplementationError, "{ log(1+1i, 1) }");
+
+        assertEval("{ log(10+1i, 10) }");
+        assertEval("{ log(10-1i, 10) }");
+        assertEval("{ log(-10-1i, 10) }");
+        assertEval("{ log(10+1i, -10) }");
+        assertEval("{ log(10+10i, 10) }");
+        assertEval("{ log(c(1+1i)) }");
+        assertEval("{ log(c(1+1i), 0) }");
+
+        assertEval("{ log(c(1+1i, 2+2i), NA) }");
+        assertEval("{ log(c(1+1i, 2+2i), NaN) }");
+        assertEval("{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NaN)) }");
+        assertEval("{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=1)) }");
+        assertEval("{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=NaN)) }");
+        assertEval("{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NA)) }");
+        assertEval("{ log(c(1+1i, 2+2i), complex(real=NA, imaginary=1)) }");
+        assertEval("{ log(c(1+1i, 2+2i, complex(real=NA, imaginary=NA))) }");
+
+        assertEval("{ log(c(10+1i, 10), 10) }");
+        assertEval("{ log(c(10+10i, 10), 10) }");
+        assertEval("{ log(c(1+1i, 2+1i)) }");
+
+        assertEval("{ log(c(10, 10+10i), 10) }");
+        assertEval("{ log(c(10.0, 10+10i), 10) }");
+        assertEval("{ log(c(T, 10+10i), 10) }");
+
+        assertEval("{ log(1, 1+1i) }");
+        assertEval("{ log(10, 10+10i) }");
+        assertEval("{ log(1.0, 1+1i) }");
+        assertEval("{ log(10.0, 1+1i) }");
+        assertEval("{ log(T, 1+1i) }");
+
+        assertEval("{ log(1+1i, 1+1i) }");
+        assertEval("{ log(1+1i, 1-1i) }");
+        assertEval("{ log(1+1i, -1-1i) }");
+        assertEval("{ log(10+10i, 10+10i) }");
+        assertEval("{ log(1+1i, 10+10i) }");
+
+        assertEval("{ log(c(10, 10), 10+10i) }");
+        assertEval("{ log(c(10.0, 10.0), 10+10i) }");
+        assertEval("{ log(c(T, F), 1+1i) }");
+        assertEval("{ log(c(10+10i, 10+10i), 10+10i) }");
+        // division by complex(r=0, i=0) returns NaN+NaNi, instead of -Inf+NaNi
+        assertEval(Ignored.ImplementationError, "{ log(complex(real=sqrt(.5), imaginary=sqrt(.5)), 1) }");
+    }
+
+    @Test
+    public void testProducedManyNaNsButOneWarnig() {
+        assertEval("{ log(c(F, F), F) }");
+        assertEval("{ log(c(1L, 1L), 1L) }");
+        assertEval("{ log(c(1.0, 1.0), 1.0) }");
+        assertEval("{ log(c(0+0i, 0+0i), 0) }");
+
+        assertEval("{ log(c(F, F), 0+0i) }");
+        assertEval("{ log(c(0L, 0L), 0+0i) }");
+        assertEval("{ log(c(0.0, 0.0), 0+0i) }");
+        assertEval("{ log(c(0+0i, 0+0i), 0+0i) }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java
index 7f3b487981..e27d7728fc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -20,6 +20,7 @@ public class TestBuiltin_mget extends TestBase {
     @Test
     public void testMGet() {
         assertEval("{ a<- 1; b <- 2; mget(c(\"a\", \"b\")) }");
+        assertEval("{ a<- 1; b <- 2; mget(c('a', 'b'), envir=1) }");
         assertEval("{ a<- 1; b <- 2; f <- function() { mget(c(\"a\", \"b\"), inherits=TRUE)}; f() }");
         assertEval("{ a<- 1; mget(c(\"a\", \"b\"), ifnotfound=list(100)) }");
         assertEval("{ b <- 2; f <- function() { mget(c(\"a\", \"b\"), ifnotfound=list(100), inherits=TRUE)}; f() }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
index a62ed37731..704e3e765b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nchar.java
@@ -99,4 +99,14 @@ public class TestBuiltin_nchar extends TestBase {
         assertEval("nchar('aasd', type='charsxzy')");
         assertEval("nchar('aasd', type='')");
     }
+
+    @Test
+    public void testNULLAndMissing() {
+        assertEval("nchar()");
+        assertEval("nchar(type = 'chars', allowNA = FALSE, keepNA = NA)");
+        assertEval("nchar(x=NULL)");
+        assertEval("nchar(x=NULL, type = 'chars', allowNA = FALSE, keepNA = NA)");
+        assertEval("nchar(wrongArg=\"a\")");
+        assertEval("nchar(wrongArg='a')");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
index 980d16177b..0c86bc1ebd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_nzchar.java
@@ -83,5 +83,10 @@ public class TestBuiltin_nzchar extends TestBase {
     public void nonStringArgs() {
         assertEval("nzchar(list('x', 42, list('a'), list()))");
         assertEval("nzchar(NULL)");
+        assertEval("nzchar(NA)");
+        assertEval("nzchar(keepNA=F)");
+        assertEval("nzchar(keepNA=NA)");
+        assertEval("nchar(wrongArgName=\"a\")");
+        assertEval("nchar(wrongArgName='a')");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
index 70bc9c36d2..53fd3e3a12 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pmatch.java
@@ -61,6 +61,9 @@ public class TestBuiltin_pmatch extends TestBase {
     public void testArgumentsCasts() {
         assertEval("pmatch(NULL, 1)");
         assertEval("pmatch(1, NULL)");
+        assertEval("pmatch(x=NULL, table=NULL)");
+        assertEval("pmatch(x=1)");
+        assertEval("pmatch(table=1)");
         assertEval("pmatch(1:5, c(1,3), nomatch=NULL)");
         assertEval("pmatch(1:5, c(1,3), nomatch='str')");
         assertEval("pmatch(1:5, c(1,3), duplicates.ok=42)");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java
index 96970b11a2..081df3a505 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sort.java
@@ -130,4 +130,24 @@ public class TestBuiltin_sort extends TestBase {
         assertEval("{ .Internal(sort(NULL, FALSE)) }");
         assertEval("{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }");
     }
+
+    @Test
+    public void testQSort() {
+        assertEval("{ .Internal(qsort(NULL, F)) }");
+        assertEval("{ .Internal(qsort(NULL, NULL)) }");
+        // seems that when the value provided for decreased is whatever else than FALSE
+        // then it is interpreted as TRUE. In such a case qsort returns a list containing
+        // two vectors: the values sorted as in decreased=F and the original indices giving
+        // the decreased order. NOTE that even though the FastR impl of qsort always returns
+        // only 1 increasing/decreasing vector, it has no effect on the overall sort function.
+        assertEval(Ignored.ImplementationError, "{ .Internal(qsort(1, decreased=NULL)) }");
+        assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), T)) }");
+        assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), 1)) }");
+        assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), 'a')) }");
+        assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), c('a'))) }");
+        assertEval(Ignored.ImplementationError, "{ .Internal(qsort(c(4, 2, 3), list('a'))) }");
+        assertEval("{ .Internal(qsort(list(1), F)) }");
+        assertEval("{ .Internal(qsort(1, F)) }");
+        assertEval("{ .Internal(qsort(c(1), F)) }");
+    }
 }
-- 
GitLab


From 4571efc00b362bfc7246c4de93bdbfa9e3cd30b9 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Tue, 21 Mar 2017 13:09:04 +0100
Subject: [PATCH 138/402] generated expected output messages

---
 .../truffle/r/test/ExpectedTestOutput.test    | 698 ++++++++++++++++++
 1 file changed, 698 insertions(+)

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 5fc5fb2db8..9d90b4112b 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
@@ -29317,6 +29317,112 @@ attr(,"origin")
 [1] "(Intercept)" "gravity"     "ph"          "osmo"        "conduct"
 [6] "urea"        "log(calc)"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#f <- function(...) { .Internal(lapply(1:4, NA)) }; f()
+Error in f() : attempt to apply non-function
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#f <- function(...) { .Internal(lapply(1:4, NULL)) }; f()
+Error in f() : attempt to apply non-function
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#f <- function(...) { .Internal(lapply(FUN=function(x){x})) }; f()
+Error in f() : 1 argument passed to .Internal(lapply) which requires 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#f <- function(...) { .Internal(lapply(NA, FUN=function(x){x})) }; f()
+[[1]]
+[1] NA
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#f <- function(...) { .Internal(lapply(NULL, function(x){x})) }; f()
+list()
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#f <- function(...) { .Internal(lapply(X=1:4)) }; f()
+Error in f() : 1 argument passed to .Internal(lapply) which requires 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Ignored.ImplementationError#
+#f <- function(...) { .Internal(lapply(X=c(function() {print('test1')}, function() {print('test2')}), FUN=function(x){x})) }; f()
+[[1]]
+function ()
+{
+    print("test1")
+}
+<environment: 0x7fb02e3849c0>
+
+[[2]]
+function ()
+{
+    print("test2")
+}
+<environment: 0x7fb02e3849c0>
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreErrorContext#
+#f <- function(...) { .Internal(lapply(X=environment(), FUN=function(x){x})) }; f()
+Error in environment()[[i]] :
+  wrong arguments for subsetting an environment
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreErrorContext#
+#f <- function(...) { .Internal(lapply(X=function() {print('test')}, FUN=function(x){x})) }; f()
+Error in function() { : object of type 'closure' is not subsettable
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(1:4, NA)
+Error in match.fun(FUN) : 'NA' is not a function, character or symbol
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(1:4, NULL)
+Error in match.fun(FUN) : 'NULL' is not a function, character or symbol
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(FUN=function(x){x})
+Error in lapply(FUN = function(x) { :
+  argument "X" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(NA, FUN=function(x){x})
+[[1]]
+[1] NA
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(NULL, function(x){x})
+list()
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreErrorContext#
+#lapply(X=1:4)
+Error in match.fun(FUN) : argument "FUN" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#Output.IgnoreWhitespace#
+#lapply(X=c(function() {print("test1")}, function() {print("test2")}), FUN=function(x){x})
+[[1]]
+function ()
+{
+    print("test1")
+}
+
+[[2]]
+function ()
+{
+    print("test2")
+}
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(X=environment(), FUN=function(x){x})
+list()
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
+#lapply(X=function() {print('test')}, FUN=function(x){x})
+[[1]]
+{
+    print("test")
+}
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_lapply.testLapply#
 #{ .Internal(lapply(1:4, 42)) }
 Error: attempt to apply non-function
@@ -32358,6 +32464,460 @@ Error in lockEnvironment("foo", TRUE) : not an environment
 #{ round( log(10,2), digits = 5 ) }
 [1] 3.32193
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(-10-1i, 10) }
+[1] 1.002161-1.321091i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(0+0i) }
+[1] -Inf+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(0+0i, 0) }
+[1] NaN+NaNi
+Warning message:
+In log(0 + (0+0i), 0) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(0+0i, 0+0i) }
+[1] NaN+NaNi
+Warning message:
+In log(0 + (0+0i), 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#Ignored.ImplementationError#
+#{ log(0+0i, 1) }
+[1] -Inf+NaNi
+Warning message:
+In log(0 + (0+0i), 1) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(0.0, 0+0i) }
+[1] NaN+NaNi
+Warning message:
+In log(0, 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(0L, 0+0i) }
+[1] NaN+NaNi
+Warning message:
+In log(0L, 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i) }
+[1] 0.3465736+0.7853982i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i, -1-1i) }
+[1] -0.3050968+0.1919672i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i, 0) }
+[1] 0+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#Ignored.ImplementationError#
+#{ log(1+1i, 1) }
+[1] Inf+Infi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i, 1+1i) }
+[1] 1+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i, 1-1i) }
+[1] -0.674032+0.7387021i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i, 10+10i) }
+[1] 0.2010479+0.236866i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1+1i, NA_complex_) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1, 1+1i) }
+[1] 0+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(1.0, 1+1i) }
+[1] 0+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10+10i, 10) }
+[1] 1.150515+0.341094i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10+10i, 10+10i) }
+[1] 1+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10+1i, -10) }
+[1] 0.3708579-0.4627043i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10+1i, 10) }
+[1] 1.002161+0.043286i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10, 10+10i) }
+[1] 0.7989521-0.236866i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10-1i, 10) }
+[1] 1.002161-0.043286i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(10.0, 1+1i) }
+[1] 1.082842-2.453915i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(F, 0+0i) }
+[1] NaN+NaNi
+Warning message:
+In log(F, 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(NA_complex_) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(T, 1+1i) }
+[1] 0+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i)) }
+[1] 0.3465736+0.7853982i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i), 0) }
+[1] 0+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+1i)) }
+[1] 0.3465736+0.7853982i 0.8047190+0.4636476i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), NA) }
+[1] NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), NaN) }
+[1] NaN+NaNi NaN+NaNi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NA)) }
+[1] NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), complex(real=1, imaginary=NaN)) }
+[1] NaN+NaNi NaN+NaNi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), complex(real=NA, imaginary=1)) }
+[1] NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=1)) }
+[1] NaN+NaNi NaN+NaNi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i), complex(real=NaN, imaginary=NaN)) }
+[1] NaN+NaNi NaN+NaNi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, 2+2i, complex(real=NA, imaginary=NA))) }
+[1] 0.3465736+0.7853982i 1.0397208+0.7853982i                   NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(1+1i, NA_complex_)) }
+[1] 0.3465736+0.7853982i                   NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10+10i, 10), 10) }
+[1] 1.150515+0.341094i 1.000000+0.000000i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10+10i, 10+10i), 10+10i) }
+[1] 1+0i 1+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10+1i, 10), 10) }
+[1] 1.002161+0.043286i 1.000000+0.000000i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10, 10), 10+10i) }
+[1] 0.7989521-0.236866i 0.7989521-0.236866i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10, 10+10i), 10) }
+[1] 1.000000+0.000000i 1.150515+0.341094i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10.0, 10+10i), 10) }
+[1] 1.000000+0.000000i 1.150515+0.341094i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(10.0, 10.0), 10+10i) }
+[1] 0.7989521-0.236866i 0.7989521-0.236866i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(T, 10+10i), 10) }
+[1] 0.000000+0.000000i 1.150515+0.341094i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(c(T, F), 1+1i) }
+[1]    0+  0i -Inf+Infi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(complex(real=1, imaginary=NA)) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(complex(real=NA, imaginary=1i)) }
+[1] NA
+Warning message:
+In complex(real = NA, imaginary = 0+1i) :
+  imaginary parts discarded in coercion
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
+#{ log(complex(real=NA, imaginary=NA)) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#Ignored.ImplementationError#
+#{ log(complex(real=sqrt(.5), imaginary=sqrt(.5)), 1) }
+[1] Inf+Infi
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(-1.1) }
+[1] NaN
+Warning message:
+In log(-1.1) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(0.0) }
+[1] -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(1.0, 1.0) }
+[1] NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(1.1) }
+[1] 0.09531018
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(10, NA_real_) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(10.0, -1.0) }
+[1] NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(10.0, 1.0) }
+[1] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(10.0, 10.0) }
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(NA_real_) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(c(1.0, 0.0, 10.0), 1.0) }
+[1]  NaN -Inf  Inf
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(c(1.0, 0.0, 10.0), 10.0) }
+[1]    0 -Inf    1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(c(1.0, 2.0), NA) }
+[1] NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(c(1.0, 2.0), NaN) }
+[1] NaN NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(c(1.0, 2.0, NA)) }
+[1] 0.0000000 0.6931472        NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogDouble#
+#{ log(c(10, NA_real_)) }
+[1] 2.302585       NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(-1L) }
+[1] NaN
+Warning message:
+In log(-1L) : NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(0L) }
+[1] -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(0L, NA_integer_) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(10L, -1L) }
+[1] NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(10L, 10L) }
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(10L, 1L) }
+[1] Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(1L) }
+[1] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(1L, 1L) }
+[1] NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(NA_integer_) }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(c(0L, NA_integer_)) }
+[1] -Inf   NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(c(1L, 0L, 10L), 1L) }
+[1]  NaN -Inf  Inf
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(c(1L, 1L, 0L, 10L), 10L) }
+[1]    0    0 -Inf    1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(c(1L, 2L), NA) }
+[1] NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(c(1L, 2L), NaN) }
+[1] NaN NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogInt#
+#{ log(c(1L, 2L, NA)) }
+[1] 0.0000000 0.6931472        NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(F, F) }
+[1] NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(F, T) }
+[1] -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(T) }
+[1] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(T, F) }
+[1] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(T, T) }
+[1] NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(c(T)) }
+[1] 0
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(c(T, F)) }
+[1]    0 -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(c(T, F), T) }
+[1]  NaN -Inf
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(c(T, T), NA) }
+[1] NA NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogLogical#
+#{ log(c(T, T), NaN) }
+[1] NaN NaN
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(0+0i, 0+0i), 0) }
+[1] NaN+NaNi NaN+NaNi
+Warning message:
+In log(c(0 + (0+0i), 0 + (0+0i)), 0) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(0+0i, 0+0i), 0+0i) }
+[1] NaN+NaNi NaN+NaNi
+Warning message:
+In log(c(0 + (0+0i), 0 + (0+0i)), 0 + (0+0i)) :
+  NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(0.0, 0.0), 0+0i) }
+[1] NaN+NaNi NaN+NaNi
+Warning message:
+In log(c(0, 0), 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(0L, 0L), 0+0i) }
+[1] NaN+NaNi NaN+NaNi
+Warning message:
+In log(c(0L, 0L), 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(1.0, 1.0), 1.0) }
+[1] NaN NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(1L, 1L), 1L) }
+[1] NaN NaN
+Warning message:
+NaNs produced
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(F, F), 0+0i) }
+[1] NaN+NaNi NaN+NaNi
+Warning message:
+In log(c(F, F), 0 + (0+0i)) : NaNs produced in function "log"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testProducedManyNaNsButOneWarnig#
+#{ log(c(F, F), F) }
+[1] NaN NaN
+Warning message:
+NaNs produced
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testlog1#
 #argv <- list(0.7800058115849);do.call('log', argv)
 [1] -0.2484539
@@ -34751,6 +35311,11 @@ $b
 [1] 2
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGet#
+#{ a<- 1; b <- 2; mget(c('a', 'b'), envir=1) }
+Error in mget(c("a", "b"), envir = 1) :
+  second argument must be an environment
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGet#
 #{ a<- 1; mget(c("a", "b"), ifnotfound=list(100)) }
 $a
@@ -36194,6 +36759,31 @@ Error in nchar("aasd", type = "") : invalid 'type' argument
 #nchar('aasd', type='charsxzy')
 Error in nchar("aasd", type = "charsxzy") : invalid 'type' argument
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing#
+#nchar()
+Error in nchar() : argument "x" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing#
+#nchar(type = 'chars', allowNA = FALSE, keepNA = NA)
+Error in nchar(type = "chars", allowNA = FALSE, keepNA = NA) :
+  argument "x" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing#
+#nchar(wrongArg="a")
+Error in nchar(wrongArg = "a") : unused argument (wrongArg = "a")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing#
+#nchar(wrongArg='a')
+Error in nchar(wrongArg = "a") : unused argument (wrongArg = "a")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing#
+#nchar(x=NULL)
+integer(0)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testNULLAndMissing#
+#nchar(x=NULL, type = 'chars', allowNA = FALSE, keepNA = NA)
+integer(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nchar.testnchar1#
 #argv <- list('DtTmCl> format(.leap.seconds)         # all 24 leap seconds in your timezone', 'c', FALSE, FALSE); .Internal(nchar(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] 76
@@ -36378,10 +36968,32 @@ Warning messages:
 #nzchar(c('asdasd', NA), keepNA=TRUE)
 [1] TRUE   NA
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
+#nchar(wrongArgName="a")
+Error in nchar(wrongArgName = "a") : unused argument (wrongArgName = "a")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
+#nchar(wrongArgName='a')
+Error in nchar(wrongArgName = "a") : unused argument (wrongArgName = "a")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
+#nzchar(NA)
+[1] TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
 #nzchar(NULL)
 logical(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
+#nzchar(keepNA=F)
+Error in nzchar(keepNA = F) :
+  supplied argument name 'keepNA' does not match 'x'
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
+#nzchar(keepNA=NA)
+Error in nzchar(keepNA = NA) :
+  supplied argument name 'keepNA' does not match 'x'
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_nzchar.nonStringArgs#
 #nzchar(list('x', 42, list('a'), list()))
 [1] TRUE TRUE TRUE TRUE
@@ -42266,6 +42878,18 @@ In pmatch(1:5, c(1, 3), nomatch = "str") : NAs introduced by coercion
 #pmatch(NULL, 1)
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts#
+#pmatch(table=1)
+Error in pmatch(table = 1) : argument "x" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts#
+#pmatch(x=1)
+Error in pmatch(x = 1) : argument "table" is missing, with no default
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testArgumentsCasts#
+#pmatch(x=NULL, table=NULL)
+integer(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_pmatch.testpmatch1#
 #argv <- list('kendall', c('pearson', 'kendall', 'spearman'), 0L, TRUE); .Internal(pmatch(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] 2
@@ -62327,6 +62951,80 @@ Error: 'decreasing' must be TRUE or FALSE
 #{ lv<-list(a=5,b=c(1,2)); .Internal(sort(lv,FALSE)) }
 Error: only atomic vectors can be sorted
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#
+#{ .Internal(qsort(1, F)) }
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError#
+#{ .Internal(qsort(1, decreased=NULL)) }
+$x
+[1] 1
+
+$ix
+[1] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#
+#{ .Internal(qsort(NULL, F)) }
+Error: argument is not a numeric vector
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#
+#{ .Internal(qsort(NULL, NULL)) }
+Error: argument is not a numeric vector
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#
+#{ .Internal(qsort(c(1), F)) }
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError#
+#{ .Internal(qsort(c(4, 2, 3), 'a')) }
+$x
+[1] 2 3 4
+
+$ix
+[1] 2 3 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError#
+#{ .Internal(qsort(c(4, 2, 3), 1)) }
+$x
+[1] 2 3 4
+
+$ix
+[1] 2 3 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError#
+#{ .Internal(qsort(c(4, 2, 3), T)) }
+$x
+[1] 2 3 4
+
+$ix
+[1] 2 3 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError#
+#{ .Internal(qsort(c(4, 2, 3), c('a'))) }
+$x
+[1] 2 3 4
+
+$ix
+[1] 2 3 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#Ignored.ImplementationError#
+#{ .Internal(qsort(c(4, 2, 3), list('a'))) }
+$x
+[1] 2 3 4
+
+$ix
+[1] 2 3 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testQSort#
+#{ .Internal(qsort(list(1), F)) }
+Error: argument is not a numeric vector
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_sort.testSort#
 #{ sort(3:1, index.return=TRUE) }
 $x
-- 
GitLab


From 1f2708cbf91ef890d57c906cf88b6ce519afd3d2 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Mar 2017 13:37:06 +0100
Subject: [PATCH 139/402] remove deprecated calls to createAccess() in interop

---
 .../interop/RForeignAccessFactoryImpl.java    | 36 +++++++++----------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 1b8aca885d..b68c032aa9 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -100,41 +100,41 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
         ForeignAccess foreignAccess = null;
         String name = clazz.getSimpleName();
         if (RNull.class.isAssignableFrom(clazz)) {
-            foreignAccess = RNullMRForeign.createAccess();
+            foreignAccess = RNullMRForeign.ACCESS;
         } else if (RList.class.isAssignableFrom(clazz)) {
-            foreignAccess = RListMRForeign.createAccess();
+            foreignAccess = RListMRForeign.ACCESS;
         } else if (REnvironment.class.isAssignableFrom(clazz)) {
-            foreignAccess = REnvironmentMRForeign.createAccess();
+            foreignAccess = REnvironmentMRForeign.ACCESS;
         } else if (RPairList.class.isAssignableFrom(clazz)) {
-            foreignAccess = RPairListMRForeign.createAccess();
+            foreignAccess = RPairListMRForeign.ACCESS;
         } else if (RFunction.class.isAssignableFrom(clazz)) {
-            foreignAccess = RFunctionMRForeign.createAccess();
+            foreignAccess = RFunctionMRForeign.ACCESS;
         } else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) {
-            foreignAccess = DLLInfoMRForeign.createAccess();
+            foreignAccess = DLLInfoMRForeign.ACCESS;
         } else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) {
-            foreignAccess = DLLDotSymbolMRForeign.createAccess();
+            foreignAccess = DLLDotSymbolMRForeign.ACCESS;
         } else if (RSymbol.class.isAssignableFrom(clazz)) {
-            foreignAccess = RSymbolMRForeign.createAccess();
+            foreignAccess = RSymbolMRForeign.ACCESS;
         } else if (RExternalPtr.class.isAssignableFrom(clazz)) {
-            foreignAccess = RExternalPtrMRForeign.createAccess();
+            foreignAccess = RExternalPtrMRForeign.ACCESS;
         } else if (RUnboundValue.class.isAssignableFrom(clazz)) {
-            foreignAccess = RUnboundValueMRForeign.createAccess();
+            foreignAccess = RUnboundValueMRForeign.ACCESS;
         } else if (NativeRawArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeRawArrayMRForeign.createAccess();
+            foreignAccess = NativeRawArrayMRForeign.ACCESS;
         } else if (NativeLogicalArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeLogicalArrayMRForeign.createAccess();
+            foreignAccess = NativeLogicalArrayMRForeign.ACCESS;
         } else if (NativeCharArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeCharArrayMRForeign.createAccess();
+            foreignAccess = NativeCharArrayMRForeign.ACCESS;
         } else if (NativeDoubleArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeDoubleArrayMRForeign.createAccess();
+            foreignAccess = NativeDoubleArrayMRForeign.ACCESS;
         } else if (NativeIntegerArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeIntegerArrayMRForeign.createAccess();
+            foreignAccess = NativeIntegerArrayMRForeign.ACCESS;
         } else if (RInteger.class.isAssignableFrom(clazz)) {
-            foreignAccess = RIntegerMRForeign.createAccess();
+            foreignAccess = RIntegerMRForeign.ACCESS;
         } else if (RDouble.class.isAssignableFrom(clazz)) {
-            foreignAccess = RDoubleMRForeign.createAccess();
+            foreignAccess = RDoubleMRForeign.ACCESS;
         } else if (CharSXPWrapper.class.isAssignableFrom(clazz)) {
-            foreignAccess = CharSXPWrapperMRForeign.createAccess();
+            foreignAccess = CharSXPWrapperMRForeign.ACCESS;
         } else {
             if (RAbstractVector.class.isAssignableFrom(clazz)) {
                 foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
-- 
GitLab


From 730d98b9c1ddb4721c93f9bb28808081ef265e76 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Mar 2017 13:45:43 +0100
Subject: [PATCH 140/402] simplify access to interop factories (no more
 explicit thread safety management needed)

---
 .../interop/RForeignAccessFactoryImpl.java    | 134 ++++++------------
 1 file changed, 42 insertions(+), 92 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index b68c032aa9..0c91b000ba 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -23,12 +23,9 @@
 package com.oracle.truffle.r.engine.interop;
 
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.MessageResolution;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -49,106 +46,59 @@ import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 
 /**
- * A {@link ForeignAccess} instance captures the {@link Thread} that creates it and all uses are
- * checked against the current thread. Therefore, in a world with multiple {@link PolyglotEngine}s,
- * aka multiple {@link Thread} and {@link RContext} instances, it is not possible to use a simple
- * global constant value for the {@link ForeignAccess} instance that could be associated directly
- * with the {@link TruffleObject} class.
- *
- * This factory provides a generic solution for all FastR types (all of which are
- * {@link TruffleObject}s), at some cost in performance.
- *
  * For most types we use the {@link MessageResolution} facility to automatically generate the
  * factory for creating the {@link ForeignAccess} instance. The exceptions are the (many) subclasses
  * of {@link RAbstractVector} as these have the same handling but the generator cannot handle
  * abstract classes.
- *
  */
 public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
-    private static final class TableEntry {
-        private final Class<? extends RTruffleObject> clazz; // for sanity check
-        private final ForeignAccess foreignAccess;
-        /**
-         * {@link PolyglotEngine} checks the thread on a {@link ForeignAccess}.
-         */
-        private final Thread thread;
-
-        private TableEntry(Class<? extends RTruffleObject> clazz, ForeignAccess foreignAccess) {
-            this.clazz = clazz;
-            this.foreignAccess = foreignAccess;
-            this.thread = Thread.currentThread();
-        }
-    }
-
-    private final TableEntry[] table = new TableEntry[32];
-    int tableIndex;
 
-    private synchronized ForeignAccess get(RTruffleObject obj) {
-        Class<? extends RTruffleObject> objclazz = obj.getClass();
-        Thread thread = Thread.currentThread();
-        for (int i = 0; i < tableIndex; i++) {
-            TableEntry te = table[i];
-            if (te.clazz == objclazz && te.thread == thread) {
-                return te.foreignAccess;
-            }
-        }
-        return createForeignAccess(objclazz);
-    }
-
-    @TruffleBoundary
-    private static ForeignAccess createForeignAccess(Class<? extends RTruffleObject> clazz) {
-        ForeignAccess foreignAccess = null;
-        String name = clazz.getSimpleName();
-        if (RNull.class.isAssignableFrom(clazz)) {
-            foreignAccess = RNullMRForeign.ACCESS;
-        } else if (RList.class.isAssignableFrom(clazz)) {
-            foreignAccess = RListMRForeign.ACCESS;
-        } else if (REnvironment.class.isAssignableFrom(clazz)) {
-            foreignAccess = REnvironmentMRForeign.ACCESS;
-        } else if (RPairList.class.isAssignableFrom(clazz)) {
-            foreignAccess = RPairListMRForeign.ACCESS;
-        } else if (RFunction.class.isAssignableFrom(clazz)) {
-            foreignAccess = RFunctionMRForeign.ACCESS;
-        } else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) {
-            foreignAccess = DLLInfoMRForeign.ACCESS;
-        } else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) {
-            foreignAccess = DLLDotSymbolMRForeign.ACCESS;
-        } else if (RSymbol.class.isAssignableFrom(clazz)) {
-            foreignAccess = RSymbolMRForeign.ACCESS;
-        } else if (RExternalPtr.class.isAssignableFrom(clazz)) {
-            foreignAccess = RExternalPtrMRForeign.ACCESS;
-        } else if (RUnboundValue.class.isAssignableFrom(clazz)) {
-            foreignAccess = RUnboundValueMRForeign.ACCESS;
-        } else if (NativeRawArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeRawArrayMRForeign.ACCESS;
-        } else if (NativeLogicalArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeLogicalArrayMRForeign.ACCESS;
-        } else if (NativeCharArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeCharArrayMRForeign.ACCESS;
-        } else if (NativeDoubleArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeDoubleArrayMRForeign.ACCESS;
-        } else if (NativeIntegerArray.class.isAssignableFrom(clazz)) {
-            foreignAccess = NativeIntegerArrayMRForeign.ACCESS;
-        } else if (RInteger.class.isAssignableFrom(clazz)) {
-            foreignAccess = RIntegerMRForeign.ACCESS;
-        } else if (RDouble.class.isAssignableFrom(clazz)) {
-            foreignAccess = RDoubleMRForeign.ACCESS;
-        } else if (CharSXPWrapper.class.isAssignableFrom(clazz)) {
-            foreignAccess = CharSXPWrapperMRForeign.ACCESS;
+    @Override
+    public ForeignAccess getForeignAccess(RTruffleObject obj) {
+        CompilerAsserts.neverPartOfCompilation("getForeignAccess");
+        if (obj instanceof RNull) {
+            return RNullMRForeign.ACCESS;
+        } else if (obj instanceof RList) {
+            return RListMRForeign.ACCESS;
+        } else if (obj instanceof REnvironment) {
+            return REnvironmentMRForeign.ACCESS;
+        } else if (obj instanceof RPairList) {
+            return RPairListMRForeign.ACCESS;
+        } else if (obj instanceof RFunction) {
+            return RFunctionMRForeign.ACCESS;
+        } else if (obj instanceof DLL.DLLInfo) {
+            return DLLInfoMRForeign.ACCESS;
+        } else if (obj instanceof DLL.DotSymbol) {
+            return DLLDotSymbolMRForeign.ACCESS;
+        } else if (obj instanceof RSymbol) {
+            return RSymbolMRForeign.ACCESS;
+        } else if (obj instanceof RExternalPtr) {
+            return RExternalPtrMRForeign.ACCESS;
+        } else if (obj instanceof RUnboundValue) {
+            return RUnboundValueMRForeign.ACCESS;
+        } else if (obj instanceof NativeRawArray) {
+            return NativeRawArrayMRForeign.ACCESS;
+        } else if (obj instanceof NativeLogicalArray) {
+            return NativeLogicalArrayMRForeign.ACCESS;
+        } else if (obj instanceof NativeCharArray) {
+            return NativeCharArrayMRForeign.ACCESS;
+        } else if (obj instanceof NativeDoubleArray) {
+            return NativeDoubleArrayMRForeign.ACCESS;
+        } else if (obj instanceof NativeIntegerArray) {
+            return NativeIntegerArrayMRForeign.ACCESS;
+        } else if (obj instanceof RInteger) {
+            return RIntegerMRForeign.ACCESS;
+        } else if (obj instanceof RDouble) {
+            return RDoubleMRForeign.ACCESS;
+        } else if (obj instanceof CharSXPWrapper) {
+            return CharSXPWrapperMRForeign.ACCESS;
         } else {
-            if (RAbstractVector.class.isAssignableFrom(clazz)) {
-                foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
+            if (obj instanceof RAbstractVector) {
+                return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
             } else {
-                throw RInternalError.unimplemented("foreignAccess: " + name);
+                throw RInternalError.unimplemented("missing foreign access factory for " + obj.getClass().getSimpleName());
             }
         }
-        return foreignAccess;
-    }
-
-    @Override
-    public ForeignAccess getForeignAccess(RTruffleObject obj) {
-        CompilerAsserts.neverPartOfCompilation("getForeignAccess");
-        return get(obj);
     }
 
     @Override
-- 
GitLab


From c2b073987cdcbcf1a90ffc98175fc838cb846de6 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Mar 2017 14:27:20 +0100
Subject: [PATCH 141/402] maintain proper RContext for foreign access to R
 vectors

---
 .../interop/RAbstractVectorAccessFactory.java    | 15 +++++++++++----
 .../truffle/r/engine/interop/RFunctionMR.java    | 10 ++++------
 .../truffle/r/runtime/data/MemoryCopyTracer.java | 16 ++++++++++++----
 3 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
index 3cb4647f51..75555feaac 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,15 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.ForeignAccess.Factory18;
 import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorReadNodeGen;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -60,6 +63,7 @@ public final class RAbstractVectorAccessFactory implements Factory18 {
         @CompilationFinal private boolean lengthAccess;
         @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
         @Child private RLengthNode lengthNode = RLengthNode.create();
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
         VectorReadNode() {
             super(TruffleRLanguage.class, null, null);
@@ -67,10 +71,13 @@ public final class RAbstractVectorAccessFactory implements Factory18 {
         }
 
         @Override
+        @SuppressWarnings("try")
         public final Object execute(VirtualFrame frame) {
-            Object label = ForeignAccess.getArguments(frame).get(0);
-            Object receiver = ForeignAccess.getReceiver(frame);
-            return execute(frame, receiver, label);
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                Object label = ForeignAccess.getArguments(frame).get(0);
+                Object receiver = ForeignAccess.getReceiver(frame);
+                return execute(frame, receiver, label);
+            }
         }
 
         protected abstract Object execute(VirtualFrame frame, Object reciever, Object label);
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index 8001e76066..34a7bd310d 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -67,12 +67,10 @@ public class RFunctionMR {
 
             RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments, ArgumentsSignature.empty(arguments.length));
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                try {
-                    dummyFrame.setObject(slot, actualArgs);
-                    return call.execute(dummyFrame, receiver);
-                } finally {
-                    dummyFrame.setObject(slot, null);
-                }
+                dummyFrame.setObject(slot, actualArgs);
+                return call.execute(dummyFrame, receiver);
+            } finally {
+                dummyFrame.setObject(slot, null);
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java
index ecba6aeb9d..7316b4b323 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryCopyTracer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,9 @@ import java.util.Deque;
 import java.util.concurrent.ConcurrentLinkedDeque;
 
 import com.oracle.truffle.api.Assumption;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
@@ -71,10 +73,16 @@ public final class MemoryCopyTracer {
      * no-op.
      */
     public static void reportCopying(RAbstractVector source, RAbstractVector dest) {
+        assert RContext.getInstance() != null : "valid context needed whenever copying could be reported";
         if (!noMemoryCopyTracingAssumption.isValid() && enabled) {
-            for (Listener listener : listeners) {
-                listener.reportCopying(source, dest);
-            }
+            notifyListeners(source, dest);
+        }
+    }
+
+    @TruffleBoundary
+    private static void notifyListeners(RAbstractVector source, RAbstractVector dest) {
+        for (Listener listener : listeners) {
+            listener.reportCopying(source, dest);
         }
     }
 
-- 
GitLab


From 0c60fa7d3eb5ebf68cc5e1363e12fd7fd65c4b2d Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 22 Mar 2017 09:38:08 +0100
Subject: [PATCH 142/402] =?UTF-8?q?fill=20lists=20allocated=20from=20nativ?=
 =?UTF-8?q?e=20code=20with=20=E2=80=9CNULL=E2=80=9D=20values?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java    | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

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 e98b5d7988..f16b3e1726 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
@@ -387,7 +387,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             case RAWSXP:
                 return RDataFactory.createRawVector(new byte[n]);
             case VECSXP:
-                return RDataFactory.createList(n);
+                // fill list with "NULL" values
+                RList list = RDataFactory.createList(n);
+                for (int i = 0; i < n; i++) {
+                    list.setElement(i, RNull.instance);
+                }
+                return list;
             case LANGSXP:
                 return RDataFactory.createLangPairList(n);
             default:
-- 
GitLab


From 724e4f6166546f21f106ca84817489324747b4be Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 22 Mar 2017 09:39:53 +0100
Subject: [PATCH 143/402] cache last successful index in findNativeArray

---
 .../fficall/src/jni/rffiutils.c                      | 12 ++++++++++++
 1 file changed, 12 insertions(+)

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 07f347eec3..bec561670d 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -69,6 +69,7 @@ typedef struct nativeArrayTable_struct {
 static NativeArrayElem *nativeArrayTable;
 // hwm of nativeArrayTable
 static int nativeArrayTableHwm;
+static int nativeArrayTableLastIndex;
 static int nativeArrayTableLength;
 static void releaseNativeArray(JNIEnv *env, int index);
 
@@ -209,6 +210,16 @@ void updateNativeArrays(JNIEnv *env) {
 
 
 static void *findNativeArray(JNIEnv *env, SEXP x) {
+    if (nativeArrayTableLastIndex < nativeArrayTableHwm) {
+        NativeArrayElem cv = nativeArrayTable[nativeArrayTableLastIndex];
+        if (cv.obj != NULL && (cv.obj == x || (*env)->IsSameObject(env, cv.obj, x))) {
+            void *data = cv.data;
+#if TRACE_NATIVE_ARRAYS
+            fprintf(traceFile, "findNativeArray(%p): found %p (cached)\n", x, data);
+#endif
+            return data;
+        }
+    }
     int i;
     assert(isValidJNIRef(env, x));
     for (i = 0; i < nativeArrayTableHwm; i++) {
@@ -216,6 +227,7 @@ static void *findNativeArray(JNIEnv *env, SEXP x) {
         if (cv.obj != NULL) {
             assert(isValidJNIRef(env, cv.obj));
             if ((*env)->IsSameObject(env, cv.obj, x)) {
+                nativeArrayTableLastIndex = i;
                 void *data = cv.data;
 #if TRACE_NATIVE_ARRAYS
                 fprintf(traceFile, "findNativeArray(%p): found %p\n", x, data);
-- 
GitLab


From 31708f7055b2d992350f6c256b35c8cf71b52759 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 22 Feb 2017 16:41:04 +0100
Subject: [PATCH 144/402] provide macros and public functions for IS_UTF8, etc.

---
 .../fficall/src/common/inlined_fastr.c              |  3 ++-
 mx.fastr/mx_fastr_edinclude.py                      | 13 +++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
index 72b60fd49b..184f0869ed 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -545,3 +545,4 @@ Rboolean IS_BYTES(SEXP x) { return FALSE; }
 Rboolean IS_LATIN1(SEXP x) { return FALSE; }
 Rboolean IS_ASCII(SEXP x) { return FALSE; }
 Rboolean IS_UTF8(SEXP x) { return TRUE; }
+Rboolean ENC_KNOWN(SEXP x) { return TRUE; }
diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py
index dc211cdd32..3d329b13ac 100644
--- a/mx.fastr/mx_fastr_edinclude.py
+++ b/mx.fastr/mx_fastr_edinclude.py
@@ -61,6 +61,19 @@ sexp = '''#ifdef FASTR
 typedef void *SEXP;
 #define DATAPTR(x)\t\tR_DATAPTR(x)
 void *(R_DATAPTR)(SEXP x);
+
+#define IS_BYTES IS_BYTES
+#define IS_LATIN1 IS_LATIN1
+#define IS_ASCII IS_ASCII
+#define IS_UTF8 IS_UTF8
+#define ENC_KNOWN ENC_KNOWN
+
+Rboolean IS_BYTES(SEXP x);
+Rboolean IS_LATIN1(SEXP x);
+Rboolean IS_ASCII(SEXP x);
+Rboolean IS_UTF8(SEXP x);
+Rboolean ENC_KNOWN(SEXP x);
+
 #else
 '''
 use_internals_begin = '''#if defined (USE_RINTERNALS_DEFS) && (defined (USE_RINTERNALS) || defined (FASTR))
-- 
GitLab


From c25307880538e059281b4f3e5277b5fc54ec5757 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 22 Mar 2017 11:49:31 +0100
Subject: [PATCH 145/402] move reset of condition handlers into finally block

---
 .../builtin/base/ConditionFunctions.java      |  8 +--
 .../truffle/r/runtime/RErrorHandling.java     | 63 ++++++++++---------
 .../truffle/r/test/ExpectedTestOutput.test    | 44 ++++++++++++-
 .../base/condition/R/withCallingHandlers0.R   | 28 ++++++++-
 .../base/condition/R/withCallingHandlers1.R   | 29 ++++++++-
 5 files changed, 133 insertions(+), 39 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
index b2cf2f7964..1c65b8139a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
@@ -181,11 +181,9 @@ public class ConditionFunctions {
         @TruffleBoundary
         protected RNull invokeRestart(RList restart, Object args) {
             checkLength(restart);
-            if (RErrorHandling.invokeRestart(restart, args) == null) {
-                throw error(RError.Message.RESTART_NOT_ON_STACK);
-            } else {
-                return RNull.instance; // not reached
-            }
+            RErrorHandling.invokeRestart(restart, args);
+            // invokeRestart is expected to always return via a ReturnException
+            throw error(RError.Message.RESTART_NOT_ON_STACK);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 422a861da9..9b2ea12cf9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -321,7 +321,7 @@ public class RErrorHandling {
         result.setClassAttr(RESTART_CLASS);
     }
 
-    public static Object invokeRestart(RList restart, Object args) {
+    public static void invokeRestart(RList restart, Object args) {
         ContextStateImpl errorHandlingState = getRErrorHandlingState();
         Object exit = restartExit(restart);
         if (exit == RNull.instance) {
@@ -338,7 +338,6 @@ public class RErrorHandling {
                 }
                 errorHandlingState.restartStack = pList.cdr();
             }
-            return null;
         }
     }
 
@@ -346,23 +345,26 @@ public class RErrorHandling {
     public static void signalCondition(RList cond, String msg, Object call) {
         ContextStateImpl errorHandlingState = getRErrorHandlingState();
         Object oldStack = errorHandlingState.handlerStack;
-        RPairList pList;
-        while ((pList = findConditionHandler(cond)) != null) {
-            RList entry = (RList) pList.car();
-            errorHandlingState.handlerStack = pList.cdr();
-            if (isCallingEntry(entry)) {
-                Object h = entry.getDataAt(ENTRY_HANDLER);
-                if (h == RESTART_TOKEN) {
-                    errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg);
+        try {
+            RPairList pList;
+            while ((pList = findConditionHandler(cond)) != null) {
+                RList entry = (RList) pList.car();
+                errorHandlingState.handlerStack = pList.cdr();
+                if (isCallingEntry(entry)) {
+                    Object h = entry.getDataAt(ENTRY_HANDLER);
+                    if (h == RESTART_TOKEN) {
+                        errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg);
+                    } else {
+                        RFunction hf = (RFunction) h;
+                        RContext.getEngine().evalFunction(hf, null, null, null, cond);
+                    }
                 } else {
-                    RFunction hf = (RFunction) h;
-                    RContext.getEngine().evalFunction(hf, null, null, null, cond);
+                    throw gotoExitingHandler(cond, call, entry);
                 }
-            } else {
-                throw gotoExitingHandler(cond, call, entry);
             }
+        } finally {
+            errorHandlingState.handlerStack = oldStack;
         }
-        errorHandlingState.handlerStack = oldStack;
     }
 
     /**
@@ -374,24 +376,27 @@ public class RErrorHandling {
         String fMsg = formatMessage(msg, args);
         ContextStateImpl errorHandlingState = getRErrorHandlingState();
         Object oldStack = errorHandlingState.handlerStack;
-        RPairList pList;
-        while ((pList = findSimpleErrorHandler()) != null) {
-            RList entry = (RList) pList.car();
-            errorHandlingState.handlerStack = pList.cdr();
-            errorHandlingState.errMsg = fMsg;
-            if (isCallingEntry(entry)) {
-                if (entry.getDataAt(ENTRY_HANDLER) == RESTART_TOKEN) {
-                    return;
+        try {
+            RPairList pList;
+            while ((pList = findSimpleErrorHandler()) != null) {
+                RList entry = (RList) pList.car();
+                errorHandlingState.handlerStack = pList.cdr();
+                errorHandlingState.errMsg = fMsg;
+                if (isCallingEntry(entry)) {
+                    if (entry.getDataAt(ENTRY_HANDLER) == RESTART_TOKEN) {
+                        return;
+                    } else {
+                        RFunction handler = (RFunction) entry.getDataAt(2);
+                        RStringVector errorMsgVec = RDataFactory.createStringVectorFromScalar(fMsg);
+                        RContext.getRRuntimeASTAccess().callback(handler, new Object[]{errorMsgVec, call});
+                    }
                 } else {
-                    RFunction handler = (RFunction) entry.getDataAt(2);
-                    RStringVector errorMsgVec = RDataFactory.createStringVectorFromScalar(fMsg);
-                    RContext.getRRuntimeASTAccess().callback(handler, new Object[]{errorMsgVec, call});
+                    throw gotoExitingHandler(RNull.instance, call, entry);
                 }
-            } else {
-                throw gotoExitingHandler(RNull.instance, call, entry);
             }
+        } finally {
+            errorHandlingState.handlerStack = oldStack;
         }
-        errorHandlingState.handlerStack = oldStack;
     }
 
     private static ReturnException gotoExitingHandler(Object cond, Object call, RList entry) throws ReturnException {
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 8895517620..7543a2447f 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
@@ -76472,11 +76472,51 @@ f first 1
 #{f<-function(x){UseMethod("f")};f.logical<-function(x){print("logical")};f(TRUE)}
 [1] "logical"
 
-##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#Ignored.Unknown#
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R") }
+{
+    fun1("first")
+    fun1("second")
+}
+[1] "enter fun1 first"
+[1] "enter handle_myCondition myCondition: signalfirst\n"
+[1] "continue"
+[1] "exit fun1 first"
+[1] "enter fun1 second"
+[1] "enter handle_myCondition myCondition: signalsecond\n"
+[1] "continue"
+[1] "exit fun1 second"
+[1] "exit fun0"
+[1] "enter fun1 first"
+[1] "enter handle_myCondition myCondition: signalfirst\n"
+[1] "continue"
+[1] "exit fun1 first"
+[1] "enter fun1 second"
+[1] "enter handle_myCondition myCondition: signalsecond\n"
+[1] "continue"
+[1] "exit fun1 second"
+NULL
+[1] "exit fun0"
 
-##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#Ignored.Unknown#
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R") }
+{
+    fun1("first")
+    fun1("second")
+}
+[1] "enter fun1 first"
+[1] "enter handle_cond1 cond1: signalfirst\n"
+[1] "after cond1 restart"
+[1] "enter handle_cond0 cond0: signalfirst\n"
+[1] "continue"
+[1] "exit fun1 first"
+[1] "enter fun1 second"
+[1] "enter handle_cond1 cond1: signalsecond\n"
+[1] "after cond1 restart"
+[1] "enter handle_cond0 cond0: signalsecond\n"
+[1] "continue"
+[1] "exit fun1 second"
+[1] "exit fun0"
 [1] "enter fun1 first"
 [1] "enter handle_cond1 cond1: signalfirst\n"
 [1] "after cond1 restart"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R
index 85acd59a6a..d5e10d06e1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R
@@ -1,4 +1,26 @@
-# Ignored
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
 myCondition <- function(message) structure(list(message=message, call=NULL), class=c("myCondition", "condition"))
 
 handle_myCondition <- function(e) {
@@ -27,6 +49,10 @@ fun1 <- function(s) {
 	NULL
 }
 
+fun0(quote({
+	fun1("first")
+	fun1("second")
+}))
 fun0({
 	fun1("first")
 	fun1("second")
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R
index 0345697134..2ad7faa555 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R
@@ -1,4 +1,26 @@
-# Ignored
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
 cond0 <- function(message)
   structure(list(message=message, call=NULL), class=c("cond0", "condition"))
 
@@ -38,8 +60,11 @@ fun1 <- function(s) {
 	NULL
 }
 
+fun0(quote({
+	fun1("first")
+	fun1("second")
+}))
 fun0({
 	fun1("first")
 	fun1("second")
 })
-
-- 
GitLab


From 469722010087f1f0b0b32fb144c1ddd9a33729f4 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 22 Mar 2017 12:17:12 +0100
Subject: [PATCH 146/402] work around Java number formatting bug for small
 numbers

---
 .../base/printer/DoubleVectorPrinter.java     |  15 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 196 +++++-------------
 .../com/oracle/truffle/r/test/S4/TestR5.java  |   2 +-
 .../r/test/builtins/TestBuiltin_abs.java      |   5 +-
 .../r/test/builtins/TestBuiltin_asdouble.java |   3 +-
 .../r/test/builtins/TestBuiltin_deparse.java  |  22 +-
 .../r/test/builtins/TestBuiltin_exp.java      |   4 +-
 .../r/test/builtins/TestBuiltin_list.java     |   3 +-
 .../test/builtins/TestBuiltin_operators.java  |   3 +-
 .../r/test/builtins/TestBuiltin_sep.java      |   5 +-
 .../r/test/builtins/TestBuiltin_split.java    |   5 +-
 .../r/test/builtins/TestBuiltin_tdefault.java |   4 +-
 .../r/test/builtins/TestBuiltin_unlist.java   |   6 +-
 13 files changed, 94 insertions(+), 179 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
index ac9c3b375c..b692c0fd51 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -406,7 +406,18 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
             return prependBlanks(w, id);
         } else if (e != 0) {
             String fmt = String.format((d != 0) ? "%%#%d.%de" : "%%%d.%de", Math.min(w, (NB - 1)), d);
-            return snprintf(NB, fmt, x).replace('.', cdec);
+            String result;
+            if (Math.abs(x) < 1e-300 && Math.abs(x) >= Double.MIN_VALUE) {
+                // work around java formatting bug for small numbers like 1.53160350210786e-322
+                result = snprintf(NB, fmt, x * 1e100);
+                StringBuilder str = new StringBuilder(result);
+                assert str.charAt(str.length() - 3) == '2';
+                str.setCharAt(str.length() - 3, '3');
+                result = str.toString();
+            } else {
+                result = snprintf(NB, fmt, x);
+            }
+            return result.replace('.', cdec);
         } else { /* e = 0 */
             DecimalFormat df = null;
             if (d < CACHED_FORMATS.length) {
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 8895517620..54fafba051 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
@@ -128,7 +128,7 @@ NULL
 #{ clazz <- setRefClass('Foo27R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a <- 20 }
 Error: invalid replacement: reference class field ‘a’ is read-only
 
-##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Ignored.ReferenceError#
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.ImprovedErrorContext#
 #{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() }
 Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
   replacing substrings in a non-character object
@@ -2142,7 +2142,7 @@ Frequency = 1
  [6]  1.000000000  0.000000000  1.957854406 48.498545455          Inf
 [11]  1.000000000  1.000000000  0.342969777  0.007071754
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testabs4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_abs.testabs4#
 #argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));abs(argv[[1]]);
   [1]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
   [6] 1.753688e-134  0.000000e+00  0.000000e+00  0.000000e+00 2.604776e-251
@@ -6372,7 +6372,7 @@ numeric(0)
 #argv <- list(structure(c(21, 16.4, 18.7, 16.8, 17.8, 10.9, 14, 3.5, 4.3, 3.5, 2.7, 6, 14, 2.3), .Dim = c(7L, 2L), .Dimnames = list(c('L', 'NL', 'D', 'B', 'F', 'IRL', 'UK'), c('x', 'y'))));as.double(argv[[1]]);
  [1] 21.0 16.4 18.7 16.8 17.8 10.9 14.0  3.5  4.3  3.5  2.7  6.0 14.0  2.3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble14#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble14#
 #argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707712e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.96881154539801e-173, 0, 8.23599653846971e-150, 0, 0, 0, 0, 6.51733217171342e-10, 0, 2.36840184577368e-67, 0, 9.43484083575241e-307, 0, 1.59959906013772e-89, 0, 8.73836857865035e-286, 7.09716190970993e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044552e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.07028772732371e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.75227273320951e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));as.double(argv[[1]]);
   [1]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
   [6] 1.753688e-134  0.000000e+00  0.000000e+00  0.000000e+00 2.604776e-251
@@ -16850,7 +16850,7 @@ Error in print(x, y) :
 #deparse(1)
 [1] "1"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#
 #deparse(1.53160350210786e-322)
 [1] "1.53160350210786e-322"
 
@@ -17302,13 +17302,9 @@ a[a <- TRUE]
 #argv <- list(Inf, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "Inf"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse19#Ignored.Unknown#
-#argv <- list(structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c('Female', 'Male'), class = 'factor'), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c('F30', 'M01', 'M04'), class = 'factor')), .Names = c('Sex', 'age', 'Subject'), row.names = c(NA, -6L), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
-[1] "structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c(\"Female\", "
-[2] "\"Male\"), class = \"factor\"), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, "
-[3] "2L, 1L, 1L, 3L, 3L), .Label = c(\"F30\", \"M01\", \"M04\"), class = \"factor\")), .Names = c(\"Sex\", "
-[4] "\"age\", \"Subject\"), row.names = c(NA, -6L), class = \"data.frame\")"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse19#Output.IgnoreWhitespace#
+#cat({argv <- list(structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c('Female', 'Male'), class = 'factor'), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c('F30', 'M01', 'M04'), class = 'factor')), .Names = c('Sex', 'age', 'Subject'), row.names = c(NA, -6L), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c("Female",  "Male"), class = "factor"), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L,  2L, 1L, 1L, 3L, 3L), .Label = c("F30", "M01", "M04"), class = "factor")), .Names = c("Sex",  "age", "Subject"), row.names = c(NA, -6L), class = "data.frame")
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse2#
 #argv <- list(quote(rnorm(1, sd = Inf)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "rnorm(1, sd = Inf)"
@@ -17329,34 +17325,16 @@ a[a <- TRUE]
 #argv <- list(quote(cor(Z[, FALSE], use = 'pairwise.complete.obs', method = 'kendall')), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "cor(Z[, FALSE], use = \"pairwise.complete.obs\", method = \"kendall\")"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse24#Ignored.Unknown#
-#argv <- list(c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
- [1] "c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, "
- [2] "9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, "
- [3] "12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, "
- [4] "14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, "
- [5] "9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, "
- [6] "8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, "
- [7] "11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, "
- [8] "9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, "
- [9] "15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, "
-[10] "13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, "
-[11] "14.3, 8, 11.5)"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse24#Output.IgnoreWhitespace#
+#cat({argv <- list(c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9,  9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7,  12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6,  14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7,  9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9,  8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5,  11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6,  9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4,  15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9,  13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2,  14.3, 8, 11.5)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse25#
 #argv <- list(1e+05, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "1e+05"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse26#Ignored.Unknown#
-#argv <- list(structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c('M02', 'M01'), class = c('ordered', 'factor')), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('distance', 'age', 'Subject', 'Sex'), row.names = c('1', '2', '3', '4', '5', '6'), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
-[1] "structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, "
-[2] "10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, "
-[3] "1L), .Label = c(\"M02\", \"M01\"), class = c(\"ordered\", \"factor\")), "
-[4] "    Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c(\"Male\", "
-[5] "    \"Female\"), class = \"factor\")), .Names = c(\"distance\", \"age\", "
-[6] "\"Subject\", \"Sex\"), row.names = c(\"1\", \"2\", \"3\", \"4\", \"5\", \"6\""
-[7] "), class = \"data.frame\")"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse26#Output.IgnoreWhitespace#
+#cat({argv <- list(structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c('M02', 'M01'), class = c('ordered', 'factor')), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('distance', 'age', 'Subject', 'Sex'), row.names = c('1', '2', '3', '4', '5', '6'), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8,  10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L,  1L), .Label = c("M02", "M01"), class = c("ordered", "factor")),      Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c("Male",      "Female"), class = "factor")), .Names = c("distance", "age",  "Subject", "Sex"), row.names = c("1", "2", "3", "4", "5", "6" ), class = "data.frame")
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse27#
 #argv <- list('\t *ERROR* !!\n', 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "\"\\t *ERROR* !!\\n\""
@@ -17377,26 +17355,12 @@ a[a <- TRUE]
 #argv <- list(structure(FALSE, .Dim = 1L), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "structure(FALSE, .Dim = 1L)"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse31#Ignored.Unknown#
-#argv <- list(c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
-[1] "c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, "
-[2] "0.587785252292473, 1.22464679914735e-16, -0.587785252292473, "
-[3] "-0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, "
-[4] "0.587785252292473, 0.951056516295154)"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse32#Ignored.Unknown#
-#argv <- list(structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = 'ts'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
- [1] "structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, "
- [2] "46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, "
- [3] "62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, "
- [4] "39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, "
- [5] "45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, "
- [6] "62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, "
- [7] "39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, "
- [8] "45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, "
- [9] "62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, "
-[10] "40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = \"ts\")"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse31#Output.IgnoreWhitespace#
+#cat({argv <- list(c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154,  0.587785252292473, 1.22464679914735e-16, -0.587785252292473,  -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16,  0.587785252292473, 0.951056516295154)
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse32#Output.IgnoreWhitespace#
+#cat({argv <- list(structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = 'ts'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+structure(c(39.384847580955, 40.3469409309138, 42.6018205723052,  46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058,  62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114,  39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483,  45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145,  62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378,  39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543,  45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139,  62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742,  40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = "ts")
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse33#
 #argv <- list(NA_real_, 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "NA_real_"
@@ -17405,57 +17369,9 @@ a[a <- TRUE]
 #argv <- list(quote(lm(formula = y ~ x1 + x2 + x3)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "lm(formula = y ~ x1 + x2 + x3)"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse35#Ignored.Unknown#
-#argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
- [1] "structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, "
- [2] "104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, "
- [3] "140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, "
- [4] "171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, "
- [5] "196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, "
- [6] "235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, "
- [7] "269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, "
- [8] "318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, "
- [9] "422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, "
-[10] "491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, "
-[11] "559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, "
-[12] "508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[13] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[14] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[15] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[16] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[17] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[18] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[19] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[20] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[21] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[22] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, "
-[23] "391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, "
-[24] "517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, "
-[25] "428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, "
-[26] "388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, "
-[27] "513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, "
-[28] "423.494870357491, 363.43932958967, 400.592058645117, NA, NA, "
-[29] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[30] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[31] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[32] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[33] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[34] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[35] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[36] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "
-[37] "NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, "
-[38] "462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, "
-[39] "657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, "
-[40] "576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, "
-[41] "565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, "
-[42] "804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, "
-[43] "707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, "
-[44] "3L), .Dimnames = list(NULL, c(\"structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, \", "
-[45] "\"structure(c(419.147602949539, 391.474665943444, 435.919286153217, \", "
-[46] "\"structure(c(484.030717075782, 462.954959541421, 526.353307750503, \""
-[47] ")), .Tsp = c(1949, 1962.91666666667, 12), class = c(\"mts\", \"ts\", "
-[48] "\"matrix\"))"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse35#Output.IgnoreWhitespace#
+#cat({argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119,  104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114,  140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166,  171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196,  196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188,  235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267,  269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313,  318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355,  422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435,  491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548,  559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606,  508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539,  391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445,  517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116,  428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428,  388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866,  513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118,  423.494870357491, 363.43932958967, 400.592058645117, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,  NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782,  462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676,  657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864,  576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767,  565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962,  804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072,  707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L,  3L), .Dimnames = list(NULL, c("structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ",  "structure(c(419.147602949539, 391.474665943444, 435.919286153217, ",  "structure(c(484.030717075782, 462.954959541421, 526.353307750503, " )), .Tsp = c(1949, 1962.91666666667, 12), class = c("mts", "ts",  "matrix"))
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse36#
 #argv <- list(numeric(0), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "numeric(0)"
@@ -17495,11 +17411,9 @@ invalid 'cutoff' value for 'deparse', using default
 [1] "glm(formula = y ~ x, family = poisson(identity), start = c(1, "
 [2] "    0))"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse44#Ignored.Unknown#
-#argv <- list(quote(lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
-[1] "lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + "
-[2] "    DriveTrain, data = Cars93)"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse44#Output.IgnoreWhitespace#
+#cat({argv <- list(quote(lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize +      DriveTrain, data = Cars93)
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse45#
 #argv <- list(0.333333333333333, 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "0.333333333333333"
@@ -17525,11 +17439,9 @@ invalid 'cutoff' value for 'deparse', using default
 #argv <- list(quote(5 * exp(-x)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "5 * exp(-x)"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse7#Ignored.Unknown#
-#argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
-[1] "y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - "
-[2] "    exp(-k * (Tb - Ta)))))"
-
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse7#Output.IgnoreWhitespace#
+#cat({argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))})
+y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 -      exp(-k * (Tb - Ta)))))
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testdeparse8#
 #argv <- list(quote(tt <- table(c(rep(0, 7), rep(1, 4), rep(5, 3)))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "tt <- table(c(rep(0, 7), rep(1, 4), rep(5, 3)))"
@@ -23101,7 +23013,7 @@ Error in exp() : 0 arguments passed to 'exp' which requires 1
 [41] 6.221958e+21 2.421950e-01 1.309385e+01 3.972165e-01 7.452503e-03
 [46] 9.494906e-01 1.450621e+00 2.421950e-01 2.346339e+19
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_exp.testexp11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_exp.testexp11#
 #argv <- list(c(-745, -744, -743, -742, -741, -740, -730, -720, -710, -709, -708, -707, -706, -705));exp(argv[[1]]);
  [1] 4.940656e-324 9.881313e-324 1.976263e-323 5.434722e-323 1.531604e-322
  [6] 4.199558e-322 9.226315e-318 2.032231e-313 4.476286e-309 1.216781e-308
@@ -32509,7 +32421,7 @@ attr(,"class")
 [5,] -0.4969603 -0.31475219  0.45819205 -0.65231472  0.1360408
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist55#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist55#
 #argv <- list(object = c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));list(argv[[1]]);
 [[1]]
   [1]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
@@ -40638,7 +40550,7 @@ logical(0)
 [4,]  0.9639849-0.0000000i -0.28432636+0.08075397i
 [5,] -0.2883506-0.1520081i  0.06831370+0.09270951i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators324#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators324#
 #argv <- list(c(0, 0, 0, 0, 0, 0, 4.94065645841247e-324, 0, 0, 0, 0, 0), structure(c(73.0102287440125, 79.6161885135717, 81.5497837663961, 53.9710956454646, 43.6831159601594, 20.8581884349194, 7.6155030786098, 10.8008470888011, 14.7201505829463, 8.49167208457355, 101.686214382123, 921.711710792497), .Names = c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1')));`%*%`(argv[[1]],argv[[2]]);
               [,1]
 [1,] 3.952525e-323
@@ -48711,7 +48623,7 @@ Read 2 records
 #argv <- list(1, 1);`/`(argv[[1]],argv[[2]]);
 [1] 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sep.testsep10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sep.testsep10#
 #argv <- list(c(0, 9.88131291682493e-324, 1.03753785626662e-322, 1.02271588689138e-321, 1.02320995253722e-320, 1.02330876566639e-319, 1.02329394369701e-318, 1.02329295556572e-317, 1.02329300497229e-316, 1.02329299015032e-315, 1.02329299212658e-314, 1.0232929922748e-313, 1.02329299227974e-312, 1.02329299228073e-311, 1.02329299228073e-310, 1.02329299228073e-309, 1.02329299228073e-308, 1.02329299228073e-307), 1.02329299228075);`/`(argv[[1]],argv[[2]]);
  [1]  0.000000e+00 9.881313e-324 1.037538e-322 9.980126e-322 9.999889e-321
  [6] 1.000038e-319 9.999987e-319 9.999997e-318 1.000000e-316 1.000000e-315
@@ -63667,7 +63579,7 @@ $`2`
    0.0000 1514.0769    0.0000  936.0000    0.0000
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit4#
 #argv <- list(structure(c(0, 0, 0, 0, 0, 0, 1.48219693752374e-323, 0, 0, 0, 0, 0), .Dim = c(1L, 12L), .Dimnames = list(NULL, c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = '1', class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))
 $`1`
  [1]  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00  0.000000e+00
@@ -68373,7 +68285,7 @@ attr(,"assign")
      object
 [1,] "foo"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tdefault.testtdefault13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tdefault.testtdefault13#
 #argv <- list(structure(c(0, 0, 0, 0, 0, 0, 3.95252516672997e-323, 0, 0, 0, 0, 0), .Dim = c(12L, 1L))); .Internal(t.default(argv[[1]]))
      [,1] [,2] [,3] [,4] [,5] [,6]          [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    0    0    0    0    0    0 3.952525e-323    0    0     0     0     0
@@ -70672,7 +70584,7 @@ attr(,"Rd_tag")
 #argv <- list(list(c(13823, NA)), TRUE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
 [1] 13823    NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist20#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist20#
 #argv <- list(structure(list(`1` = 2.47032822920623e-323), .Names = '1'), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
             1
 2.470328e-323
@@ -70816,8 +70728,8 @@ $c
 [1] NA
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist27#Ignored.Unknown#
-#argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474, -0.985826700409291, -2.88892067167955, -0.640481702565115, 0.570507635920485, -0.05972327604261, -0.0981787440052344, 0.560820728620116, -1.18645863857947, 1.09677704427424, -0.00534402827816569, 0.707310667398079, 1.03410773473746, 0.223480414915304, -0.878707612866019, 1.16296455596733, -2.00016494478548, -0.544790740001725, -0.255670709156989, -0.166121036765006, 1.02046390878411)), row.names = c(NA, -100L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist27#Output.IgnoreWhitespace#
+#argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474)), row.names = c(NA, -80L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
 [[1]]
   [1]  0.398105880 -0.612026393  0.341119691 -1.129363096  1.433023702
   [6]  1.980399899 -0.367221476 -1.044134626  0.569719627 -0.135054604
@@ -70864,26 +70776,20 @@ attr(,"class")
 [1] "shingle"
 
 [[2]]
-  [1]  0.450187101 -0.018559833 -0.318068375 -0.929362147 -1.487460310
-  [6] -1.075192297  1.000028804 -0.621266695 -1.384426847  1.869290622
- [11]  0.425100377 -0.238647101  1.058483049  0.886422651 -0.619243048
- [16]  2.206102465 -0.255027030 -1.424494650 -0.144399602  0.207538339
- [21]  2.307978399  0.105802368  0.456998805 -0.077152935 -0.334000842
- [26] -0.034726028  0.787639606  2.075245009  1.027392439  1.207908398
- [31] -1.231323422  0.983895570  0.219924804 -1.467250029  0.521022743
- [36] -0.158754605  1.464587312 -0.766082000 -0.430211754 -0.926109497
- [41] -0.177103961  0.402011779 -0.731748173  0.830373168 -1.208082786
- [46] -1.047984413  1.441157707 -1.015847465  0.411974712 -0.381076051
- [51]  0.409401840  1.688873286  1.586588433 -0.330907801 -2.285235535
- [56]  2.497661590  0.667066167  0.541327336 -0.013399523  0.510108423
- [61] -0.164375832  0.420694643 -0.400246744 -1.370207878  0.987838267
- [66]  1.519745025 -0.308740569 -1.253289756  0.642241306 -0.044709137
- [71] -1.733218407  0.002131860 -0.630300334 -0.340968580 -1.156572363
- [76]  1.803141908 -0.331132036 -1.605513412  0.197193439  0.263175646
- [81] -0.985826700 -2.888920672 -0.640481703  0.570507636 -0.059723276
- [86] -0.098178744  0.560820729 -1.186458639  1.096777044 -0.005344028
- [91]  0.707310667  1.034107735  0.223480415 -0.878707613  1.162964556
- [96] -2.000164945 -0.544790740 -0.255670709 -0.166121037  1.020463909
+ [1]  0.45018710 -0.01855983 -0.31806837 -0.92936215 -1.48746031 -1.07519230
+ [7]  1.00002880 -0.62126669 -1.38442685  1.86929062  0.42510038 -0.23864710
+[13]  1.05848305  0.88642265 -0.61924305  2.20610246 -0.25502703 -1.42449465
+[19] -0.14439960  0.20753834  2.30797840  0.10580237  0.45699881 -0.07715294
+[25] -0.33400084 -0.03472603  0.78763961  2.07524501  1.02739244  1.20790840
+[31] -1.23132342  0.98389557  0.21992480 -1.46725003  0.52102274 -0.15875460
+[37]  1.46458731 -0.76608200 -0.43021175 -0.92610950 -0.17710396  0.40201178
+[43] -0.73174817  0.83037317 -1.20808279 -1.04798441  1.44115771 -1.01584747
+[49]  0.41197471 -0.38107605  0.40940184  1.68887329  1.58658843 -0.33090780
+[55] -2.28523554  2.49766159  0.66706617  0.54132734 -0.01339952  0.51010842
+[61] -0.16437583  0.42069464 -0.40024674 -1.37020788  0.98783827  1.51974503
+[67] -0.30874057 -1.25328976  0.64224131 -0.04470914 -1.73321841  0.00213186
+[73] -0.63030033 -0.34096858 -1.15657236  1.80314191 -0.33113204 -1.60551341
+[79]  0.19719344  0.26317565
 
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist28#
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index f9955dfb45..fc5c557832 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -101,7 +101,7 @@ public class TestR5 extends TestBase {
         assertEval("{ clazz <- setRefClass('Foo27R5', fields = list(a = 'numeric')); clazz$lock('a'); obj <- clazz$new(); obj$a <- 10; obj$a <- 20 }");
 
         // generate getter and setter
-        assertEval(Ignored.ReferenceError, "{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() }");
+        assertEval(Output.ImprovedErrorContext, "{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric', b = 'character')); clazz$accessors(); clazz$methods() }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java
index c15b3706a2..041fd9ad90 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -35,8 +35,7 @@ public class TestBuiltin_abs extends TestBase {
 
     @Test
     public void testabs4() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));abs(argv[[1]]);");
+        assertEval("argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));abs(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
index 2277c79179..8cdead0a43 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
@@ -84,8 +84,7 @@ public class TestBuiltin_asdouble extends TestBase {
 
     @Test
     public void testasdouble14() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707712e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.96881154539801e-173, 0, 8.23599653846971e-150, 0, 0, 0, 0, 6.51733217171342e-10, 0, 2.36840184577368e-67, 0, 9.43484083575241e-307, 0, 1.59959906013772e-89, 0, 8.73836857865035e-286, 7.09716190970993e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044552e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.07028772732371e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.75227273320951e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));as.double(argv[[1]]);");
+        assertEval("argv <- list(c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707712e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.96881154539801e-173, 0, 8.23599653846971e-150, 0, 0, 0, 0, 6.51733217171342e-10, 0, 2.36840184577368e-67, 0, 9.43484083575241e-307, 0, 1.59959906013772e-89, 0, 8.73836857865035e-286, 7.09716190970993e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044552e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.07028772732371e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.75227273320951e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));as.double(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
index da7f2560bc..04bb15c4d3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
@@ -21,6 +21,10 @@ import com.oracle.truffle.r.test.TestBase;
 // Checkstyle: stop line length check
 public class TestBuiltin_deparse extends TestBase {
 
+    private void assertEvalDeparsed(String snippet) {
+        assertEval(Output.IgnoreWhitespace, "cat({" + snippet + "})");
+    }
+
     @Test
     public void testdeparse1() {
         assertEval("argv <- list(quote(rsp), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
@@ -53,7 +57,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse7() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -114,7 +118,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse19() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(structure(list(Sex = structure(c(2L, 2L, 1L, 1L, 2L, 2L), .Label = c('Female', 'Male'), class = 'factor'), age = c(15, 20, 10, 12, 2, 4), Subject = structure(c(2L, 2L, 1L, 1L, 3L, 3L), .Label = c('F30', 'M01', 'M04'), class = 'factor')), .Names = c('Sex', 'age', 'Subject'), row.names = c(NA, -6L), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -140,7 +144,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse24() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(c(7.4, 8, 12.6, 11.5, 14.3, 14.9, 8.6, 13.8, 20.1, 8.6, 6.9, 9.7, 9.2, 10.9, 13.2, 11.5, 12, 18.4, 11.5, 9.7, 9.7, 16.6, 9.7, 12, 16.6, 14.9, 8, 12, 14.9, 5.7, 7.4, 8.6, 9.7, 16.1, 9.2, 8.6, 14.3, 9.7, 6.9, 13.8, 11.5, 10.9, 9.2, 8, 13.8, 11.5, 14.9, 20.7, 9.2, 11.5, 10.3, 6.3, 1.7, 4.6, 6.3, 8, 8, 10.3, 11.5, 14.9, 8, 6.9, 13.8, 7.4, 6.9, 7.4, 4.6, 4, 10.3, 8, 8.6, 11.5, 11.5, 11.5, 9.7, 11.5, 10.3, 6.3, 7.4, 10.9, 10.3, 15.5, 14.3, 12.6, 9.7, 3.4, 8, 5.7, 9.7, 2.3, 6.3, 6.3, 6.9, 5.1, 2.8, 4.6, 7.4, 15.5, 10.9, 10.3, 10.9, 9.7, 14.9, 15.5, 6.3, 10.9, 11.5, 6.9, 13.8, 10.3, 10.3, 8, 12.6, 9.2, 10.3, 10.3, 16.6, 6.9, 13.2, 14.3, 8, 11.5), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -151,7 +155,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse26() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(structure(list(distance = c(26, 25, 29, 31, 21.5, 22.5), age = c(8, 10, 12, 14, 8, 10), Subject = structure(c(2L, 2L, 2L, 2L, 1L, 1L), .Label = c('M02', 'M01'), class = c('ordered', 'factor')), Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L), .Label = c('Male', 'Female'), class = 'factor')), .Names = c('distance', 'age', 'Subject', 'Sex'), row.names = c('1', '2', '3', '4', '5', '6'), class = 'data.frame'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -177,13 +181,13 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse31() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(c(0, 0.587785252292473, 0.951056516295154, 0.951056516295154, 0.587785252292473, 1.22464679914735e-16, -0.587785252292473, -0.951056516295154, -0.951056516295154, -0.587785252292473, -2.44929359829471e-16, 0.587785252292473, 0.951056516295154), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
     public void testdeparse32() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(structure(c(39.384847580955, 40.3469409309138, 42.6018205723052, 46.6665176252597, 51.3438205965467, 60.0069972599329, 64.6480892875058, 62.5709232928432, 57.679739382496, 49.5060394945433, 43.474726406114, 39.8236314289602, 38.361391396627, 37.9275637097922, 43.6868952734483, 45.1919846859641, 51.722520194987, 59.3399821539983, 61.9345241730145, 62.1515308754468, 57.6561604617486, 49.2849925780811, 42.606775772378, 39.6394677676018, 38.6328048791077, 38.4418602988203, 43.1520834957543, 45.6551746936999, 51.7999631155049, 59.5021948495759, 62.9217123388139, 62.0751910659837, 57.8048619656866, 49.5091658164884, 42.8045075272742, 40.2515159054665), .Tsp = c(1937, 1939.91666666667, 12), class = 'ts'), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -199,7 +203,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse35() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 60L, FALSE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -245,7 +249,7 @@ public class TestBuiltin_deparse extends TestBase {
 
     @Test
     public void testdeparse44() {
-        assertEval(Ignored.Unknown,
+        assertEvalDeparsed(
                         "argv <- list(quote(lm(formula = 1000/MPG.city ~ Weight + Cylinders + Type + EngineSize + DriveTrain, data = Cars93)), 60L, TRUE, 69, -1L); .Internal(deparse(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
@@ -286,7 +290,7 @@ public class TestBuiltin_deparse extends TestBase {
     public void testDeparse() {
         assertEval(template("deparse(%0)", VALUES));
         assertEval(template("deparse(quote(cat(%0)))", VALUES));
-        assertEval(Ignored.OutputFormatting, "deparse(1.53160350210786e-322)");
+        assertEval("deparse(1.53160350210786e-322)");
         assertEval("{ deparse(new.env()) }");
         assertEval("{ k <- 2 ; deparse(k) }");
         assertEval("{ deparse(round) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java
index 9093f0b0e0..86d353663c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_exp.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -64,7 +64,7 @@ public class TestBuiltin_exp extends TestBase {
 
     @Test
     public void testexp11() {
-        assertEval(Ignored.Unknown, "argv <- list(c(-745, -744, -743, -742, -741, -740, -730, -720, -710, -709, -708, -707, -706, -705));exp(argv[[1]]);");
+        assertEval("argv <- list(c(-745, -744, -743, -742, -741, -740, -730, -720, -710, -709, -708, -707, -706, -705));exp(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java
index 28dbce4917..0c1ddfeaa1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java
@@ -292,8 +292,7 @@ public class TestBuiltin_list extends TestBase {
 
     @Test
     public void testlist55() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(object = c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));list(argv[[1]]);");
+        assertEval("argv <- list(object = c(0, 0, 0, 0, 0, 1.75368801162502e-134, 0, 0, 0, 2.60477585273833e-251, 1.16485035372295e-260, 0, 1.53160350210786e-322, 0.333331382328728, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.44161262707711e-123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.968811545398e-173, 0, 8.2359965384697e-150, 0, 0, 0, 0, 6.51733217171341e-10, 0, 2.36840184577368e-67, 0, 9.4348408357524e-307, 0, 1.59959906013771e-89, 0, 8.73836857865034e-286, 7.09716190970992e-54, 0, 0, 0, 1.530425353017e-274, 8.57590058044551e-14, 0.333333106397154, 0, 0, 1.36895217898448e-199, 2.0226102635783e-177, 5.50445388209462e-42, 0, 0, 0, 0, 1.07846402051283e-44, 1.88605464411243e-186, 1.09156111051203e-26, 0, 3.0702877273237e-124, 0.333333209689785, 0, 0, 0, 0, 0, 0, 3.09816093866831e-94, 0, 0, 4.7522727332095e-272, 0, 0, 2.30093251441394e-06, 0, 0, 1.27082826644707e-274, 0, 0, 0, 0, 0, 0, 0, 4.5662025456054e-65, 0, 2.77995853978268e-149, 0, 0, 0));list(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
index b2dd1d1206..52807ae955 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
@@ -1622,8 +1622,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators324() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(0, 0, 0, 0, 0, 0, 4.94065645841247e-324, 0, 0, 0, 0, 0), structure(c(73.0102287440125, 79.6161885135717, 81.5497837663961, 53.9710956454646, 43.6831159601594, 20.8581884349194, 7.6155030786098, 10.8008470888011, 14.7201505829463, 8.49167208457355, 101.686214382123, 921.711710792497), .Names = c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1')));`%*%`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(c(0, 0, 0, 0, 0, 0, 4.94065645841247e-324, 0, 0, 0, 0, 0), structure(c(73.0102287440125, 79.6161885135717, 81.5497837663961, 53.9710956454646, 43.6831159601594, 20.8581884349194, 7.6155030786098, 10.8008470888011, 14.7201505829463, 8.49167208457355, 101.686214382123, 921.711710792497), .Names = c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1')));`%*%`(argv[[1]],argv[[2]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java
index 3d0a2e63d3..25ebda8276 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -64,8 +64,7 @@ public class TestBuiltin_sep extends TestBase {
 
     @Test
     public void testsep10() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(0, 9.88131291682493e-324, 1.03753785626662e-322, 1.02271588689138e-321, 1.02320995253722e-320, 1.02330876566639e-319, 1.02329394369701e-318, 1.02329295556572e-317, 1.02329300497229e-316, 1.02329299015032e-315, 1.02329299212658e-314, 1.0232929922748e-313, 1.02329299227974e-312, 1.02329299228073e-311, 1.02329299228073e-310, 1.02329299228073e-309, 1.02329299228073e-308, 1.02329299228073e-307), 1.02329299228075);`/`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(c(0, 9.88131291682493e-324, 1.03753785626662e-322, 1.02271588689138e-321, 1.02320995253722e-320, 1.02330876566639e-319, 1.02329394369701e-318, 1.02329295556572e-317, 1.02329300497229e-316, 1.02329299015032e-315, 1.02329299212658e-314, 1.0232929922748e-313, 1.02329299227974e-312, 1.02329299228073e-311, 1.02329299228073e-310, 1.02329299228073e-309, 1.02329299228073e-308, 1.02329299228073e-307), 1.02329299228075);`/`(argv[[1]],argv[[2]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java
index 46b21139af..234bd45d02 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -36,8 +36,7 @@ public class TestBuiltin_split extends TestBase {
 
     @Test
     public void testsplit4() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0, 0, 0, 0, 0, 0, 1.48219693752374e-323, 0, 0, 0, 0, 0), .Dim = c(1L, 12L), .Dimnames = list(NULL, c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = '1', class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(0, 0, 0, 0, 0, 0, 1.48219693752374e-323, 0, 0, 0, 0, 0), .Dim = c(1L, 12L), .Dimnames = list(NULL, c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = '1', class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java
index 58b7bf9977..6773ef1d1a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -79,7 +79,7 @@ public class TestBuiltin_tdefault extends TestBase {
 
     @Test
     public void testtdefault13() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(0, 0, 0, 0, 0, 0, 3.95252516672997e-323, 0, 0, 0, 0, 0), .Dim = c(12L, 1L))); .Internal(t.default(argv[[1]]))");
+        assertEval("argv <- list(structure(c(0, 0, 0, 0, 0, 0, 3.95252516672997e-323, 0, 0, 0, 0, 0), .Dim = c(12L, 1L))); .Internal(t.default(argv[[1]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java
index 3bf186353d..7508bec871 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java
@@ -117,7 +117,7 @@ public class TestBuiltin_unlist extends TestBase {
 
     @Test
     public void testunlist20() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(list(`1` = 2.47032822920623e-323), .Names = '1'), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(list(`1` = 2.47032822920623e-323), .Names = '1'), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -152,8 +152,8 @@ public class TestBuiltin_unlist extends TestBase {
 
     @Test
     public void testunlist27() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474, -0.985826700409291, -2.88892067167955, -0.640481702565115, 0.570507635920485, -0.05972327604261, -0.0981787440052344, 0.560820728620116, -1.18645863857947, 1.09677704427424, -0.00534402827816569, 0.707310667398079, 1.03410773473746, 0.223480414915304, -0.878707612866019, 1.16296455596733, -2.00016494478548, -0.544790740001725, -0.255670709156989, -0.166121036765006, 1.02046390878411)), row.names = c(NA, -100L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval(Output.IgnoreWhitespace,
+                        "argv <- list(list(structure(list(structure(c(0.398105880367068, -0.612026393250771, 0.341119691424425, -1.12936309608079, 1.43302370170104, 1.98039989850586, -0.367221476466509, -1.04413462631653, 0.569719627442413, -0.135054603880824, 2.40161776050478, -0.0392400027331692, 0.689739362450777, 0.0280021587806661, -0.743273208882405, 0.188792299514343, -1.80495862889104, 1.46555486156289, 0.153253338211898, 2.17261167036215, 0.475509528899663, -0.709946430921815, 0.610726353489055, -0.934097631644252, -1.2536334002391, 0.291446235517463, -0.443291873218433, 0.00110535163162413, 0.0743413241516641, -0.589520946188072, -0.568668732818502, -0.135178615123832, 1.1780869965732, -1.52356680042976, 0.593946187628422, 0.332950371213518, 1.06309983727636, -0.304183923634301, 0.370018809916288, 0.267098790772231, -0.54252003099165, 1.20786780598317, 1.16040261569495, 0.700213649514998, 1.58683345454085, 0.558486425565304, -1.27659220845804, -0.573265414236886, -1.22461261489836, -0.473400636439312, -0.620366677224124, 0.0421158731442352, -0.910921648552446, 0.158028772404075, -0.654584643918818, 1.76728726937265, 0.716707476017206, 0.910174229495227, 0.384185357826345, 1.68217608051942, -0.635736453948977, -0.461644730360566, 1.43228223854166, -0.650696353310367, -0.207380743601965, -0.392807929441984, -0.319992868548507, -0.279113302976559, 0.494188331267827, -0.177330482269606, -0.505957462114257, 1.34303882517041, -0.214579408546869, -0.179556530043387, -0.100190741213562, 0.712666307051405, -0.0735644041263263, -0.0376341714670479, -0.681660478755657, -0.324270272246319, 0.0601604404345152, -0.588894486259664, 0.531496192632572, -1.51839408178679, 0.306557860789766, -1.53644982353759, -0.300976126836611, -0.528279904445006, -0.652094780680999, -0.0568967778473925, -1.91435942568001, 1.17658331201856, -1.664972436212, -0.463530401472386, -1.11592010504285, -0.750819001193448, 2.08716654562835, 0.0173956196932517, -1.28630053043433, -1.64060553441858), .Label = structure(list(c(-1.91442143130152, -0.573203408615382), c(-0.934159637265755, -0.300914121215107), c(-0.568730738440006, 0.0174576253147555), c(-0.279175308598063, 0.384247363447848), c(0.0279401531591622, 1.16046462131646), c(0.398043874745564, 2.40167976612628)), class = 'shingleLevel'), class = 'shingle')), row.names = c(NA, -100L), class = 'data.frame'), structure(list(c(0.450187101272656, -0.018559832714638, -0.318068374543844, -0.929362147453702, -1.48746031014148, -1.07519229661568, 1.00002880371391, -0.621266694796823, -1.38442684738449, 1.86929062242358, 0.425100377372448, -0.238647100913033, 1.05848304870902, 0.886422651374936, -0.619243048231147, 2.20610246454047, -0.255027030141015, -1.42449465021281, -0.144399601954219, 0.207538339232345, 2.30797839905936, 0.105802367893711, 0.456998805423414, -0.077152935356531, -0.334000842366544, -0.0347260283112762, 0.787639605630162, 2.07524500865228, 1.02739243876377, 1.2079083983867, -1.23132342155804, 0.983895570053379, 0.219924803660651, -1.46725002909224, 0.521022742648139, -0.158754604716016, 1.4645873119698, -0.766081999604665, -0.430211753928547, -0.926109497377437, -0.17710396143654, 0.402011779486338, -0.731748173119606, 0.830373167981674, -1.20808278630446, -1.04798441280774, 1.44115770684428, -1.01584746530465, 0.411974712317515, -0.38107605110892, 0.409401839650934, 1.68887328620405, 1.58658843344197, -0.330907800682766, -2.28523553529247, 2.49766158983416, 0.667066166765493, 0.5413273359637, -0.0133995231459087, 0.510108422952926, -0.164375831769667, 0.420694643254513, -0.400246743977644, -1.37020787754746, 0.987838267454879, 1.51974502549955, -0.308740569225614, -1.25328975560769, 0.642241305677824, -0.0447091368939791, -1.73321840682484, 0.00213185968026965, -0.630300333928146, -0.340968579860405, -1.15657236263585, 1.80314190791747, -0.331132036391221, -1.60551341225308, 0.197193438739481, 0.263175646405474)), row.names = c(NA, -80L), class = 'data.frame')), FALSE, FALSE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
-- 
GitLab


From d6e21d32c1eb01fbdc948b359891624ac87e7f8a Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 21 Mar 2017 10:44:31 +0100
Subject: [PATCH 147/402] fix quote for empty args

---
 .../com/oracle/truffle/r/nodes/builtin/base/Quote.java    | 7 +++++++
 .../src/com/oracle/truffle/r/test/ExpectedTestOutput.test | 8 ++++++++
 .../oracle/truffle/r/test/builtins/TestBuiltin_quote.java | 6 +++++-
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
index 98620c384f..a43472d12f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
@@ -31,9 +31,11 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 
 @RBuiltin(name = "quote", nonEvalArgs = 0, kind = PRIMITIVE, parameterNames = {"expr"}, behavior = PURE)
 public abstract class Quote extends RBuiltinNode {
@@ -76,4 +78,9 @@ public abstract class Quote extends RBuiltinNode {
     protected Object quote(RPromise expr) {
         return createLanguage(expr.getClosure());
     }
+
+    @Specialization
+    protected Object quote(@SuppressWarnings("unused") RMissing expr) {
+        return RSymbol.MISSING;
+    }
 }
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 8895517620..68647559a3 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
@@ -44791,6 +44791,10 @@ $ix
 #{ quit("xx") }
 Error in quit(save, status, runLast) : unrecognized value of 'save'
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote#Ignored.ImplementationError#
+#quote()
+Error in quote() : 0 arguments passed to 'quote' which requires 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote#
 #quote(?'+')
 `?`("+")
@@ -44807,6 +44811,10 @@ Error in quit(save, status, runLast) : unrecognized value of 'save'
 #quote(?sum)
 `?`(sum)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote#
+#quote(expr=)
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_quote.testQuote#
 #{ class(quote(x + y)) }
 [1] "call"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java
index 19382e734f..2eeee80799 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_quote.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -41,5 +41,9 @@ public class TestBuiltin_quote extends TestBase {
         assertEval("quote(??show)");
         assertEval("quote(?`[[`)");
         assertEval("quote(?'+')");
+
+        // in GNUR, these behave inconsistently:
+        assertEval(Ignored.ImplementationError, "quote()");
+        assertEval("quote(expr=)");
     }
 }
-- 
GitLab


From 0c3001ed97eee0f952d19f3bc05d5abd80a76b28 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 22 Mar 2017 15:45:28 +0100
Subject: [PATCH 148/402] Fix: NPE in all.names when skipping a parameter.

---
 .../com/oracle/truffle/r/nodes/builtin/base/AllNames.java   | 5 ++++-
 .../src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java  | 6 ++++++
 .../src/com/oracle/truffle/r/test/ExpectedTestOutput.test   | 4 ++++
 .../truffle/r/test/builtins/TestBuiltin_allnames.java       | 4 +++-
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
index d93063eb23..0feeb054e6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
@@ -108,7 +108,10 @@ public abstract class AllNames extends RBuiltinNode {
         protected Void visit(RSyntaxCall element) {
             accept(element.getSyntaxLHS());
             for (RSyntaxElement arg : element.getSyntaxArguments()) {
-                accept(arg);
+                // unmatched arguments may still be null
+                if (arg != null) {
+                    accept(arg);
+                }
             }
             return null;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
index dc146c10aa..99ae59e013 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -60,6 +61,11 @@ public abstract class AnyNA extends RBuiltinNode {
         casts.arg("recursive").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
     }
 
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE};
+    }
+
     private static byte doScalar(boolean isNA) {
         return RRuntime.asLogical(isNA);
     }
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 f93f9ac0ad..f1c58896bf 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
@@ -2700,6 +2700,10 @@ character(0)
 #{ all.names(expression(sin(x+y+x)), unique=T) }
 [1] "sin" "+"   "x"   "y"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testAllNames#
+#{ all.names(quote(switch(x, 'median' =, 'hello' = print('hello case')))) }
+[1] "switch" "x"      "print"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_allnames.testallnames1#
 #argv <- list(quote(y ~ ((g1) * exp((log(g2/g1)) * (1 - exp(-k * (x - Ta)))/(1 - exp(-k * (Tb - Ta)))))), FALSE, -1L, TRUE); .Internal(all.names(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] "y"  "g1" "g2" "k"  "x"  "Ta" "Tb"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java
index 54e5ed2846..d832fd2ef5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_allnames.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -64,5 +64,7 @@ public class TestBuiltin_allnames extends TestBase {
         assertEval("{ all.names(expression(sin(x+y+x)), unique=T) }");
         assertEval("{ all.names(expression(sin(x+y+x)), unique=NULL) }");
         assertEval("{ all.names(expression(sin(x+y+x)), unique=NA) }");
+
+        assertEval("{ all.names(quote(switch(x, 'median' =, 'hello' = print('hello case')))) }");
     }
 }
-- 
GitLab


From f18c38c2e8657adaa5c89929df3cdc1427344e11 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Mar 2017 09:32:25 +0100
Subject: [PATCH 149/402] remove unnecessary "0x00" byte during save

---
 .../nodes/builtin/base/LoadSaveFunctions.java |  2 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 19 ++++++++++++++++++-
 .../r/test/library/base/TestConnections.java  |  6 +++++-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
index 027d33bbf8..01788ee13c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
@@ -236,7 +236,7 @@ public class LoadSaveFunctions {
                 if (!ascii && openConn.isTextMode()) {
                     throw error(RError.Message.CONN_XDR);
                 }
-                openConn.writeChar(ascii ? ASCII_HEADER : XDR_HEADER, 0, "", false);
+                openConn.writeChar(ascii ? ASCII_HEADER : XDR_HEADER, 0, null, false);
                 RSerialize.serialize(openConn, toSave, ascii ? RSerialize.ASCII : RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
             } catch (IOException ex) {
                 throw error(RError.Message.GENERIC, ex.getMessage());
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 7543a2447f..0f04b19455 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
@@ -76896,7 +76896,24 @@ Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
 #{ rv <- charToRaw("Hello"); rc <- rawConnection(rv, "r+"); writeChar(", World", rc); res <- rawToChar(rawConnectionValue(rc)); close(rc); res }
 [1] ", World"
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.Unknown#
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.ImplementationError#
+#conn <- rawConnection(raw(0), "w"); value <- c(1,2,3); save(value, file=conn); rawConnectionValue(conn)
+ [1] 52 44 58 32 0a 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 04 02 00 00
+[26] 00 01 00 04 00 09 00 00 00 05 76 61 6c 75 65 00 00 00 0e 00 00 00 03 3f f0
+[51] 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 08 00 00 00 00 00 00 00 00 00
+[76] fe
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.ImplementationError#
+#conn <- rawConnection(raw(0), "wb"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn)
+  [1] 52 44 58 32 0a 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 04 02 00 00
+ [26] 00 01 00 04 00 09 00 00 00 05 76 61 6c 75 65 00 00 02 13 00 00 00 02 00 00
+ [51] 00 0e 00 00 00 03 3f f0 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 08 00
+ [76] 00 00 00 00 00 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 03 66 6f 6f 00
+[101] 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 6e 61 6d 65 73 00 00 00 10 00
+[126] 00 00 02 00 04 00 09 00 00 00 01 61 00 04 00 09 00 00 00 01 62 00 00 00 fe
+[151] 00 00 00 fe
+
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.ImplementationError#
 #{ s <- "äöüß"; rc <- rawConnection(raw(0), "wb"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }
  [1] 63 33 20 61 34 20 63 33 20 62 36 20 63 33 0a 62 63 20 63 33 20 39 66 0a
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 7ef2680d0a..a727d532ef 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -241,8 +241,12 @@ public class TestConnections extends TestRBase {
     public void testRawWriteBinary() {
 
         // this test is currently ignored, since 'charToRaw' is not compliant
-        assertEval(Ignored.Unknown, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
+        assertEval(Ignored.ImplementationError, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
         assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
+
+        assertEval(Ignored.ImplementationError, "conn <- rawConnection(raw(0), \"wb\"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn)");
+        // ignored because save refuses to write to a rawConnection that is not configured to binary
+        assertEval(Ignored.ImplementationError, "conn <- rawConnection(raw(0), \"w\"); value <- c(1,2,3); save(value, file=conn); rawConnectionValue(conn)");
     }
 
     @Test
-- 
GitLab


From 3c7510d20ddf77ddc4e9ccb433f268f1ced54e41 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 22 Mar 2017 10:35:34 +0100
Subject: [PATCH 150/402] Implemented internal argument matching for internal
 function "rep". This is required to have the same signature as in GnuR and to
 be able to make this function generic.

---
 .../truffle/r/nodes/builtin/base/Repeat.java  | 309 +++++++++++-------
 .../r/nodes/function/ArgumentMatcher.java     |  26 +-
 .../call/PrepareMatchInternalArguments.java   |  81 +++++
 .../truffle/r/test/ExpectedTestOutput.test    |   5 +
 .../com/oracle/truffle/r/test/S4/TestS4.java  |   2 +
 5 files changed, 293 insertions(+), 130 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index 8b92d9861f..1d3f608b04 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -35,21 +35,33 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.RepeatNodeGen.FastRInternalRepeatNodeGen;
+import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineBuilder;
+import com.oracle.truffle.r.nodes.function.FormalArguments;
+import com.oracle.truffle.r.nodes.function.call.PrepareMatchInternalArguments;
+import com.oracle.truffle.r.nodes.function.call.PrepareMatchInternalArgumentsNodeGen;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * The {@code rep} builtin works as follows.
@@ -71,166 +83,213 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  * </ul>
  * </ol>
  */
-@RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "times", "length.out", "each"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
+@RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class Repeat extends RBuiltinNode {
 
-    private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile();
-    @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
+    private static final PipelineBuilder PB_TIMES;
+    private static final PipelineBuilder PB_LENGTH_OUT;
+    private static final PipelineBuilder PB_EACH;
+    private static final FormalArguments FORMALS;
+    private static final int ARG_IDX_TIMES;
+    private static final int ARG_IDX_LENGHT_OUT;
+    private static final int ARG_IDX_EACH;
+
+    @Child private FastRInternalRepeat internalNode = FastRInternalRepeatNodeGen.create();
+    @Child private CastNode castTimes = PB_TIMES.buildNode();
+    @Child private CastNode castLengthOut = PB_LENGTH_OUT.buildNode();
+    @Child private CastNode castEach = PB_EACH.buildNode();
+    @Child private PrepareMatchInternalArguments prepareArgs = PrepareMatchInternalArgumentsNodeGen.create(FORMALS, this);
 
     @Override
     public Object[] getDefaultParameterValues() {
-        return new Object[]{RMissing.instance, 1, RRuntime.INT_NA, 1};
+        return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY};
     }
 
     static {
         Casts casts = new Casts(Repeat.class);
         casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName());
-        casts.arg("times").defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector();
-        casts.arg("length.out").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA,
-                        RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0)));
-        casts.arg("each").asIntegerVector().shouldBe(size(1).or(size(0)), RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED, "each").replaceNA(
-                        1).mustBe(gte(0));
-    }
 
-    protected boolean hasNames(RAbstractVector x) {
-        return getNames.getNames(x) != null;
-    }
+        // prepare cast pipeline nodes for vararg matching
+        PB_TIMES = new PipelineBuilder("times");
+        PB_TIMES.fluent().defaultError(RError.Message.INVALID_ARGUMENT, "times").mustNotBeNull().asIntegerVector();
 
-    @Specialization(guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
-    protected RAbstractVector repNoEachNoNamesSimple(RAbstractDoubleVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
-        int t = times.getDataAt(0);
-        if (t < 0) {
-            throw error(RError.Message.INVALID_ARGUMENT, "times");
-        }
-        int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
-        double[] data = new double[length];
-        Arrays.fill(data, x.getDataAt(0));
-        return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0)));
-    }
+        PB_LENGTH_OUT = new PipelineBuilder("length.out");
+        PB_LENGTH_OUT.fluent().asIntegerVector().shouldBe(size(1).or(size(0)),
+                        RError.Message.FIRST_ELEMENT_USED, "length.out").findFirst(RRuntime.INT_NA,
+                                        RError.Message.FIRST_ELEMENT_USED, "length.out").mustBe(intNA().or(gte(0)));
 
-    @Specialization(guards = {"each > 1", "!hasNames(x)"})
-    protected RAbstractVector repEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
-        if (times.getLength() > 1) {
-            throw error(RError.Message.INVALID_ARGUMENT, "times");
-        }
-        RAbstractVector input = handleEach(x, each);
-        if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-            return handleLengthOut(input, lengthOut, false);
-        } else {
-            return handleTimes(input, times, false);
-        }
+        PB_EACH = new PipelineBuilder("each");
+        PB_EACH.fluent().asIntegerVector().shouldBe(size(1).or(size(0)),
+                        RError.Message.FIRST_ELEMENT_USED, "each").findFirst(1, RError.Message.FIRST_ELEMENT_USED,
+                                        "each").replaceNA(1).mustBe(gte(0));
+
+        ArgumentsSignature signature = ArgumentsSignature.get("times", "length.out", "each");
+        ARG_IDX_TIMES = 0;
+        ARG_IDX_LENGHT_OUT = 1;
+        ARG_IDX_EACH = 2;
+        FORMALS = FormalArguments.createForBuiltin(new Object[]{1, RRuntime.INT_NA, 1}, signature);
     }
 
-    @Specialization(guards = {"each <= 1", "!hasNames(x)"})
-    protected RAbstractVector repNoEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
-        if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-            return handleLengthOut(x, lengthOut, true);
-        } else {
-            return handleTimes(x, times, true);
-        }
+    @Specialization
+    protected Object repeat(VirtualFrame frame, RAbstractVector x, RArgsValuesAndNames args) {
+        RArgsValuesAndNames margs = prepareArgs.execute(args, null);
+
+        // cast arguments
+        Object times = castTimes.execute(margs.getArgument(ARG_IDX_TIMES));
+        Object lengthOut = castLengthOut.execute(margs.getArgument(ARG_IDX_LENGHT_OUT));
+        Object each = castEach.execute(margs.getArgument(ARG_IDX_EACH));
+
+        return internalNode.execute(frame, x, times, lengthOut, each);
     }
 
-    @Specialization(guards = {"each > 1", "hasNames(x)"})
-    protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each,
-                    @Cached("create()") InitAttributesNode initAttributes,
-                    @Cached("createNames()") SetFixedAttributeNode putNames) {
-        if (times.getLength() > 1) {
-            throw error(RError.Message.INVALID_ARGUMENT, "times");
-        }
-        RAbstractVector input = handleEach(x, each);
-        RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
-        RVector<?> r;
-        if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-            names = (RStringVector) handleLengthOut(names, lengthOut, false);
-            r = handleLengthOut(input, lengthOut, false);
-        } else {
-            names = (RStringVector) handleTimes(names, times, false);
-            r = handleTimes(input, times, false);
+    @TypeSystemReference(RTypes.class)
+    abstract static class FastRInternalRepeat extends RBaseNode {
+        private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile();
+
+        @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
+
+        public abstract RAbstractVector execute(VirtualFrame frame, Object... args);
+
+        protected boolean hasNames(RAbstractVector x) {
+            return getNames.getNames(x) != null;
         }
-        putNames.execute(initAttributes.execute(r), names);
-        return r;
-    }
 
-    @Specialization(guards = {"each <= 1", "hasNames(x)"})
-    protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each,
-                    @Cached("create()") InitAttributesNode initAttributes,
-                    @Cached("createNames()") SetFixedAttributeNode putNames) {
-        RStringVector names;
-        RVector<?> r;
-        if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-            names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true);
-            r = handleLengthOut(x, lengthOut, true);
-        } else {
-            names = (RStringVector) handleTimes(getNames.getNames(x), times, true);
-            r = handleTimes(x, times, true);
+        @Specialization(guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
+        protected RAbstractVector repNoEachNoNamesSimple(RAbstractDoubleVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
+            int t = times.getDataAt(0);
+            if (t < 0) {
+                throw error(RError.Message.INVALID_ARGUMENT, "times");
+            }
+            int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
+            double[] data = new double[length];
+            Arrays.fill(data, x.getDataAt(0));
+            return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0)));
         }
-        putNames.execute(initAttributes.execute(r), names);
-        return r;
-    }
 
-    /**
-     * Prepare the input vector by replicating its elements.
-     */
-    private static RVector<?> handleEach(RAbstractVector x, int each) {
-        RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete());
-        for (int i = 0; i < x.getLength(); i++) {
-            for (int j = i * each; j < (i + 1) * each; j++) {
-                r.transferElementSameType(j, x, i);
+        @Specialization(guards = {"each > 1", "!hasNames(x)"})
+        protected RAbstractVector repEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
+            if (times.getLength() > 1) {
+                throw error(RError.Message.INVALID_ARGUMENT, "times");
+            }
+            RAbstractVector input = handleEach(x, each);
+            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
+                return handleLengthOut(input, lengthOut, false);
+            } else {
+                return handleTimes(input, times, false);
             }
         }
-        return r;
-    }
 
-    /**
-     * Extend or truncate the vector to a specified length.
-     */
-    private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut, boolean copyIfSameSize) {
-        if (x.getLength() == lengthOut) {
-            return (RVector<?>) (copyIfSameSize ? x.copy() : x);
+        @Specialization(guards = {"each <= 1", "!hasNames(x)"})
+        protected RAbstractVector repNoEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
+            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
+                return handleLengthOut(x, lengthOut, true);
+            } else {
+                return handleTimes(x, times, true);
+            }
         }
-        return x.copyResized(lengthOut, false);
-    }
 
-    /**
-     * Replicate the vector a given number of times.
-     */
-    private RVector<?> handleTimes(RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) {
-        if (oneTimeGiven.profile(times.getLength() == 1)) {
-            // only one times value is given
-            final int howManyTimes = times.getDataAt(0);
-            if (howManyTimes < 0) {
+        @Specialization(guards = {"each > 1", "hasNames(x)"})
+        protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each,
+                        @Cached("create()") InitAttributesNode initAttributes,
+                        @Cached("createNames()") SetFixedAttributeNode putNames) {
+            if (times.getLength() > 1) {
                 throw error(RError.Message.INVALID_ARGUMENT, "times");
             }
-            if (replicateOnce.profile(howManyTimes == 1)) {
-                return (RVector<?>) (copyIfSameSize ? x.copy() : x);
+            RAbstractVector input = handleEach(x, each);
+            RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
+            RVector<?> r;
+            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
+                names = (RStringVector) handleLengthOut(names, lengthOut, false);
+                r = handleLengthOut(input, lengthOut, false);
             } else {
-                return x.copyResized(x.getLength() * howManyTimes, false);
+                names = (RStringVector) handleTimes(names, times, false);
+                r = handleTimes(input, times, false);
             }
-        } else {
-            // times is a vector with several elements
-            if (x.getLength() != times.getLength()) {
-                throw error(RError.Message.INVALID_ARGUMENT, "times");
-            }
-            // iterate once over the times vector to determine result vector size
-            int resultLength = 0;
-            for (int i = 0; i < times.getLength(); i++) {
-                int t = times.getDataAt(i);
-                if (t < 0) {
-                    throw error(RError.Message.INVALID_ARGUMENT, "times");
-                }
-                resultLength += t;
+            putNames.execute(initAttributes.execute(r), names);
+            return r;
+        }
+
+        @Specialization(guards = {"each <= 1", "hasNames(x)"})
+        protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each,
+                        @Cached("create()") InitAttributesNode initAttributes,
+                        @Cached("createNames()") SetFixedAttributeNode putNames) {
+            RStringVector names;
+            RVector<?> r;
+            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
+                names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true);
+                r = handleLengthOut(x, lengthOut, true);
+            } else {
+                names = (RStringVector) handleTimes(getNames.getNames(x), times, true);
+                r = handleTimes(x, times, true);
             }
-            // create and populate result vector
-            RVector<?> r = x.createEmptySameType(resultLength, x.isComplete());
-            int wp = 0; // write pointer
+            putNames.execute(initAttributes.execute(r), names);
+            return r;
+        }
+
+        /**
+         * Prepare the input vector by replicating its elements.
+         */
+        private static RVector<?> handleEach(RAbstractVector x, int each) {
+            RVector<?> r = x.createEmptySameType(x.getLength() * each, x.isComplete());
             for (int i = 0; i < x.getLength(); i++) {
-                for (int j = 0; j < times.getDataAt(i); ++j, ++wp) {
-                    r.transferElementSameType(wp, x, i);
+                for (int j = i * each; j < (i + 1) * each; j++) {
+                    r.transferElementSameType(j, x, i);
                 }
             }
             return r;
         }
+
+        /**
+         * Extend or truncate the vector to a specified length.
+         */
+        private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut, boolean copyIfSameSize) {
+            if (x.getLength() == lengthOut) {
+                return (RVector<?>) (copyIfSameSize ? x.copy() : x);
+            }
+            return x.copyResized(lengthOut, false);
+        }
+
+        /**
+         * Replicate the vector a given number of times.
+         */
+        private RVector<?> handleTimes(RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) {
+            if (oneTimeGiven.profile(times.getLength() == 1)) {
+                // only one times value is given
+                final int howManyTimes = times.getDataAt(0);
+                if (howManyTimes < 0) {
+                    throw error(RError.Message.INVALID_ARGUMENT, "times");
+                }
+                if (replicateOnce.profile(howManyTimes == 1)) {
+                    return (RVector<?>) (copyIfSameSize ? x.copy() : x);
+                } else {
+                    return x.copyResized(x.getLength() * howManyTimes, false);
+                }
+            } else {
+                // times is a vector with several elements
+                if (x.getLength() != times.getLength()) {
+                    throw error(RError.Message.INVALID_ARGUMENT, "times");
+                }
+                // iterate once over the times vector to determine result vector size
+                int resultLength = 0;
+                for (int i = 0; i < times.getLength(); i++) {
+                    int t = times.getDataAt(i);
+                    if (t < 0) {
+                        throw error(RError.Message.INVALID_ARGUMENT, "times");
+                    }
+                    resultLength += t;
+                }
+                // create and populate result vector
+                RVector<?> r = x.createEmptySameType(resultLength, x.isComplete());
+                int wp = 0; // write pointer
+                for (int i = 0; i < x.getLength(); i++) {
+                    for (int j = 0; j < times.getDataAt(i); ++j, ++wp) {
+                        r.transferElementSameType(wp, x, i);
+                    }
+                }
+                return r;
+            }
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index 1cf534c2eb..850535f538 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -211,10 +211,10 @@ public class ArgumentMatcher {
     }
 
     /**
-     * Used for the implementation of the 'UseMethod' builtin. Reorders the arguments passed into
-     * the called, generic function and prepares them to be passed into the specific function
+     * Used for matching varargs to an internally defined signature. Reorders the arguments passed
+     * into the called, generic function and prepares them to be passed into the specific function
      *
-     * @param target The 'Method' which is going to be 'Use'd
+     * @param formals The formal arguments to match to.
      * @param evaluatedArgs The arguments which are already in evaluated form (as they are directly
      *            taken from the stack)
      * @param s3DefaultArguments default values carried over from S3 group dispatch method (e.g.
@@ -223,8 +223,7 @@ public class ArgumentMatcher {
      * @return A Fresh {@link RArgsValuesAndNames} containing the arguments rearranged and stuffed
      *         with default values (in the form of {@link RPromise}s where needed)
      */
-    public static RArgsValuesAndNames matchArgumentsEvaluated(RRootNode target, RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments, RBaseNode callingNode) {
-        FormalArguments formals = target.getFormalArguments();
+    public static RArgsValuesAndNames matchArgumentsEvaluated(FormalArguments formals, RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments, RBaseNode callingNode) {
         MatchPermutation match = permuteArguments(evaluatedArgs.getSignature(), formals.getSignature(), callingNode, index -> {
             throw RInternalError.unimplemented("S3Dispatch should not have arg length mismatch");
         }, index -> evaluatedArgs.getSignature().getName(index), null);
@@ -261,6 +260,23 @@ public class ArgumentMatcher {
         return new RArgsValuesAndNames(evaledArgs, formals.getSignature());
     }
 
+    /**
+     * Used for the implementation of the 'UseMethod' builtin. Reorders the arguments passed into
+     * the called, generic function and prepares them to be passed into the specific function
+     *
+     * @param target The 'Method' which is going to be 'Use'd
+     * @param evaluatedArgs The arguments which are already in evaluated form (as they are directly
+     *            taken from the stack)
+     * @param s3DefaultArguments default values carried over from S3 group dispatch method (e.g.
+     *            from max to Summary.factor). {@code null} if there are no such arguments.
+     * @param callingNode The {@link Node} invoking the match
+     * @return A Fresh {@link RArgsValuesAndNames} containing the arguments rearranged and stuffed
+     *         with default values (in the form of {@link RPromise}s where needed)
+     */
+    public static RArgsValuesAndNames matchArgumentsEvaluated(RRootNode target, RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments, RBaseNode callingNode) {
+        return matchArgumentsEvaluated(target.getFormalArguments(), evaluatedArgs, s3DefaultArguments, callingNode);
+    }
+
     private static String getErrorForArgument(RNode[] suppliedArgs, ArgumentsSignature suppliedSignature, int index) {
         RNode node = suppliedArgs[index];
         if (node instanceof VarArgNode) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java
new file mode 100644
index 0000000000..23b150ba12
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareMatchInternalArguments.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.function.call;
+
+import java.util.Objects;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.function.ArgumentMatcher;
+import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation;
+import com.oracle.truffle.r.nodes.function.FormalArguments;
+import com.oracle.truffle.r.nodes.function.RCallNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+/**
+ * Basically the same as {@link PrepareArguments} but for a specific set of internal generic
+ * functions using a vararg parameter but expecting a specific amount of parameters by internally
+ * matching them.
+ */
+public abstract class PrepareMatchInternalArguments extends Node {
+
+    protected static final int CACHE_SIZE = 8;
+
+    protected final RBaseNode callingNode;
+    protected final FormalArguments formals;
+
+    protected PrepareMatchInternalArguments(FormalArguments formals, RBaseNode callingNode) {
+        this.callingNode = Objects.requireNonNull(callingNode);
+        this.formals = Objects.requireNonNull(formals);
+    }
+
+    protected MatchPermutation createArguments(ArgumentsSignature supplied) {
+        return ArgumentMatcher.matchArguments(supplied, formals.getSignature(), callingNode, null);
+    }
+
+    @Specialization(limit = "CACHE_SIZE", guards = {"cachedExplicitArgSignature == explicitArgs.getSignature()"})
+    public RArgsValuesAndNames prepare(RArgsValuesAndNames explicitArgs, S3DefaultArguments s3DefaultArguments,
+                    @SuppressWarnings("unused") @Cached("explicitArgs.getSignature()") ArgumentsSignature cachedExplicitArgSignature,
+                    @Cached("createArguments(cachedExplicitArgSignature)") MatchPermutation permutation) {
+        return ArgumentMatcher.matchArgumentsEvaluated(permutation, explicitArgs.getArguments(), s3DefaultArguments, formals);
+    }
+
+    @Fallback
+    @TruffleBoundary
+    public RArgsValuesAndNames prepareGeneric(RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments) {
+        return ArgumentMatcher.matchArgumentsEvaluated(formals, evaluatedArgs, s3DefaultArguments, callingNode);
+    }
+
+    /**
+     * Returns the argument values and corresponding signature. The signature represents the
+     * original call signature reordered in the same way as the arguments. For s3DefaultArguments
+     * motivation see {@link RCallNode#callGroupGeneric}.
+     */
+    public abstract RArgsValuesAndNames execute(RArgsValuesAndNames evaluatedArgs, S3DefaultArguments s3DefaultArguments);
+}
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 8895517620..4dc6655ded 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
@@ -494,6 +494,11 @@ Note: method with signature ‘A2#A1’ chosen for function ‘foo’,
 #{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }
 [1] 10
 
+##com.oracle.truffle.r.test.S4.TestS4.testMethods#
+#{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) }
+Creating a generic function for ‘ifelse’ from package ‘base’ in the global environment
+[1] "ifelse"
+
 ##com.oracle.truffle.r.test.S4.TestS4.testMethods#
 #{ setGeneric("gen", function(o) standardGeneric("gen")); res<-print(setGeneric("gen", function(o) standardGeneric("gen"))); removeGeneric("gen"); res }
 [1] "gen"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 7632dfa95c..5fd998ead2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -126,6 +126,8 @@ public class TestS4 extends TestRBase {
         assertEval("setGeneric('do.call', signature = c('what', 'args'))");
 
         assertEval("{ setClass('A1', representation(a='numeric')); setMethod('length', 'A1', function(x) x@a); obj <- new('A1'); obj@a <- 10; length(obj) }");
+
+        assertEval("{ setClass('A2', representation(a = 'numeric')); setMethod('rep', 'A2', function(x, a, b, c) { c(x@a, a, b, c) }); setMethod('ifelse', c(yes = 'A2'), function(test, yes, no) print(test)) }");
     }
 
     @Test
-- 
GitLab


From cee9b3bdf5a453ad365b6bc701ca79ece02937a9 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 1 Mar 2017 10:31:15 +0100
Subject: [PATCH 151/402] Initial internal grid package support

---
 .../r/library/fastrGrid/ColorNames.java       | 686 ++++++++++++++++++
 .../r/library/fastrGrid/DoSetViewPort.java    | 150 ++++
 .../fastrGrid/DoSetViewPortBuiltin.java       |  51 ++
 .../truffle/r/library/fastrGrid/GPar.java     | 154 ++++
 .../r/library/fastrGrid/GridContext.java      |  50 ++
 .../r/library/fastrGrid/GridState.java        |  82 +++
 .../r/library/fastrGrid/GridStateGetNode.java |  49 ++
 .../r/library/fastrGrid/GridStateSetNode.java |  53 ++
 .../r/library/fastrGrid/GridUtils.java        |  49 ++
 .../fastrGrid/IgnoredGridExternal.java        |  47 ++
 .../r/library/fastrGrid/LGridDirty.java       |  50 ++
 .../r/library/fastrGrid/LInitGrid.java        |  35 +
 .../library/fastrGrid/LInitViewPortStack.java |  37 +
 .../truffle/r/library/fastrGrid/LLines.java   | 109 +++
 .../truffle/r/library/fastrGrid/LNewPage.java |  27 +
 .../truffle/r/library/fastrGrid/LRect.java    |  74 ++
 .../r/library/fastrGrid/LSegments.java        |  77 ++
 .../truffle/r/library/fastrGrid/LText.java    | 125 ++++
 .../r/library/fastrGrid/LUpViewPort.java      |  50 ++
 .../truffle/r/library/fastrGrid/Point.java    |  51 ++
 .../truffle/r/library/fastrGrid/Size.java     |  41 ++
 .../r/library/fastrGrid/TransformMatrix.java  | 101 +++
 .../truffle/r/library/fastrGrid/Unit.java     | 217 ++++++
 .../truffle/r/library/fastrGrid/ViewPort.java |  85 +++
 .../r/library/fastrGrid/ViewPortContext.java  |  58 ++
 .../r/library/fastrGrid/ViewPortLocation.java |  55 ++
 .../library/fastrGrid/ViewPortTransform.java  |  53 ++
 .../fastrGrid/device/DrawingContext.java      |  48 ++
 .../library/fastrGrid/device/GridDevice.java  |  69 ++
 .../fastrGrid/device/JFrameDevice.java        | 132 ++++
 .../truffle/r/library/fastrGrid/fastrGrid.R   |  46 ++
 .../r/library/graphics/FastRFrame.java        |   4 +-
 .../r/nodes/builtin/base/BasePackage.java     |   4 +
 .../foreign/CallAndExternalFunctions.java     |  94 ++-
 .../builtin/base/foreign/LookupAdapter.java   |   5 +
 .../truffle/r/runtime/FastROptions.java       |   1 +
 mx.fastr/copyrights/overrides                 |  21 +
 37 files changed, 3035 insertions(+), 5 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java
new file mode 100644
index 0000000000..18eb3b0964
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java
@@ -0,0 +1,686 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1997-2014, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import java.util.HashMap;
+
+final class ColorNames {
+    private static HashMap<String, String> synonymToHexName;
+
+    public static String findByName(String synonym) {
+        if (synonymToHexName == null) {
+            initialize();
+        }
+        return synonymToHexName.get(synonym);
+    }
+
+    private static void initialize() {
+        synonymToHexName = new HashMap<>(700);
+        synonymToHexName.put("white", "#FFFFFF");
+        synonymToHexName.put("aliceblue", "#F0F8FF");
+        synonymToHexName.put("antiquewhite", "#FAEBD7");
+        synonymToHexName.put("antiquewhite1", "#FFEFDB");
+        synonymToHexName.put("antiquewhite2", "#EEDFCC");
+        synonymToHexName.put("antiquewhite3", "#CDC0B0");
+        synonymToHexName.put("antiquewhite4", "#8B8378");
+        synonymToHexName.put("aquamarine", "#7FFFD4");
+        synonymToHexName.put("aquamarine1", "#7FFFD4");
+        synonymToHexName.put("aquamarine2", "#76EEC6");
+        synonymToHexName.put("aquamarine3", "#66CDAA");
+        synonymToHexName.put("aquamarine4", "#458B74");
+        synonymToHexName.put("azure", "#F0FFFF");
+        synonymToHexName.put("azure1", "#F0FFFF");
+        synonymToHexName.put("azure2", "#E0EEEE");
+        synonymToHexName.put("azure3", "#C1CDCD");
+        synonymToHexName.put("azure4", "#838B8B");
+        synonymToHexName.put("beige", "#F5F5DC");
+        synonymToHexName.put("bisque", "#FFE4C4");
+        synonymToHexName.put("bisque1", "#FFE4C4");
+        synonymToHexName.put("bisque2", "#EED5B7");
+        synonymToHexName.put("bisque3", "#CDB79E");
+        synonymToHexName.put("bisque4", "#8B7D6B");
+        synonymToHexName.put("black", "#000000");
+        synonymToHexName.put("blanchedalmond", "#FFEBCD");
+        synonymToHexName.put("blue", "#0000FF");
+        synonymToHexName.put("blue1", "#0000FF");
+        synonymToHexName.put("blue2", "#0000EE");
+        synonymToHexName.put("blue3", "#0000CD");
+        synonymToHexName.put("blue4", "#00008B");
+        synonymToHexName.put("blueviolet", "#8A2BE2");
+        synonymToHexName.put("brown", "#A52A2A");
+        synonymToHexName.put("brown1", "#FF4040");
+        synonymToHexName.put("brown2", "#EE3B3B");
+        synonymToHexName.put("brown3", "#CD3333");
+        synonymToHexName.put("brown4", "#8B2323");
+        synonymToHexName.put("burlywood", "#DEB887");
+        synonymToHexName.put("burlywood1", "#FFD39B");
+        synonymToHexName.put("burlywood2", "#EEC591");
+        synonymToHexName.put("burlywood3", "#CDAA7D");
+        synonymToHexName.put("burlywood4", "#8B7355");
+        synonymToHexName.put("cadetblue", "#5F9EA0");
+        synonymToHexName.put("cadetblue1", "#98F5FF");
+        synonymToHexName.put("cadetblue2", "#8EE5EE");
+        synonymToHexName.put("cadetblue3", "#7AC5CD");
+        synonymToHexName.put("cadetblue4", "#53868B");
+        synonymToHexName.put("chartreuse", "#7FFF00");
+        synonymToHexName.put("chartreuse1", "#7FFF00");
+        synonymToHexName.put("chartreuse2", "#76EE00");
+        synonymToHexName.put("chartreuse3", "#66CD00");
+        synonymToHexName.put("chartreuse4", "#458B00");
+        synonymToHexName.put("chocolate", "#D2691E");
+        synonymToHexName.put("chocolate1", "#FF7F24");
+        synonymToHexName.put("chocolate2", "#EE7621");
+        synonymToHexName.put("chocolate3", "#CD661D");
+        synonymToHexName.put("chocolate4", "#8B4513");
+        synonymToHexName.put("coral", "#FF7F50");
+        synonymToHexName.put("coral1", "#FF7256");
+        synonymToHexName.put("coral2", "#EE6A50");
+        synonymToHexName.put("coral3", "#CD5B45");
+        synonymToHexName.put("coral4", "#8B3E2F");
+        synonymToHexName.put("cornflowerblue", "#6495ED");
+        synonymToHexName.put("cornsilk", "#FFF8DC");
+        synonymToHexName.put("cornsilk1", "#FFF8DC");
+        synonymToHexName.put("cornsilk2", "#EEE8CD");
+        synonymToHexName.put("cornsilk3", "#CDC8B1");
+        synonymToHexName.put("cornsilk4", "#8B8878");
+        synonymToHexName.put("cyan", "#00FFFF");
+        synonymToHexName.put("cyan1", "#00FFFF");
+        synonymToHexName.put("cyan2", "#00EEEE");
+        synonymToHexName.put("cyan3", "#00CDCD");
+        synonymToHexName.put("cyan4", "#008B8B");
+        synonymToHexName.put("darkblue", "#00008B");
+        synonymToHexName.put("darkcyan", "#008B8B");
+        synonymToHexName.put("darkgoldenrod", "#B8860B");
+        synonymToHexName.put("darkgoldenrod1", "#FFB90F");
+        synonymToHexName.put("darkgoldenrod2", "#EEAD0E");
+        synonymToHexName.put("darkgoldenrod3", "#CD950C");
+        synonymToHexName.put("darkgoldenrod4", "#8B6508");
+        synonymToHexName.put("darkgray", "#A9A9A9");
+        synonymToHexName.put("darkgreen", "#006400");
+        synonymToHexName.put("darkgrey", "#A9A9A9");
+        synonymToHexName.put("darkkhaki", "#BDB76B");
+        synonymToHexName.put("darkmagenta", "#8B008B");
+        synonymToHexName.put("darkolivegreen", "#556B2F");
+        synonymToHexName.put("darkolivegreen1", "#CAFF70");
+        synonymToHexName.put("darkolivegreen2", "#BCEE68");
+        synonymToHexName.put("darkolivegreen3", "#A2CD5A");
+        synonymToHexName.put("darkolivegreen4", "#6E8B3D");
+        synonymToHexName.put("darkorange", "#FF8C00");
+        synonymToHexName.put("darkorange1", "#FF7F00");
+        synonymToHexName.put("darkorange2", "#EE7600");
+        synonymToHexName.put("darkorange3", "#CD6600");
+        synonymToHexName.put("darkorange4", "#8B4500");
+        synonymToHexName.put("darkorchid", "#9932CC");
+        synonymToHexName.put("darkorchid1", "#BF3EFF");
+        synonymToHexName.put("darkorchid2", "#B23AEE");
+        synonymToHexName.put("darkorchid3", "#9A32CD");
+        synonymToHexName.put("darkorchid4", "#68228B");
+        synonymToHexName.put("darkred", "#8B0000");
+        synonymToHexName.put("darksalmon", "#E9967A");
+        synonymToHexName.put("darkseagreen", "#8FBC8F");
+        synonymToHexName.put("darkseagreen1", "#C1FFC1");
+        synonymToHexName.put("darkseagreen2", "#B4EEB4");
+        synonymToHexName.put("darkseagreen3", "#9BCD9B");
+        synonymToHexName.put("darkseagreen4", "#698B69");
+        synonymToHexName.put("darkslateblue", "#483D8B");
+        synonymToHexName.put("darkslategray", "#2F4F4F");
+        synonymToHexName.put("darkslategray1", "#97FFFF");
+        synonymToHexName.put("darkslategray2", "#8DEEEE");
+        synonymToHexName.put("darkslategray3", "#79CDCD");
+        synonymToHexName.put("darkslategray4", "#528B8B");
+        synonymToHexName.put("darkslategrey", "#2F4F4F");
+        synonymToHexName.put("darkturquoise", "#00CED1");
+        synonymToHexName.put("darkviolet", "#9400D3");
+        synonymToHexName.put("deeppink", "#FF1493");
+        synonymToHexName.put("deeppink1", "#FF1493");
+        synonymToHexName.put("deeppink2", "#EE1289");
+        synonymToHexName.put("deeppink3", "#CD1076");
+        synonymToHexName.put("deeppink4", "#8B0A50");
+        synonymToHexName.put("deepskyblue", "#00BFFF");
+        synonymToHexName.put("deepskyblue1", "#00BFFF");
+        synonymToHexName.put("deepskyblue2", "#00B2EE");
+        synonymToHexName.put("deepskyblue3", "#009ACD");
+        synonymToHexName.put("deepskyblue4", "#00688B");
+        synonymToHexName.put("dimgray", "#696969");
+        synonymToHexName.put("dimgrey", "#696969");
+        synonymToHexName.put("dodgerblue", "#1E90FF");
+        synonymToHexName.put("dodgerblue1", "#1E90FF");
+        synonymToHexName.put("dodgerblue2", "#1C86EE");
+        synonymToHexName.put("dodgerblue3", "#1874CD");
+        synonymToHexName.put("dodgerblue4", "#104E8B");
+        synonymToHexName.put("firebrick", "#B22222");
+        synonymToHexName.put("firebrick1", "#FF3030");
+        synonymToHexName.put("firebrick2", "#EE2C2C");
+        synonymToHexName.put("firebrick3", "#CD2626");
+        synonymToHexName.put("firebrick4", "#8B1A1A");
+        synonymToHexName.put("floralwhite", "#FFFAF0");
+        synonymToHexName.put("forestgreen", "#228B22");
+        synonymToHexName.put("gainsboro", "#DCDCDC");
+        synonymToHexName.put("ghostwhite", "#F8F8FF");
+        synonymToHexName.put("gold", "#FFD700");
+        synonymToHexName.put("gold1", "#FFD700");
+        synonymToHexName.put("gold2", "#EEC900");
+        synonymToHexName.put("gold3", "#CDAD00");
+        synonymToHexName.put("gold4", "#8B7500");
+        synonymToHexName.put("goldenrod", "#DAA520");
+        synonymToHexName.put("goldenrod1", "#FFC125");
+        synonymToHexName.put("goldenrod2", "#EEB422");
+        synonymToHexName.put("goldenrod3", "#CD9B1D");
+        synonymToHexName.put("goldenrod4", "#8B6914");
+        synonymToHexName.put("gray", "#BEBEBE");
+        synonymToHexName.put("gray0", "#000000");
+        synonymToHexName.put("gray1", "#030303");
+        synonymToHexName.put("gray2", "#050505");
+        synonymToHexName.put("gray3", "#080808");
+        synonymToHexName.put("gray4", "#0A0A0A");
+        synonymToHexName.put("gray5", "#0D0D0D");
+        synonymToHexName.put("gray6", "#0F0F0F");
+        synonymToHexName.put("gray7", "#121212");
+        synonymToHexName.put("gray8", "#141414");
+        synonymToHexName.put("gray9", "#171717");
+        synonymToHexName.put("gray10", "#1A1A1A");
+        synonymToHexName.put("gray11", "#1C1C1C");
+        synonymToHexName.put("gray12", "#1F1F1F");
+        synonymToHexName.put("gray13", "#212121");
+        synonymToHexName.put("gray14", "#242424");
+        synonymToHexName.put("gray15", "#262626");
+        synonymToHexName.put("gray16", "#292929");
+        synonymToHexName.put("gray17", "#2B2B2B");
+        synonymToHexName.put("gray18", "#2E2E2E");
+        synonymToHexName.put("gray19", "#303030");
+        synonymToHexName.put("gray20", "#333333");
+        synonymToHexName.put("gray21", "#363636");
+        synonymToHexName.put("gray22", "#383838");
+        synonymToHexName.put("gray23", "#3B3B3B");
+        synonymToHexName.put("gray24", "#3D3D3D");
+        synonymToHexName.put("gray25", "#404040");
+        synonymToHexName.put("gray26", "#424242");
+        synonymToHexName.put("gray27", "#454545");
+        synonymToHexName.put("gray28", "#474747");
+        synonymToHexName.put("gray29", "#4A4A4A");
+        synonymToHexName.put("gray30", "#4D4D4D");
+        synonymToHexName.put("gray31", "#4F4F4F");
+        synonymToHexName.put("gray32", "#525252");
+        synonymToHexName.put("gray33", "#545454");
+        synonymToHexName.put("gray34", "#575757");
+        synonymToHexName.put("gray35", "#595959");
+        synonymToHexName.put("gray36", "#5C5C5C");
+        synonymToHexName.put("gray37", "#5E5E5E");
+        synonymToHexName.put("gray38", "#616161");
+        synonymToHexName.put("gray39", "#636363");
+        synonymToHexName.put("gray40", "#666666");
+        synonymToHexName.put("gray41", "#696969");
+        synonymToHexName.put("gray42", "#6B6B6B");
+        synonymToHexName.put("gray43", "#6E6E6E");
+        synonymToHexName.put("gray44", "#707070");
+        synonymToHexName.put("gray45", "#737373");
+        synonymToHexName.put("gray46", "#757575");
+        synonymToHexName.put("gray47", "#787878");
+        synonymToHexName.put("gray48", "#7A7A7A");
+        synonymToHexName.put("gray49", "#7D7D7D");
+        synonymToHexName.put("gray50", "#7F7F7F");
+        synonymToHexName.put("gray51", "#828282");
+        synonymToHexName.put("gray52", "#858585");
+        synonymToHexName.put("gray53", "#878787");
+        synonymToHexName.put("gray54", "#8A8A8A");
+        synonymToHexName.put("gray55", "#8C8C8C");
+        synonymToHexName.put("gray56", "#8F8F8F");
+        synonymToHexName.put("gray57", "#919191");
+        synonymToHexName.put("gray58", "#949494");
+        synonymToHexName.put("gray59", "#969696");
+        synonymToHexName.put("gray60", "#999999");
+        synonymToHexName.put("gray61", "#9C9C9C");
+        synonymToHexName.put("gray62", "#9E9E9E");
+        synonymToHexName.put("gray63", "#A1A1A1");
+        synonymToHexName.put("gray64", "#A3A3A3");
+        synonymToHexName.put("gray65", "#A6A6A6");
+        synonymToHexName.put("gray66", "#A8A8A8");
+        synonymToHexName.put("gray67", "#ABABAB");
+        synonymToHexName.put("gray68", "#ADADAD");
+        synonymToHexName.put("gray69", "#B0B0B0");
+        synonymToHexName.put("gray70", "#B3B3B3");
+        synonymToHexName.put("gray71", "#B5B5B5");
+        synonymToHexName.put("gray72", "#B8B8B8");
+        synonymToHexName.put("gray73", "#BABABA");
+        synonymToHexName.put("gray74", "#BDBDBD");
+        synonymToHexName.put("gray75", "#BFBFBF");
+        synonymToHexName.put("gray76", "#C2C2C2");
+        synonymToHexName.put("gray77", "#C4C4C4");
+        synonymToHexName.put("gray78", "#C7C7C7");
+        synonymToHexName.put("gray79", "#C9C9C9");
+        synonymToHexName.put("gray80", "#CCCCCC");
+        synonymToHexName.put("gray81", "#CFCFCF");
+        synonymToHexName.put("gray82", "#D1D1D1");
+        synonymToHexName.put("gray83", "#D4D4D4");
+        synonymToHexName.put("gray84", "#D6D6D6");
+        synonymToHexName.put("gray85", "#D9D9D9");
+        synonymToHexName.put("gray86", "#DBDBDB");
+        synonymToHexName.put("gray87", "#DEDEDE");
+        synonymToHexName.put("gray88", "#E0E0E0");
+        synonymToHexName.put("gray89", "#E3E3E3");
+        synonymToHexName.put("gray90", "#E5E5E5");
+        synonymToHexName.put("gray91", "#E8E8E8");
+        synonymToHexName.put("gray92", "#EBEBEB");
+        synonymToHexName.put("gray93", "#EDEDED");
+        synonymToHexName.put("gray94", "#F0F0F0");
+        synonymToHexName.put("gray95", "#F2F2F2");
+        synonymToHexName.put("gray96", "#F5F5F5");
+        synonymToHexName.put("gray97", "#F7F7F7");
+        synonymToHexName.put("gray98", "#FAFAFA");
+        synonymToHexName.put("gray99", "#FCFCFC");
+        synonymToHexName.put("gray100", "#FFFFFF");
+        synonymToHexName.put("green", "#00FF00");
+        synonymToHexName.put("green1", "#00FF00");
+        synonymToHexName.put("green2", "#00EE00");
+        synonymToHexName.put("green3", "#00CD00");
+        synonymToHexName.put("green4", "#008B00");
+        synonymToHexName.put("greenyellow", "#ADFF2F");
+        synonymToHexName.put("grey", "#BEBEBE");
+        synonymToHexName.put("grey0", "#000000");
+        synonymToHexName.put("grey1", "#030303");
+        synonymToHexName.put("grey2", "#050505");
+        synonymToHexName.put("grey3", "#080808");
+        synonymToHexName.put("grey4", "#0A0A0A");
+        synonymToHexName.put("grey5", "#0D0D0D");
+        synonymToHexName.put("grey6", "#0F0F0F");
+        synonymToHexName.put("grey7", "#121212");
+        synonymToHexName.put("grey8", "#141414");
+        synonymToHexName.put("grey9", "#171717");
+        synonymToHexName.put("grey10", "#1A1A1A");
+        synonymToHexName.put("grey11", "#1C1C1C");
+        synonymToHexName.put("grey12", "#1F1F1F");
+        synonymToHexName.put("grey13", "#212121");
+        synonymToHexName.put("grey14", "#242424");
+        synonymToHexName.put("grey15", "#262626");
+        synonymToHexName.put("grey16", "#292929");
+        synonymToHexName.put("grey17", "#2B2B2B");
+        synonymToHexName.put("grey18", "#2E2E2E");
+        synonymToHexName.put("grey19", "#303030");
+        synonymToHexName.put("grey20", "#333333");
+        synonymToHexName.put("grey21", "#363636");
+        synonymToHexName.put("grey22", "#383838");
+        synonymToHexName.put("grey23", "#3B3B3B");
+        synonymToHexName.put("grey24", "#3D3D3D");
+        synonymToHexName.put("grey25", "#404040");
+        synonymToHexName.put("grey26", "#424242");
+        synonymToHexName.put("grey27", "#454545");
+        synonymToHexName.put("grey28", "#474747");
+        synonymToHexName.put("grey29", "#4A4A4A");
+        synonymToHexName.put("grey30", "#4D4D4D");
+        synonymToHexName.put("grey31", "#4F4F4F");
+        synonymToHexName.put("grey32", "#525252");
+        synonymToHexName.put("grey33", "#545454");
+        synonymToHexName.put("grey34", "#575757");
+        synonymToHexName.put("grey35", "#595959");
+        synonymToHexName.put("grey36", "#5C5C5C");
+        synonymToHexName.put("grey37", "#5E5E5E");
+        synonymToHexName.put("grey38", "#616161");
+        synonymToHexName.put("grey39", "#636363");
+        synonymToHexName.put("grey40", "#666666");
+        synonymToHexName.put("grey41", "#696969");
+        synonymToHexName.put("grey42", "#6B6B6B");
+        synonymToHexName.put("grey43", "#6E6E6E");
+        synonymToHexName.put("grey44", "#707070");
+        synonymToHexName.put("grey45", "#737373");
+        synonymToHexName.put("grey46", "#757575");
+        synonymToHexName.put("grey47", "#787878");
+        synonymToHexName.put("grey48", "#7A7A7A");
+        synonymToHexName.put("grey49", "#7D7D7D");
+        synonymToHexName.put("grey50", "#7F7F7F");
+        synonymToHexName.put("grey51", "#828282");
+        synonymToHexName.put("grey52", "#858585");
+        synonymToHexName.put("grey53", "#878787");
+        synonymToHexName.put("grey54", "#8A8A8A");
+        synonymToHexName.put("grey55", "#8C8C8C");
+        synonymToHexName.put("grey56", "#8F8F8F");
+        synonymToHexName.put("grey57", "#919191");
+        synonymToHexName.put("grey58", "#949494");
+        synonymToHexName.put("grey59", "#969696");
+        synonymToHexName.put("grey60", "#999999");
+        synonymToHexName.put("grey61", "#9C9C9C");
+        synonymToHexName.put("grey62", "#9E9E9E");
+        synonymToHexName.put("grey63", "#A1A1A1");
+        synonymToHexName.put("grey64", "#A3A3A3");
+        synonymToHexName.put("grey65", "#A6A6A6");
+        synonymToHexName.put("grey66", "#A8A8A8");
+        synonymToHexName.put("grey67", "#ABABAB");
+        synonymToHexName.put("grey68", "#ADADAD");
+        synonymToHexName.put("grey69", "#B0B0B0");
+        synonymToHexName.put("grey70", "#B3B3B3");
+        synonymToHexName.put("grey71", "#B5B5B5");
+        synonymToHexName.put("grey72", "#B8B8B8");
+        synonymToHexName.put("grey73", "#BABABA");
+        synonymToHexName.put("grey74", "#BDBDBD");
+        synonymToHexName.put("grey75", "#BFBFBF");
+        synonymToHexName.put("grey76", "#C2C2C2");
+        synonymToHexName.put("grey77", "#C4C4C4");
+        synonymToHexName.put("grey78", "#C7C7C7");
+        synonymToHexName.put("grey79", "#C9C9C9");
+        synonymToHexName.put("grey80", "#CCCCCC");
+        synonymToHexName.put("grey81", "#CFCFCF");
+        synonymToHexName.put("grey82", "#D1D1D1");
+        synonymToHexName.put("grey83", "#D4D4D4");
+        synonymToHexName.put("grey84", "#D6D6D6");
+        synonymToHexName.put("grey85", "#D9D9D9");
+        synonymToHexName.put("grey86", "#DBDBDB");
+        synonymToHexName.put("grey87", "#DEDEDE");
+        synonymToHexName.put("grey88", "#E0E0E0");
+        synonymToHexName.put("grey89", "#E3E3E3");
+        synonymToHexName.put("grey90", "#E5E5E5");
+        synonymToHexName.put("grey91", "#E8E8E8");
+        synonymToHexName.put("grey92", "#EBEBEB");
+        synonymToHexName.put("grey93", "#EDEDED");
+        synonymToHexName.put("grey94", "#F0F0F0");
+        synonymToHexName.put("grey95", "#F2F2F2");
+        synonymToHexName.put("grey96", "#F5F5F5");
+        synonymToHexName.put("grey97", "#F7F7F7");
+        synonymToHexName.put("grey98", "#FAFAFA");
+        synonymToHexName.put("grey99", "#FCFCFC");
+        synonymToHexName.put("grey100", "#FFFFFF");
+        synonymToHexName.put("honeydew", "#F0FFF0");
+        synonymToHexName.put("honeydew1", "#F0FFF0");
+        synonymToHexName.put("honeydew2", "#E0EEE0");
+        synonymToHexName.put("honeydew3", "#C1CDC1");
+        synonymToHexName.put("honeydew4", "#838B83");
+        synonymToHexName.put("hotpink", "#FF69B4");
+        synonymToHexName.put("hotpink1", "#FF6EB4");
+        synonymToHexName.put("hotpink2", "#EE6AA7");
+        synonymToHexName.put("hotpink3", "#CD6090");
+        synonymToHexName.put("hotpink4", "#8B3A62");
+        synonymToHexName.put("indianred", "#CD5C5C");
+        synonymToHexName.put("indianred1", "#FF6A6A");
+        synonymToHexName.put("indianred2", "#EE6363");
+        synonymToHexName.put("indianred3", "#CD5555");
+        synonymToHexName.put("indianred4", "#8B3A3A");
+        synonymToHexName.put("ivory", "#FFFFF0");
+        synonymToHexName.put("ivory1", "#FFFFF0");
+        synonymToHexName.put("ivory2", "#EEEEE0");
+        synonymToHexName.put("ivory3", "#CDCDC1");
+        synonymToHexName.put("ivory4", "#8B8B83");
+        synonymToHexName.put("khaki", "#F0E68C");
+        synonymToHexName.put("khaki1", "#FFF68F");
+        synonymToHexName.put("khaki2", "#EEE685");
+        synonymToHexName.put("khaki3", "#CDC673");
+        synonymToHexName.put("khaki4", "#8B864E");
+        synonymToHexName.put("lavender", "#E6E6FA");
+        synonymToHexName.put("lavenderblush", "#FFF0F5");
+        synonymToHexName.put("lavenderblush1", "#FFF0F5");
+        synonymToHexName.put("lavenderblush2", "#EEE0E5");
+        synonymToHexName.put("lavenderblush3", "#CDC1C5");
+        synonymToHexName.put("lavenderblush4", "#8B8386");
+        synonymToHexName.put("lawngreen", "#7CFC00");
+        synonymToHexName.put("lemonchiffon", "#FFFACD");
+        synonymToHexName.put("lemonchiffon1", "#FFFACD");
+        synonymToHexName.put("lemonchiffon2", "#EEE9BF");
+        synonymToHexName.put("lemonchiffon3", "#CDC9A5");
+        synonymToHexName.put("lemonchiffon4", "#8B8970");
+        synonymToHexName.put("lightblue", "#ADD8E6");
+        synonymToHexName.put("lightblue1", "#BFEFFF");
+        synonymToHexName.put("lightblue2", "#B2DFEE");
+        synonymToHexName.put("lightblue3", "#9AC0CD");
+        synonymToHexName.put("lightblue4", "#68838B");
+        synonymToHexName.put("lightcoral", "#F08080");
+        synonymToHexName.put("lightcyan", "#E0FFFF");
+        synonymToHexName.put("lightcyan1", "#E0FFFF");
+        synonymToHexName.put("lightcyan2", "#D1EEEE");
+        synonymToHexName.put("lightcyan3", "#B4CDCD");
+        synonymToHexName.put("lightcyan4", "#7A8B8B");
+        synonymToHexName.put("lightgoldenrod", "#EEDD82");
+        synonymToHexName.put("lightgoldenrod1", "#FFEC8B");
+        synonymToHexName.put("lightgoldenrod2", "#EEDC82");
+        synonymToHexName.put("lightgoldenrod3", "#CDBE70");
+        synonymToHexName.put("lightgoldenrod4", "#8B814C");
+        synonymToHexName.put("lightgoldenrodyellow", "#FAFAD2");
+        synonymToHexName.put("lightgray", "#D3D3D3");
+        synonymToHexName.put("lightgreen", "#90EE90");
+        synonymToHexName.put("lightgrey", "#D3D3D3");
+        synonymToHexName.put("lightpink", "#FFB6C1");
+        synonymToHexName.put("lightpink1", "#FFAEB9");
+        synonymToHexName.put("lightpink2", "#EEA2AD");
+        synonymToHexName.put("lightpink3", "#CD8C95");
+        synonymToHexName.put("lightpink4", "#8B5F65");
+        synonymToHexName.put("lightsalmon", "#FFA07A");
+        synonymToHexName.put("lightsalmon1", "#FFA07A");
+        synonymToHexName.put("lightsalmon2", "#EE9572");
+        synonymToHexName.put("lightsalmon3", "#CD8162");
+        synonymToHexName.put("lightsalmon4", "#8B5742");
+        synonymToHexName.put("lightseagreen", "#20B2AA");
+        synonymToHexName.put("lightskyblue", "#87CEFA");
+        synonymToHexName.put("lightskyblue1", "#B0E2FF");
+        synonymToHexName.put("lightskyblue2", "#A4D3EE");
+        synonymToHexName.put("lightskyblue3", "#8DB6CD");
+        synonymToHexName.put("lightskyblue4", "#607B8B");
+        synonymToHexName.put("lightslateblue", "#8470FF");
+        synonymToHexName.put("lightslategray", "#778899");
+        synonymToHexName.put("lightslategrey", "#778899");
+        synonymToHexName.put("lightsteelblue", "#B0C4DE");
+        synonymToHexName.put("lightsteelblue1", "#CAE1FF");
+        synonymToHexName.put("lightsteelblue2", "#BCD2EE");
+        synonymToHexName.put("lightsteelblue3", "#A2B5CD");
+        synonymToHexName.put("lightsteelblue4", "#6E7B8B");
+        synonymToHexName.put("lightyellow", "#FFFFE0");
+        synonymToHexName.put("lightyellow1", "#FFFFE0");
+        synonymToHexName.put("lightyellow2", "#EEEED1");
+        synonymToHexName.put("lightyellow3", "#CDCDB4");
+        synonymToHexName.put("lightyellow4", "#8B8B7A");
+        synonymToHexName.put("limegreen", "#32CD32");
+        synonymToHexName.put("linen", "#FAF0E6");
+        synonymToHexName.put("magenta", "#FF00FF");
+        synonymToHexName.put("magenta1", "#FF00FF");
+        synonymToHexName.put("magenta2", "#EE00EE");
+        synonymToHexName.put("magenta3", "#CD00CD");
+        synonymToHexName.put("magenta4", "#8B008B");
+        synonymToHexName.put("maroon", "#B03060");
+        synonymToHexName.put("maroon1", "#FF34B3");
+        synonymToHexName.put("maroon2", "#EE30A7");
+        synonymToHexName.put("maroon3", "#CD2990");
+        synonymToHexName.put("maroon4", "#8B1C62");
+        synonymToHexName.put("mediumaquamarine", "#66CDAA");
+        synonymToHexName.put("mediumblue", "#0000CD");
+        synonymToHexName.put("mediumorchid", "#BA55D3");
+        synonymToHexName.put("mediumorchid1", "#E066FF");
+        synonymToHexName.put("mediumorchid2", "#D15FEE");
+        synonymToHexName.put("mediumorchid3", "#B452CD");
+        synonymToHexName.put("mediumorchid4", "#7A378B");
+        synonymToHexName.put("mediumpurple", "#9370DB");
+        synonymToHexName.put("mediumpurple1", "#AB82FF");
+        synonymToHexName.put("mediumpurple2", "#9F79EE");
+        synonymToHexName.put("mediumpurple3", "#8968CD");
+        synonymToHexName.put("mediumpurple4", "#5D478B");
+        synonymToHexName.put("mediumseagreen", "#3CB371");
+        synonymToHexName.put("mediumslateblue", "#7B68EE");
+        synonymToHexName.put("mediumspringgreen", "#00FA9A");
+        synonymToHexName.put("mediumturquoise", "#48D1CC");
+        synonymToHexName.put("mediumvioletred", "#C71585");
+        synonymToHexName.put("midnightblue", "#191970");
+        synonymToHexName.put("mintcream", "#F5FFFA");
+        synonymToHexName.put("mistyrose", "#FFE4E1");
+        synonymToHexName.put("mistyrose1", "#FFE4E1");
+        synonymToHexName.put("mistyrose2", "#EED5D2");
+        synonymToHexName.put("mistyrose3", "#CDB7B5");
+        synonymToHexName.put("mistyrose4", "#8B7D7B");
+        synonymToHexName.put("moccasin", "#FFE4B5");
+        synonymToHexName.put("navajowhite", "#FFDEAD");
+        synonymToHexName.put("navajowhite1", "#FFDEAD");
+        synonymToHexName.put("navajowhite2", "#EECFA1");
+        synonymToHexName.put("navajowhite3", "#CDB38B");
+        synonymToHexName.put("navajowhite4", "#8B795E");
+        synonymToHexName.put("navy", "#000080");
+        synonymToHexName.put("navyblue", "#000080");
+        synonymToHexName.put("oldlace", "#FDF5E6");
+        synonymToHexName.put("olivedrab", "#6B8E23");
+        synonymToHexName.put("olivedrab1", "#C0FF3E");
+        synonymToHexName.put("olivedrab2", "#B3EE3A");
+        synonymToHexName.put("olivedrab3", "#9ACD32");
+        synonymToHexName.put("olivedrab4", "#698B22");
+        synonymToHexName.put("orange", "#FFA500");
+        synonymToHexName.put("orange1", "#FFA500");
+        synonymToHexName.put("orange2", "#EE9A00");
+        synonymToHexName.put("orange3", "#CD8500");
+        synonymToHexName.put("orange4", "#8B5A00");
+        synonymToHexName.put("orangered", "#FF4500");
+        synonymToHexName.put("orangered1", "#FF4500");
+        synonymToHexName.put("orangered2", "#EE4000");
+        synonymToHexName.put("orangered3", "#CD3700");
+        synonymToHexName.put("orangered4", "#8B2500");
+        synonymToHexName.put("orchid", "#DA70D6");
+        synonymToHexName.put("orchid1", "#FF83FA");
+        synonymToHexName.put("orchid2", "#EE7AE9");
+        synonymToHexName.put("orchid3", "#CD69C9");
+        synonymToHexName.put("orchid4", "#8B4789");
+        synonymToHexName.put("palegoldenrod", "#EEE8AA");
+        synonymToHexName.put("palegreen", "#98FB98");
+        synonymToHexName.put("palegreen1", "#9AFF9A");
+        synonymToHexName.put("palegreen2", "#90EE90");
+        synonymToHexName.put("palegreen3", "#7CCD7C");
+        synonymToHexName.put("palegreen4", "#548B54");
+        synonymToHexName.put("paleturquoise", "#AFEEEE");
+        synonymToHexName.put("paleturquoise1", "#BBFFFF");
+        synonymToHexName.put("paleturquoise2", "#AEEEEE");
+        synonymToHexName.put("paleturquoise3", "#96CDCD");
+        synonymToHexName.put("paleturquoise4", "#668B8B");
+        synonymToHexName.put("palevioletred", "#DB7093");
+        synonymToHexName.put("palevioletred1", "#FF82AB");
+        synonymToHexName.put("palevioletred2", "#EE799F");
+        synonymToHexName.put("palevioletred3", "#CD6889");
+        synonymToHexName.put("palevioletred4", "#8B475D");
+        synonymToHexName.put("papayawhip", "#FFEFD5");
+        synonymToHexName.put("peachpuff", "#FFDAB9");
+        synonymToHexName.put("peachpuff1", "#FFDAB9");
+        synonymToHexName.put("peachpuff2", "#EECBAD");
+        synonymToHexName.put("peachpuff3", "#CDAF95");
+        synonymToHexName.put("peachpuff4", "#8B7765");
+        synonymToHexName.put("peru", "#CD853F");
+        synonymToHexName.put("pink", "#FFC0CB");
+        synonymToHexName.put("pink1", "#FFB5C5");
+        synonymToHexName.put("pink2", "#EEA9B8");
+        synonymToHexName.put("pink3", "#CD919E");
+        synonymToHexName.put("pink4", "#8B636C");
+        synonymToHexName.put("plum", "#DDA0DD");
+        synonymToHexName.put("plum1", "#FFBBFF");
+        synonymToHexName.put("plum2", "#EEAEEE");
+        synonymToHexName.put("plum3", "#CD96CD");
+        synonymToHexName.put("plum4", "#8B668B");
+        synonymToHexName.put("powderblue", "#B0E0E6");
+        synonymToHexName.put("purple", "#A020F0");
+        synonymToHexName.put("purple1", "#9B30FF");
+        synonymToHexName.put("purple2", "#912CEE");
+        synonymToHexName.put("purple3", "#7D26CD");
+        synonymToHexName.put("purple4", "#551A8B");
+        synonymToHexName.put("red", "#FF0000");
+        synonymToHexName.put("red1", "#FF0000");
+        synonymToHexName.put("red2", "#EE0000");
+        synonymToHexName.put("red3", "#CD0000");
+        synonymToHexName.put("red4", "#8B0000");
+        synonymToHexName.put("rosybrown", "#BC8F8F");
+        synonymToHexName.put("rosybrown1", "#FFC1C1");
+        synonymToHexName.put("rosybrown2", "#EEB4B4");
+        synonymToHexName.put("rosybrown3", "#CD9B9B");
+        synonymToHexName.put("rosybrown4", "#8B6969");
+        synonymToHexName.put("royalblue", "#4169E1");
+        synonymToHexName.put("royalblue1", "#4876FF");
+        synonymToHexName.put("royalblue2", "#436EEE");
+        synonymToHexName.put("royalblue3", "#3A5FCD");
+        synonymToHexName.put("royalblue4", "#27408B");
+        synonymToHexName.put("snewData.addlebrown", "#8B4513");
+        synonymToHexName.put("salmon", "#FA8072");
+        synonymToHexName.put("salmon1", "#FF8C69");
+        synonymToHexName.put("salmon2", "#EE8262");
+        synonymToHexName.put("salmon3", "#CD7054");
+        synonymToHexName.put("salmon4", "#8B4C39");
+        synonymToHexName.put("sandybrown", "#F4A460");
+        synonymToHexName.put("seagreen", "#2E8B57");
+        synonymToHexName.put("seagreen1", "#54FF9F");
+        synonymToHexName.put("seagreen2", "#4EEE94");
+        synonymToHexName.put("seagreen3", "#43CD80");
+        synonymToHexName.put("seagreen4", "#2E8B57");
+        synonymToHexName.put("seashell", "#FFF5EE");
+        synonymToHexName.put("seashell1", "#FFF5EE");
+        synonymToHexName.put("seashell2", "#EEE5DE");
+        synonymToHexName.put("seashell3", "#CDC5BF");
+        synonymToHexName.put("seashell4", "#8B8682");
+        synonymToHexName.put("sienna", "#A0522D");
+        synonymToHexName.put("sienna1", "#FF8247");
+        synonymToHexName.put("sienna2", "#EE7942");
+        synonymToHexName.put("sienna3", "#CD6839");
+        synonymToHexName.put("sienna4", "#8B4726");
+        synonymToHexName.put("skyblue", "#87CEEB");
+        synonymToHexName.put("skyblue1", "#87CEFF");
+        synonymToHexName.put("skyblue2", "#7EC0EE");
+        synonymToHexName.put("skyblue3", "#6CA6CD");
+        synonymToHexName.put("skyblue4", "#4A708B");
+        synonymToHexName.put("slateblue", "#6A5ACD");
+        synonymToHexName.put("slateblue1", "#836FFF");
+        synonymToHexName.put("slateblue2", "#7A67EE");
+        synonymToHexName.put("slateblue3", "#6959CD");
+        synonymToHexName.put("slateblue4", "#473C8B");
+        synonymToHexName.put("slategray", "#708090");
+        synonymToHexName.put("slategray1", "#C6E2FF");
+        synonymToHexName.put("slategray2", "#B9D3EE");
+        synonymToHexName.put("slategray3", "#9FB6CD");
+        synonymToHexName.put("slategray4", "#6C7B8B");
+        synonymToHexName.put("slategrey", "#708090");
+        synonymToHexName.put("snow", "#FFFAFA");
+        synonymToHexName.put("snow1", "#FFFAFA");
+        synonymToHexName.put("snow2", "#EEE9E9");
+        synonymToHexName.put("snow3", "#CDC9C9");
+        synonymToHexName.put("snow4", "#8B8989");
+        synonymToHexName.put("springgreen", "#00FF7F");
+        synonymToHexName.put("springgreen1", "#00FF7F");
+        synonymToHexName.put("springgreen2", "#00EE76");
+        synonymToHexName.put("springgreen3", "#00CD66");
+        synonymToHexName.put("springgreen4", "#008B45");
+        synonymToHexName.put("steelblue", "#4682B4");
+        synonymToHexName.put("steelblue1", "#63B8FF");
+        synonymToHexName.put("steelblue2", "#5CACEE");
+        synonymToHexName.put("steelblue3", "#4F94CD");
+        synonymToHexName.put("steelblue4", "#36648B");
+        synonymToHexName.put("tan", "#D2B48C");
+        synonymToHexName.put("tan1", "#FFA54F");
+        synonymToHexName.put("tan2", "#EE9A49");
+        synonymToHexName.put("tan3", "#CD853F");
+        synonymToHexName.put("tan4", "#8B5A2B");
+        synonymToHexName.put("thistle", "#D8BFD8");
+        synonymToHexName.put("thistle1", "#FFE1FF");
+        synonymToHexName.put("thistle2", "#EED2EE");
+        synonymToHexName.put("thistle3", "#CDB5CD");
+        synonymToHexName.put("thistle4", "#8B7B8B");
+        synonymToHexName.put("tomato", "#FF6347");
+        synonymToHexName.put("tomato1", "#FF6347");
+        synonymToHexName.put("tomato2", "#EE5C42");
+        synonymToHexName.put("tomato3", "#CD4F39");
+        synonymToHexName.put("tomato4", "#8B3626");
+        synonymToHexName.put("turquoise", "#40E0D0");
+        synonymToHexName.put("turquoise1", "#00F5FF");
+        synonymToHexName.put("turquoise2", "#00E5EE");
+        synonymToHexName.put("turquoise3", "#00C5CD");
+        synonymToHexName.put("turquoise4", "#00868B");
+        synonymToHexName.put("violet", "#EE82EE");
+        synonymToHexName.put("violetred", "#D02090");
+        synonymToHexName.put("violetred1", "#FF3E96");
+        synonymToHexName.put("violetred2", "#EE3A8C");
+        synonymToHexName.put("violetred3", "#CD3278");
+        synonymToHexName.put("violetred4", "#8B2252");
+        synonymToHexName.put("wheat", "#F5DEB3");
+        synonymToHexName.put("wheat1", "#FFE7BA");
+        synonymToHexName.put("wheat2", "#EED8AE");
+        synonymToHexName.put("wheat3", "#CDBA96");
+        synonymToHexName.put("wheat4", "#8B7E66");
+        synonymToHexName.put("whitesmoke", "#F5F5F5");
+        synonymToHexName.put("yellow", "#FFFF00");
+        synonymToHexName.put("yellow1", "#FFFF00");
+        synonymToHexName.put("yellow2", "#EEEE00");
+        synonymToHexName.put("yellow3", "#CDCD00");
+        synonymToHexName.put("yellow4", "#8B8B00");
+        synonymToHexName.put("yellowgreen", "#9ACD32");
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
new file mode 100644
index 0000000000..133d02cacb
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -0,0 +1,150 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.flatten;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.fromFlat;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.identity;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortLocation.VPLocationFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+class DoSetViewPort extends RBaseNode {
+    @Child private CastNode castScalarDouble = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
+    @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
+    @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
+    @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
+    @Child private VPLocationFromVPNode vpLocationFromVP = new VPLocationFromVPNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
+        GridState gridState = GridContext.getContext().getGridState();
+        Object[] pushedVPData = pushedViewPort.getDataWithoutCopying();
+        if (hasParent && pushing) {
+            RList parent = gridState.getViewPort();
+            pushedVPData[ViewPort.PVP_PARENT] = parent;
+            REnvironment children = (REnvironment) castChildrenEnv.execute(parent.getDataAt(ViewPort.PVP_CHILDREN));
+            safePutToEnv(pushedViewPort, pushedVPData[ViewPort.VP_NAME], children);
+        }
+
+        GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
+        calcViewportTransform(pushedViewPort, pushedViewPort.getDataAt(ViewPort.PVP_PARENT), !hasParent, currentDevice, GPar.asDrawingContext(gridState.getGpar()));
+
+        // TODO: clipping
+        pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
+        pushedVPData[ViewPort.PVP_DEVWIDTHCM] = scalar(Unit.inchesToCm(currentDevice.getWidth()));
+        pushedVPData[ViewPort.PVP_DEVHEIGHTCM] = scalar(Unit.inchesToCm(currentDevice.getHeight()));
+        return pushedViewPort;
+    }
+
+    private void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext drawingContext) {
+        double[][] parentTransform;
+        ViewPortContext parentContext;
+        ViewPortLocation vpl;
+        Size parentSize;
+        if (parent == null || parent == RNull.instance) {
+            parentTransform = TransformMatrix.identity();
+            parentContext = ViewPortContext.createDefault();
+            parentSize = new Size(device.getWidth(), device.getHeight());
+            vpl = vpLocationFromVP.execute(viewPort);
+        } else {
+            assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list";
+            RList parentList = (RList) parent;
+            Object[] parentData = parentList.getDataWithoutCopying();
+            if (!incremental) {
+                calcViewportTransform(parentList, parentData[ViewPort.PVP_PARENT], false, device, drawingContext);
+            }
+            parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
+            parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
+            parentContext = vpContextFromVP.execute(parentList);
+
+            // TODO: gcontextFromgpar(viewportParentGPar(vp), 0, &parentgc, dd);
+            // TODO: if (....)
+            vpl = vpLocationFromVP.execute(viewPort);
+        }
+
+        UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, drawingContext);
+        double xInches = unitsToInches.convertX(vpl.x, 0, conversionCtx);
+        double yInches = unitsToInches.convertY(vpl.y, 0, conversionCtx);
+        double width = unitsToInches.convertX(vpl.width, 0, conversionCtx);
+        double height = unitsToInches.convertY(vpl.height, 0, conversionCtx);
+
+        if (!Double.isFinite(xInches) || !Double.isFinite(yInches) || !Double.isFinite(width) || !Double.isFinite(height)) {
+            error(Message.GENERIC, "non-finite location and/or size for viewport");
+        }
+
+        double xadj = GridUtils.justification(width, vpl.hjust);
+        double yadj = GridUtils.justification(height, vpl.vjust);
+
+        // Produce transform for this viewport
+        double[][] thisLocation = translation(xInches, yInches);
+        double[][] thisRotation = identity();
+        // TODO: if (viewportAngle(vp) != 0) rotation(viewportAngle(vp), thisRotation);
+
+        double[][] thisJustification = translation(xadj, yadj);
+        // Position relative to origin of rotation THEN rotate.
+        double[][] tempTransform = multiply(thisJustification, thisRotation);
+        // Translate to bottom-left corner.
+        double[][] thisTransform = multiply(tempTransform, thisLocation);
+        // Combine with parent's transform
+        double[][] transform = multiply(thisTransform, parentTransform);
+
+        // Sum up the rotation angles
+        // TODO: rotationAngle = parentAngle + viewportAngle(vp);
+        double rotationAngle = 0;
+        // TODO: Finally, allocate the rows and columns for this viewport's layout if it has one
+
+        Object[] viewPortData = viewPort.getDataWithoutCopying();
+        viewPortData[ViewPort.PVP_WIDTHCM] = scalar(Unit.inchesToCm(width));
+        viewPortData[ViewPort.PVP_HEIGHTCM] = scalar(Unit.inchesToCm(height));
+        viewPortData[ViewPort.PVP_ROTATION] = scalar(rotationAngle);
+        viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
+    }
+
+    private RAbstractDoubleVector castDoubleVector(Object obj) {
+        return (RAbstractDoubleVector) castDoubleVector.execute(obj);
+    }
+
+    private double castScalar(Object obj) {
+        return (double) castScalarDouble.execute(obj);
+    }
+
+    private static RDoubleVector scalar(double val) {
+        return RDataFactory.createDoubleVectorFromScalar(val);
+    }
+
+    private static void safePutToEnv(RList pushedViewPort, Object pushedVPDatum, REnvironment children) {
+        try {
+            children.put(RRuntime.asString(pushedVPDatum), pushedViewPort);
+        } catch (PutException e) {
+            RInternalError.shouldNotReachHere("Cannot update children environment in a view port list");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
new file mode 100644
index 0000000000..d8b2359414
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
@@ -0,0 +1,51 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.builtins.RBehavior;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+/**
+ * On the top of what {@link DoSetViewPort} node does, this node sets the resulting view port as the
+ * current view port in the current {@link GridState} instance. This builtin allows us to write some
+ * of the grid code in R.
+ */
+@RBuiltin(name = ".fastr.grid.doSetViewPort", parameterNames = {"vp", "hasParent", "pushing"}, kind = RBuiltinKind.INTERNAL, behavior = RBehavior.COMPLEX)
+public abstract class DoSetViewPortBuiltin extends RBuiltinNode {
+    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
+
+    static {
+        Casts casts = new Casts(DoSetViewPortBuiltin.class);
+        casts.arg("vp").mustBe(RList.class);
+        casts.arg("hasParent").mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean());
+        casts.arg("pushing").mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean());
+    }
+
+    @Specialization
+    RNull doIt(RList pushedVP, boolean hasParent, boolean pushing) {
+        RList vp = doSetViewPort.doSetViewPort(pushedVP, hasParent, pushing);
+        GridContext.getContext().getGridState().setViewPort(vp);
+        return RNull.instance;
+    }
+
+    public static DoSetViewPortBuiltin create() {
+        return DoSetViewPortBuiltinNodeGen.create();
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
new file mode 100644
index 0000000000..d714b28ef4
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -0,0 +1,154 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import java.util.Arrays;
+
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+
+/**
+ * In the context of grid package, GPar is a list that contains the parameters for the drawing, like
+ * line style, color, etc. This class wraps the list and provides type-safe access to its elements.
+ */
+public final class GPar {
+    private static final int GP_FILL = 0;
+    private static final int GP_COL = 1;
+    private static final int GP_GAMMA = 2;
+    private static final int GP_LTY = 3;
+    private static final int GP_LWD = 4;
+
+    /**
+     * Multiplier added to the final font size.
+     */
+    private static final int GP_CEX = 5;
+
+    /**
+     * Font size in points, however, the real font size will be this multiplied by {@link #GP_CEX}.
+     */
+    private static final int GP_FONTSIZE = 6;
+
+    /**
+     * Size of the line in terms of a multiply of "one line". The final real size of a line is
+     * fontsize*cex*lineheight.
+     */
+    private static final int GP_LINEHEIGHT = 7;
+    private static final int GP_FONT = 8;
+    private static final int GP_FONTFAMILY = 9;
+    private static final int GP_ALPHA = 10;
+    private static final int GP_LINEEND = 11;
+    private static final int GP_LINEJOIN = 12;
+    private static final int GP_LINEMITRE = 13;
+    private static final int GP_LEX = 14;
+    private static final int GP_FONTFACE = 15;
+    private static final int GP_LENGTH = 16;
+    private static final String[] NAMES = new String[]{
+                    "fill",
+                    "col",
+                    "gamma",
+                    "lty",
+                    "lwd",
+                    "cex",
+                    "fontsize",
+                    "lineheight",
+                    "font",
+                    "fontfamily",
+                    "alpha",
+                    "lineend",
+                    "linejoin",
+                    "linemitre",
+                    "lex",
+                    "fontface"  // TODO: could not find this name in grid sources
+    };
+    private static final RStringVector NAMES_VECTOR = (RStringVector) RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
+
+    public static RList createNew() {
+        Object[] data = new Object[GP_LENGTH];
+        Arrays.fill(data, RNull.instance);
+        data[GP_FILL] = "black";
+        data[GP_COL] = "black";
+        data[GP_GAMMA] = newDoubleVec(0);
+        data[GP_LTY] = "solid"; // TODO: LineType enum...
+        data[GP_LWD] = newDoubleVec(1);
+        data[GP_CEX] = newDoubleVec(1);
+        data[GP_FONTSIZE] = newDoubleVec(12);
+        data[GP_LINEHEIGHT] = newDoubleVec(1.0);
+        data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);  // TODO: font constants?
+        data[GP_FONTFAMILY] = ""; // means default font (probably)
+        data[GP_ALPHA] = newDoubleVec(1);
+        data[GP_LINEEND] = "round";
+        data[GP_LINEJOIN] = "round";
+        data[GP_LINEMITRE] = newDoubleVec(10);
+        data[GP_LEX] = newDoubleVec(1);
+        return RDataFactory.createList(data, NAMES_VECTOR);
+    }
+
+    public static DrawingContext asDrawingContext(RList gpar) {
+        return new GParDrawingContext(gpar);
+    }
+
+    private static RAbstractDoubleVector newDoubleVec(double val) {
+        return RDataFactory.createDoubleVectorFromScalar(val);
+    }
+
+    private static final class GParDrawingContext implements DrawingContext {
+        private final Object[] data;
+
+        private GParDrawingContext(RList list) {
+            data = list.getDataWithoutCopying();
+        }
+
+        @Override
+        public String getColor() {
+            String result = RRuntime.asString(data[GP_COL]);
+            if (!result.startsWith("#")) {
+                result = ColorNames.findByName(result);
+            }
+            return result == null ? "#FFFFFF" : result;
+        }
+
+        @Override
+        public double getFontSize() {
+            return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
+        }
+
+        @Override
+        public double getLineHeight() {
+            return asDouble(data[GP_LINEHEIGHT]);
+        }
+
+        private static double asDouble(Object val) {
+            if (val instanceof Double) {
+                return (double) val;
+            } else if (val instanceof RAbstractDoubleVector) {
+                if (((RAbstractDoubleVector) val).getLength() > 0) {
+                    return ((RAbstractDoubleVector) val).getDataAt(0);
+                }
+            } else if (val instanceof Integer) {
+                return (int) val;
+            } else if (val instanceof RAbstractIntVector) {
+                if (((RAbstractIntVector) val).getLength() > 0) {
+                    return ((RAbstractIntVector) val).getDataAt(0);
+                }
+            }
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value in GPar.");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
new file mode 100644
index 0000000000..2980378933
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
+
+/**
+ * Encapsulated the acces to the global grid state.
+ */
+public final class GridContext {
+    private static final GridContext INSTANCE = new GridContext();
+    private final GridState gridState = new GridState();
+    private GridDevice currentDevice;
+
+    public static GridContext getContext() {
+        return INSTANCE;
+    }
+
+    public GridState getGridState() {
+        return gridState;
+    }
+
+    public GridDevice getCurrentDevice() {
+        if (currentDevice == null) {
+            currentDevice = new JFrameDevice();
+        }
+        return currentDevice;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
new file mode 100644
index 0000000000..4d77162e3d
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -0,0 +1,82 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+
+public final class GridState {
+    private RList gpar;
+    private RList viewPort;
+    private REnvironment gridEnv;
+    private boolean deviceInitialized;
+
+    /**
+     * Current grob being drawn (for determining the list of grobs to search when evaluating a
+     * grobwidth/height unit via gPath). May be RNull or RList.
+     */
+    private Object currentGrob;
+
+    GridState() {
+    }
+
+    public void init(REnvironment gridEnv, GridDevice currentDevice) {
+        this.gridEnv = gridEnv;
+        this.currentGrob = RNull.instance;
+        initGPar(currentDevice);
+    }
+
+    private void initGPar(GridDevice currentDevice) {
+        gpar = GPar.createNew();
+        currentDevice.initDrawingContext(GPar.asDrawingContext(gpar));
+    }
+
+    public RList getGpar() {
+        assert gridEnv != null : "GridState not initialized";
+        return gpar;
+    }
+
+    public void setGpar(RList gpar) {
+        assert gridEnv != null : "GridState not initialized";
+        this.gpar = gpar;
+    }
+
+    public boolean isDeviceInitialized() {
+        return deviceInitialized;
+    }
+
+    public void setDeviceInitialized() {
+        this.deviceInitialized = true;
+    }
+
+    public RList getViewPort() {
+        return viewPort;
+    }
+
+    public void setViewPort(RList viewPort) {
+        this.viewPort = viewPort;
+    }
+
+    public REnvironment getGridEnv() {
+        return gridEnv;
+    }
+
+    public Object getCurrentGrob() {
+        return currentGrob;
+    }
+
+    public void setCurrentGrob(Object currentGrob) {
+        this.currentGrob = currentGrob;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
new file mode 100644
index 0000000000..1da60efecf
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import java.util.function.Function;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+
+/**
+ * Gets a specified attribute of current {@link GridState}.
+ */
+public class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
+    private final Function<GridState, Object> getter;
+
+    static {
+        Casts.noCasts(GridStateGetNode.class);
+    }
+
+    public GridStateGetNode(Function<GridState, Object> getter) {
+        this.getter = getter;
+    }
+
+    @Override
+    public Object execute() {
+        Object result = getter.apply(GridContext.getContext().getGridState());
+        assert result != null;
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java
new file mode 100644
index 0000000000..4b07fdcc38
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import java.util.function.BiConsumer;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+/**
+ * Sets a specified attribute of current {@link GridState}.
+ */
+public final class GridStateSetNode extends RExternalBuiltinNode.Arg1 {
+    private final BiConsumer<GridState, Object> setter;
+
+    static {
+        Casts.noCasts(GridStateSetNode.class);
+    }
+
+    public static GridStateSetNode create(BiConsumer<GridState, Object> setter) {
+        return new GridStateSetNode(setter);
+    }
+
+    private GridStateSetNode(BiConsumer<GridState, Object> setter) {
+        this.setter = setter;
+    }
+
+    @Override
+    public Object execute(Object arg) {
+        setter.accept(GridContext.getContext().getGridState(), arg);
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
new file mode 100644
index 0000000000..89bf150002
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -0,0 +1,49 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+final class GridUtils {
+    private GridUtils() {
+        // only static members
+    }
+
+    static double justify(double coord, double size, double justification) {
+        // justification is supposed to be either between 0 and 1
+        return coord - size * justification;
+    }
+
+    /**
+     * Returns the amount of justification required. I.e. transforms the justification from value
+     * between 0 and 1 to the value within size.
+     */
+    static double justification(double size, double justification) {
+        return -size * justification;
+    }
+
+    static double getDataAtMod(RAbstractDoubleVector vec, int idx) {
+        return vec.getDataAt(idx % vec.getLength());
+    }
+
+    @ExplodeLoop
+    static int maxLength(UnitLengthNode unitLength, RAbstractVector... units) {
+        int result = 0;
+        for (RAbstractVector unit : units) {
+            result = Math.max(result, unitLength.execute(unit));
+        }
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
new file mode 100644
index 0000000000..067193cf08
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+
+/**
+ * A node for externals that we ignore, becuase we do not need to implement them or because they
+ * support functionallity we do not implement yet, especially record/replay.
+ */
+public class IgnoredGridExternal extends RExternalBuiltinNode {
+    private final Object result;
+
+    static {
+        Casts.noCasts(IgnoredGridExternal.class);
+    }
+
+    public IgnoredGridExternal(Object result) {
+        this.result = result;
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
new file mode 100644
index 0000000000..ec70939be0
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -0,0 +1,50 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class LGridDirty extends RExternalBuiltinNode {
+    @Child private InitViewPortNode initViewPort = new InitViewPortNode();
+    private final ConditionProfile initViewPortProfile = ConditionProfile.createCountingProfile();
+
+    static {
+        Casts.noCasts(LGridDirty.class);
+    }
+
+    @Override
+    public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
+        GridState gridState = GridContext.getContext().getGridState();
+        if (!gridState.isDeviceInitialized()) {
+            CompilerDirectives.transferToInterpreter();
+            GridContext.getContext().getCurrentDevice().openNewPage();
+            gridState.setDeviceInitialized();
+        }
+        if (initViewPortProfile.profile(gridState.getViewPort() == null)) {
+            // this rarely happens, but we do not have a slow-path implementation (yet)
+            gridState.setViewPort(initViewPort.execute(frame));
+        }
+        return RNull.instance;
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        // shadowed by the VirtualFrame overload
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
new file mode 100644
index 0000000000..58903fc8be
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
@@ -0,0 +1,35 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+
+public abstract class LInitGrid extends RExternalBuiltinNode.Arg1 {
+    static {
+        Casts casts = new Casts(LInitGrid.class);
+        casts.arg(0).mustBe(REnvironment.class);
+    }
+
+    public static LInitGrid create() {
+        return LInitGridNodeGen.create();
+    }
+
+    @Specialization
+    public Object doEnv(REnvironment gridEnv) {
+        GridContext context = GridContext.getContext();
+        context.getGridState().init(gridEnv, context.getCurrentDevice());
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
new file mode 100644
index 0000000000..83a82b0a47
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -0,0 +1,37 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class LInitViewPortStack extends RExternalBuiltinNode {
+    @Child private InitViewPortNode initViewPortNode = new InitViewPortNode();
+    static {
+        Casts.noCasts(LInitViewPortStack.class);
+    }
+
+    @Override
+    public Object call(VirtualFrame frame, @SuppressWarnings("unused") RArgsValuesAndNames args) {
+        initViewPortNode.execute(frame);
+        return RNull.instance;
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        throw RInternalError.shouldNotReachHere("shadowed by the overload with VirtualFrame");
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
new file mode 100644
index 0000000000..87a5269c34
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -0,0 +1,109 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the
+ * 'length' dispatches to S3 method giving us unit length like
+ * {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode}.
+ */
+public abstract class LLines extends RExternalBuiltinNode.Arg4 {
+    @Child private CastNode toIntVector = newCastBuilder().mustBe(integerValue()).boxPrimitive().asIntegerVector().buildCastNode();
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    static {
+        Casts casts = new Casts(LLines.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(RList.class);
+    }
+
+    public static LLines create() {
+        return LLinesNodeGen.create();
+    }
+
+    @Specialization
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, Object arrowIgnored) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        // Convert the list of vectors of indexes to type-safe array and calculate the max length of
+        // the vectors.
+        RAbstractIntVector[] unitIndexesList = new RAbstractIntVector[lengths.getLength()];
+        int maxIndexesLen = 0;
+        for (int i = 0; i < lengths.getLength(); i++) {
+            unitIndexesList[i] = (RAbstractIntVector) toIntVector.execute(lengths.getDataAt(i));
+            maxIndexesLen = Math.max(maxIndexesLen, unitIndexesList[i].getLength());
+        }
+
+        double[] xx = new double[maxIndexesLen];
+        double[] yy = new double[maxIndexesLen];
+        for (RAbstractIntVector unitIndexes : unitIndexesList) {
+            boolean oldIsFinite = false;
+            int start = 0;
+            int unitIndexesLen = unitIndexes.getLength();
+            // following loop finds series of valid points (finite x and y values) and draws each
+            // such series as a polyline
+            for (int i = 0; i < unitIndexesLen; i++) {
+                int unitIndex = unitIndexes.getDataAt(i) - 1;   // coverting R's 1-based index
+                Point origLoc = Point.fromUnits(unitToInches, x, y, unitIndex, conversionCtx);
+                Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
+                xx[i] = loc.x;
+                yy[i] = loc.y;
+                boolean currIsFinite = loc.isFinite();
+                boolean lastIter = i == (unitIndexesLen - 1);
+                if (currIsFinite && !oldIsFinite) {
+                    start = i; // start a new series
+                } else if (oldIsFinite && (!currIsFinite || lastIter)) {
+                    // draw the previous points series because
+                    // (1) current is invalid point. Note: in (one of) the next iteration(s), the
+                    // oldIsFinite will be false and we will update the start and start a new series
+                    // (2) we are in the last iteration
+                    if (lastIter || i - start > 1) {
+                        // we draw only if the previous series of points was at least of length 3 or
+                        // it's last iteration. This seems slightly weird, but that's how GnuR seems
+                        // to work
+                        dev.drawPolyLines(drawingCtx, xx, yy, start, (i - start) + 1);
+                    }
+                }
+                oldIsFinite = currIsFinite;
+            }
+        }
+
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
new file mode 100644
index 0000000000..727e10ed91
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -0,0 +1,27 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class LNewPage extends RExternalBuiltinNode.Arg0 {
+    static {
+        Casts.noCasts(LNewPage.class);
+    }
+
+    @Override
+    public Object execute() {
+        GridContext.getContext().getCurrentDevice().openNewPage();
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
new file mode 100644
index 0000000000..e775dde053
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -0,0 +1,74 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LRect extends RExternalBuiltinNode.Arg6 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    static {
+        Casts casts = new Casts(LRect.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(abstractVectorValue());
+        casts.arg(3).mustBe(abstractVectorValue());
+        casts.arg(4).mustBe(numericValue()).asDoubleVector();
+        casts.arg(5).mustBe(numericValue()).asDoubleVector();
+    }
+
+    public static LRect create() {
+        return LRectNodeGen.create();
+    }
+
+    @Specialization
+    public Object execute(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector wVec, RAbstractVector hVec, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
+        for (int i = 0; i < length; i++) {
+            double w = unitToInches.convertX(wVec, i, conversionCtx);
+            double h = unitToInches.convertY(hVec, i, conversionCtx);
+            // Note: once this is factored to drawing/recording: this transformation is necessary
+            // only for drawing
+            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
+            Point loc = transLoc.justify(w, h, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
+            dev.drawRect(drawingCtx, loc.x, loc.y, w, h);
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
new file mode 100644
index 0000000000..3aca3f3afc
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -0,0 +1,77 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Gets (vectors of) 4 coordinates (two points) and draws a line between them, unlike {@link LLines}
+ * which gets a vector of points and connects them all.
+ */
+public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    static {
+        Casts casts = new Casts(LSegments.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(abstractVectorValue());
+        casts.arg(3).mustBe(abstractVectorValue());
+    }
+
+    public static LSegments create() {
+        return LSegmentsNodeGen.create();
+    }
+
+    @Specialization
+    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, Object arrowIgnored) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
+        double[] xx = new double[2];
+        double[] yy = new double[2];
+        for (int i = 0; i < length; i++) {
+            Point loc1 = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x0, y0, i, conversionCtx), vpTransform.transform);
+            Point loc2 = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x1, y1, i, conversionCtx), vpTransform.transform);
+            if (!loc1.isFinite() || !loc2.isFinite()) {
+                continue;
+            }
+            xx[0] = loc1.x;
+            xx[1] = loc2.x;
+            yy[0] = loc1.y;
+            yy[1] = loc2.y;
+            dev.drawPolyLines(drawingCtx, xx, yy, 0, 2);
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java
new file mode 100644
index 0000000000..cc3b9082a4
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java
@@ -0,0 +1,125 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the
+ * 'length' dispatches to S3 method giving us unit length like {@link Unit.UnitLengthNode}.
+ */
+public abstract class LText extends RExternalBuiltinNode.Arg7 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    static {
+        Casts casts = new Casts(LText.class);
+        // TODO: expressions and maybe other types should have special handling, not only simple
+        // String coercion
+        casts.arg(0).asStringVector();
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(abstractVectorValue());
+        casts.arg(3).mustBe(numericValue()).asDoubleVector();
+        casts.arg(4).mustBe(numericValue()).asDoubleVector();
+        casts.arg(5).mustBe(numericValue()).asDoubleVector();
+    }
+
+    public static LText create() {
+        return LTextNodeGen.create();
+    }
+
+    @Specialization
+    Object drawText(RAbstractStringVector text, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, RAbstractDoubleVector rotation,
+                    Object checkOverlapIgnored) {
+        if (text.getLength() == 0) {
+            return RNull.instance;
+        }
+
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        int length = GridUtils.maxLength(unitLength, x, y);
+        for (int i = 0; i < length; i++) {
+            Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x, y, i, conversionCtx), vpTransform.transform);
+            text(loc.x, loc.y, text.getDataAt(i % text.getLength()), getDataAtMod(hjust, i), getDataAtMod(vjust, i), getDataAtMod(rotation, i), drawingCtx, dev);
+        }
+        return RNull.instance;
+    }
+
+    // transcribed from engine.c
+
+    private void text(double x, double y, String text, double xadjIn, double yadj, double rotation, DrawingContext drawingCtx, GridDevice device) {
+        if (!Double.isFinite(yadj)) {
+            throw new RuntimeException("Not implemented: 'exact' vertical centering, see engine.c:1700");
+        }
+        double xadj = Double.isFinite(xadjIn) ? xadjIn : 0.5;
+
+        double radRotation = Math.toRadians(rotation);
+        double cosRot = Math.cos(radRotation);
+        double sinRot = Math.sin(radRotation);
+        String[] lines = text.split("\n");
+        for (int lineIdx = 0; lineIdx < lines.length; lineIdx++) {
+            double xoff;
+            double yoff;
+            if (lines.length == 1) {
+                // simplification for single line
+                xoff = x;
+                yoff = y;
+            } else {
+                yoff = (1 - yadj) * (lines.length - 1) - lineIdx;
+                // TODO: in the original the following formula uses "dd->dev->cra[1]"
+                yoff *= (drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+                xoff = -yoff * sinRot;
+                yoff = yoff * cosRot;
+                xoff = x + xoff;
+                yoff = y + yoff;
+            }
+
+            double xleft = xoff;
+            double ybottom = yoff;
+            // now determine bottom-left for THIS line
+            if (xadj != 0.0 || yadj != 0.0) {
+                // otherwise simply the initial values for xleft and ybottom are OK
+                double width = device.getStringWidth(drawingCtx, lines[lineIdx]);
+                double height = device.getStringHeight(drawingCtx, lines[lineIdx]);
+                xleft = xoff - (xadj) * width * cosRot + yadj * height * sinRot;
+                ybottom = yoff - (xadj) * width * sinRot - yadj * height * cosRot;
+            }
+
+            device.drawString(drawingCtx, xleft, ybottom, rotation, lines[lineIdx]);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java
new file mode 100644
index 0000000000..6e51c4b4d8
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java
@@ -0,0 +1,50 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public abstract class LUpViewPort extends RExternalBuiltinNode.Arg1 {
+    @Child private CastNode castParentToViewPort = newCastBuilder().mustBe(RList.class, Message.GENERIC, "cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)").buildCastNode();
+
+    static {
+        Casts casts = new Casts(LUpViewPort.class);
+        casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst(1).mustBe(gte(1));
+    }
+
+    public static LUpViewPort create() {
+        return LUpViewPortNodeGen.create();
+    }
+
+    @Specialization
+    Object upViewPort(int n) {
+        GridState gridState = GridContext.getContext().getGridState();
+        RList newViewPort = gridState.getViewPort();
+        for (int i = 0; i < n; i++) {
+            newViewPort = (RList) castParentToViewPort.execute(newViewPort.getDataAt(ViewPort.PVP_PARENT));
+        }
+        gridState.setViewPort(newViewPort);
+
+        // TODO: device changed? => calcViewportTransform for newViewPort
+        // TODO: update the clipping region
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
new file mode 100644
index 0000000000..7bd1158d1d
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public final class Point {
+    final double x;
+    final double y;
+
+    public Point(double x, double y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public static Point fromUnits(UnitToInchesNode unitToInches, RAbstractVector x, RAbstractVector y, int index, UnitConversionContext ctx) {
+        double newX = unitToInches.convertX(x, index, ctx);
+        double newY = unitToInches.convertY(y, index, ctx);
+        return new Point(newX, newY);
+    }
+
+    public Point justify(double width, double height, double hjust, double vjust) {
+        return new Point(GridUtils.justify(x, width, hjust), GridUtils.justify(y, height, vjust));
+    }
+
+    public boolean isFinite() {
+        return Double.isFinite(x) && Double.isFinite(y);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
new file mode 100644
index 0000000000..803a07eb12
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+public final class Size {
+    private final double width;
+    private final double height;
+
+    public Size(double width, double height) {
+        this.width = width;
+        this.height = height;
+    }
+
+    public double getWidth() {
+        return width;
+    }
+
+    public double getHeight() {
+        return height;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
new file mode 100644
index 0000000000..7b66ab2bae
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
@@ -0,0 +1,101 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+/**
+ * Operations on transformation (3x3) matrices.
+ */
+final class TransformMatrix {
+    private TransformMatrix() {
+        // only static members
+    }
+
+    static double[][] translation(double tx, double ty) {
+        double[][] m = identity();
+        m[2][0] = tx;
+        m[2][1] = ty;
+        return m;
+    }
+
+    static double[][] multiply(double[][] m1, double[][] m2) {
+        double[][] m = new double[3][3];
+        m[0][0] = m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] + m1[0][2] * m2[2][0];
+        m[0][1] = m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] + m1[0][2] * m2[2][1];
+        m[0][2] = m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] + m1[0][2] * m2[2][2];
+        m[1][0] = m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] + m1[1][2] * m2[2][0];
+        m[1][1] = m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] + m1[1][2] * m2[2][1];
+        m[1][2] = m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] + m1[1][2] * m2[2][2];
+        m[2][0] = m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] + m1[2][2] * m2[2][0];
+        m[2][1] = m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] + m1[2][2] * m2[2][1];
+        m[2][2] = m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] + m1[2][2] * m2[2][2];
+        return m;
+    }
+
+    static double[][] identity() {
+        double[][] result = new double[3][3];
+        result[0][0] = 1;
+        result[1][1] = 1;
+        result[2][2] = 1;
+        return result;
+    }
+
+    private static double[] location(double x, double y) {
+        return new double[]{x, y, 1};
+    }
+
+    private static double[] transLocation(double[] location, double[][] m) {
+        double[] res = new double[3];
+        res[0] = location[0] * m[0][0] + location[1] * m[1][0] + location[2] * m[2][0];
+        res[1] = location[0] * m[0][1] + location[1] * m[1][1] + location[2] * m[2][1];
+        res[2] = location[0] * m[0][2] + location[1] * m[1][2] + location[2] * m[2][2];
+        return res;
+    }
+
+    static Point transLocation(Point loc, double[][] m) {
+        double[] newLoc = transLocation(location(loc.x, loc.y), m);
+        return new Point(locationX(newLoc), locationY(newLoc));
+    }
+
+    private static double locationX(double[] loc) {
+        return loc[0];
+    }
+
+    private static double locationY(double[] loc) {
+        return loc[1];
+    }
+
+    /**
+     * Transforms the internal double matrix to R matrix flat array.
+     */
+    static double[] flatten(double[][] m) {
+        double[] res = new double[9];
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) {
+                res[i + j * 3] = m[i][j];
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Reverse operation to {@link #flatten(double[][])}.
+     */
+    static double[][] fromFlat(double[] flat) {
+        double[][] res = new double[3][3];
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) {
+                res[i][j] = flat[i + j * 3];
+            }
+        }
+        return res;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
new file mode 100644
index 0000000000..c12899186e
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -0,0 +1,217 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitElementAtNodeGen;
+import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitLengthNodeGen;
+import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+
+/**
+ * Note: internally in FastR Grid everything is in inches. However, some lists that are exposed to
+ * the R code should contain values in centimeters, we convert such values immediatelly once they
+ * enter our system.
+ */
+public class Unit {
+    private static final String VALID_UNIT_ATTR = "valid.unit";
+
+    private static final int NPC = 0;
+    public static final int CM = 1;
+    public static final int INCHES = 2;
+    private static final int LINES = 3;
+    private static final int NATIVE = 4;
+    public static final int NULL = 5; /* only used in layout specifications (?) */
+    public static final int SNPC = 6;
+    public static final int MM = 7;
+    /*
+     * Some units based on TeX's definition thereof
+     */
+    public static final int POINTS = 8; /* 72.27 pt = 1 in */
+    public static final int PICAS = 9; /* 1 pc = 12 pt */
+    public static final int BIGPOINTS = 10; /* 72 bp = 1 in */
+    public static final int DIDA = 11; /* 1157 dd = 1238 pt */
+    public static final int CICERO = 12; /* 1 cc = 12 dd */
+    public static final int SCALEDPOINTS = 13; /* 65536 sp = 1pt */
+    /*
+     * Some units which require an object to query for a value.
+     */
+    public static final int STRINGWIDTH = 14;
+    public static final int STRINGHEIGHT = 15;
+    public static final int STRINGASCENT = 16;
+    public static final int STRINGDESCENT = 17;
+    /*
+     * public static final int LINES now means multiples of the line height. This is multiples of
+     * the font size.
+     */
+    public static final int CHAR = 18;
+    public static final int GROBX = 19;
+    public static final int GROBY = 20;
+    public static final int GROBWIDTH = 21;
+    public static final int GROBHEIGHT = 22;
+    public static final int GROBASCENT = 23;
+    public static final int GROBDESCENT = 24;
+    /*
+     * No longer used
+     */
+    private static final int MYLINES = 103;
+    public static final int MYCHAR = 104;
+    public static final int MYSTRINGWIDTH = 105;
+    public static final int MYSTRINGHEIGHT = 106;
+
+    private static final double CM_IN_INCH = 2.54;
+
+    public static double inchesToCm(double inches) {
+        return inches * CM_IN_INCH;
+    }
+
+    public static double cmToInches(double cm) {
+        return cm / CM_IN_INCH;
+    }
+
+    public static UnitLengthNode createLengthNode() {
+        return UnitLengthNode.create();
+    }
+
+    public static UnitToInchesNode createToInchesNode() {
+        return UnitToInchesNode.create();
+    }
+
+    public abstract static class UnitNodeBase extends Node {
+        @Child private InheritsCheckNode inheritsCheckNode = new InheritsCheckNode("unit.arithmetic");
+
+        boolean isArithmetic(Object obj) {
+            return obj instanceof RList && inheritsCheckNode.execute(obj);
+        }
+    }
+
+    /**
+     * A unit object can represent more or fewer values that the number of elements underlying list
+     * or vector. This node gives the length if the unit in a sense of the upper limit on what can
+     * be used as an index for {@link UnitElementAtNode}.
+     */
+    public abstract static class UnitLengthNode extends UnitNodeBase {
+        public static UnitLengthNode create() {
+            return UnitLengthNodeGen.create();
+        }
+
+        public abstract int execute(RAbstractContainer vector);
+
+        @Specialization(guards = "!isArithmetic(value)")
+        int doNormal(RAbstractContainer value) {
+            return value.getLength();
+        }
+
+        @Specialization(guards = "isArithmetic(list)")
+        int doArithmetic(RList list) {
+            throw RInternalError.unimplemented("Length for arithmetic units");
+        }
+    }
+
+    /**
+     * @see UnitLengthNode
+     */
+    public abstract static class UnitElementAtNode extends UnitNodeBase {
+        @Child private CastNode castToDouble = newCastBuilder().asDoubleVector().buildCastNode();
+
+        public static UnitElementAtNode create() {
+            return UnitElementAtNodeGen.create();
+        }
+
+        public abstract double execute(RAbstractContainer vector, int index);
+
+        @Specialization(guards = "!isArithmetic(value)")
+        double doNormal(RAbstractContainer value, int index) {
+            return ((RAbstractDoubleVector) castToDouble.execute(value)).getDataAt(index);
+        }
+
+        @Specialization(guards = "isArithmetic(list)")
+        double doArithmetic(RList list, int index) {
+            throw RInternalError.unimplemented("UnitElementAt for arithmetic units");
+        }
+    }
+
+    /**
+     * Wraps the data necessary for converting a unit to another unit.
+     */
+    public static final class UnitConversionContext {
+        public final Size viewPortSize;
+        public final ViewPortContext viewPortContext;
+        public final DrawingContext drawingContext;
+
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, DrawingContext drawingContext) {
+            this.viewPortSize = viewPortSize;
+            this.viewPortContext = viewPortContext;
+            this.drawingContext = drawingContext;
+        }
+    }
+
+    /**
+     * Normalizes grid unit object to a double value in inches. For convenience the index is
+     * interpreted as cyclic unlike in {@link UnitElementAtNode}.
+     */
+    public abstract static class UnitToInchesNode extends UnitNodeBase {
+        @Child private CastNode castUnitId = newCastBuilder().mustBe(numericValue()).asIntegerVector().findFirst().buildCastNode();
+        @Child private UnitElementAtNode elementAtNode = UnitElementAtNode.create();
+
+        public static UnitToInchesNode create() {
+            return UnitToInchesNodeGen.create();
+        }
+
+        public double convertX(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
+            return execute(vector, index, conversionCtx.viewPortSize.getWidth(), conversionCtx.viewPortContext.xscalemin, conversionCtx.viewPortContext.xscalemax, conversionCtx.drawingContext);
+        }
+
+        public double convertY(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
+            return execute(vector, index, conversionCtx.viewPortSize.getHeight(), conversionCtx.viewPortContext.yscalemin, conversionCtx.viewPortContext.yscalemax, conversionCtx.drawingContext);
+        }
+
+        public abstract double execute(RAbstractContainer vector, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx);
+
+        @Specialization(guards = "!isArithmetic(value)")
+        double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+            int unitId = (Integer) castUnitId.execute(value.getAttr(VALID_UNIT_ATTR));
+            return convert(elementAtNode.execute(value, index % value.getLength()), unitId, vpSize, scalemin, scalemax, drawingCtx);
+        }
+
+        @Specialization(guards = "isArithmetic(list)")
+        double doArithmetic(RList list, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+            throw RInternalError.unimplemented("UnitToInches for arithmetic units");
+        }
+
+        private static double convert(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+            switch (unitId) {
+                case NATIVE:
+                    return ((value - scalemin) / (scalemax - scalemin)) * vpSize;
+                case NPC:
+                    return value * vpSize;
+                case LINES:
+                case MYLINES:
+                    return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+
+                default:
+                    throw RInternalError.unimplemented("unit type " + unitId + " in UnitToInches");
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
new file mode 100644
index 0000000000..820e2ef119
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -0,0 +1,85 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RList;
+
+/**
+ * There is a notion of a view point, which is an ordinary list that user creates to define a view
+ * port. One such list is pushed using {@code pushViewpoint} it is transformed to a 'pushed
+ * viewpoint', which is a copy of the original view point and it has some additional attributes.
+ */
+class ViewPort {
+    /*
+     * Structure of a viewport
+     */
+    public static final int VP_X = 0;
+    public static final int VP_Y = 1;
+    public static final int VP_WIDTH = 2;
+    public static final int VP_HEIGHT = 3;
+    public static final int VP_JUST = 4;
+    public static final int VP_GP = 5;
+    public static final int VP_CLIP = 6;
+    public static final int VP_XSCALE = 7;
+    public static final int VP_YSCALE = 8;
+    public static final int VP_ANGLE = 9;
+    public static final int VP_LAYOUT = 10;
+    public static final int VP_LPOSROW = 11;
+    public static final int VP_LPOSCOL = 12;
+    public static final int VP_VALIDJUST = 13;
+    public static final int VP_VALIDLPOSROW = 14;
+    public static final int VP_VALIDLPOSCOL = 15;
+    public static final int VP_NAME = 16;
+    /*
+     * Additional structure of a pushedvp
+     */
+    public static final int PVP_PARENTGPAR = 17;
+    private static final int PVP_GPAR = 18;
+    public static final int PVP_TRANS = 19;
+    public static final int PVP_WIDTHS = 20;
+    public static final int PVP_HEIGHTS = 21;
+    public static final int PVP_WIDTHCM = 22;
+    public static final int PVP_HEIGHTCM = 23;
+    public static final int PVP_ROTATION = 24;
+    public static final int PVP_CLIPRECT = 25;
+    public static final int PVP_PARENT = 26;
+    public static final int PVP_CHILDREN = 27;
+    public static final int PVP_DEVWIDTHCM = 28;
+    public static final int PVP_DEVHEIGHTCM = 29;
+
+    public static final class InitViewPortNode extends Node {
+        @Child private ReadVariableNode readGridTopLevel = ReadVariableNode.create("grid.top.level.vp");
+        @Child private RExplicitCallNode callNode = RExplicitCallNode.create();
+        @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
+
+        public RList execute(VirtualFrame frame) {
+            RFunction gridTopLevel = (RFunction) readGridTopLevel.execute(frame);
+            RList topVP = (RList) callNode.execute(frame, gridTopLevel, RArgsValuesAndNames.EMPTY);
+
+            GridDevice device = GridContext.getContext().getCurrentDevice();
+            // TODO: properly set the scale according to the current device
+            Object[] data = topVP.getDataWithoutCopying();
+            data[ViewPort.VP_XSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getWidth()}, RDataFactory.COMPLETE_VECTOR);
+            data[ViewPort.VP_YSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getHeight()}, RDataFactory.COMPLETE_VECTOR);
+            data[ViewPort.PVP_GPAR] = GridContext.getContext().getGridState().getGpar();
+            return doSetViewPort.doSetViewPort(topVP, false, true);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
new file mode 100644
index 0000000000..e07043ce1c
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
@@ -0,0 +1,58 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+
+public final class ViewPortContext {
+    public double xscalemin;
+    public double yscalemin;
+    public double xscalemax;
+    public double yscalemax;
+
+    private ViewPortContext() {
+    }
+
+    public static ViewPortContext createDefault() {
+        ViewPortContext result = new ViewPortContext();
+        result.xscalemin = 0;
+        result.yscalemin = 0;
+        result.xscalemax = 1;
+        result.yscalemax = 1;
+        return result;
+    }
+
+    public static final class VPContextFromVPNode extends Node {
+        @Child private CastNode castVector = newCastBuilder().asDoubleVector().mustBe(Predef.size(2)).buildCastNode();
+
+        public ViewPortContext execute(RList viewPort) {
+            ViewPortContext result = new ViewPortContext();
+            RAbstractDoubleVector x = castVec(viewPort.getDataAt(ViewPort.VP_XSCALE));
+            result.xscalemin = x.getDataAt(0);
+            result.xscalemax = x.getDataAt(1);
+            RAbstractDoubleVector y = castVec(viewPort.getDataAt(ViewPort.VP_YSCALE));
+            result.yscalemin = y.getDataAt(0);
+            result.yscalemax = y.getDataAt(1);
+            return result;
+        }
+
+        private RAbstractDoubleVector castVec(Object val) {
+            return (RAbstractDoubleVector) castVector.execute(val);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
new file mode 100644
index 0000000000..894d8d90e1
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
@@ -0,0 +1,55 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+
+/**
+ * The vectors in this class represent a unit objects, therefore we cannot just have a double value
+ * for them. However, the unit object should contain only single value.
+ */
+public class ViewPortLocation {
+    public RAbstractDoubleVector x;
+    public RAbstractDoubleVector y;
+    public RAbstractDoubleVector width;
+    public RAbstractDoubleVector height;
+    public double hjust;
+    public double vjust;
+
+    public static final class VPLocationFromVPNode extends Node {
+        @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
+        @Child private CastNode castJustVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().mustBe(size(2)).buildCastNode();
+
+        public ViewPortLocation execute(RList viewPort) {
+            ViewPortLocation r = new ViewPortLocation();
+            r.x = vec(viewPort.getDataAt(ViewPort.VP_X));
+            r.y = vec(viewPort.getDataAt(ViewPort.VP_Y));
+            r.width = vec(viewPort.getDataAt(ViewPort.VP_WIDTH));
+            r.height = vec(viewPort.getDataAt(ViewPort.VP_HEIGHT));
+            RAbstractDoubleVector just = (RAbstractDoubleVector) castJustVector.execute(viewPort.getDataAt(ViewPort.VP_VALIDJUST));
+            r.hjust = just.getDataAt(0);
+            r.vjust = just.getDataAt(1);
+            return r;
+        }
+
+        private RAbstractDoubleVector vec(Object val) {
+            return (RAbstractDoubleVector) castDoubleVector.execute(val);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
new file mode 100644
index 0000000000..016e90247a
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -0,0 +1,53 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+
+/**
+ * Holds the data of a viewport needed to perform transformations.
+ */
+public final class ViewPortTransform {
+    private final double rotationAngle;
+    public final double[][] transform;
+    public final Size size;
+
+    private ViewPortTransform(double width, double height, double rotationAngle, double[][] transform) {
+        this.size = new Size(width, height);
+        this.rotationAngle = rotationAngle;
+        this.transform = transform;
+    }
+
+    public static final class GetViewPortTransformNode extends Node {
+        @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
+        @Child private CastNode castScalarDouble = newCastBuilder().mustBe(numericValue()).asDoubleVector().findFirst().buildCastNode();
+
+        public ViewPortTransform execute(RList viewPort) {
+            double width = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
+            double height = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
+            double rotationAngle = getScalar(viewPort.getDataAt(ViewPort.VP_ANGLE));
+            RAbstractDoubleVector trans = (RAbstractDoubleVector) castDoubleVector.execute(viewPort.getDataAt(ViewPort.PVP_TRANS));
+            double[][] transform = TransformMatrix.fromFlat(trans.materialize().getDataWithoutCopying());
+            return new ViewPortTransform(width, height, rotationAngle, transform);
+        }
+
+        private double getScalar(Object value) {
+            return (double) castScalarDouble.execute(value);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
new file mode 100644
index 0000000000..facac095e9
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+/**
+ * Defines parameters for drawing, like color, line style etc.
+ */
+public interface DrawingContext {
+    double INCH_TO_POINTS_FACTOR = 72;
+
+    /**
+     * @return Hexadecimal string of the color with leading '#', e.g. '#FFA8B2'. Never returns a
+     *         synonym.
+     */
+    String getColor();
+
+    /**
+     * Gets the font size in points.
+     *
+     * @see #INCH_TO_POINTS_FACTOR
+     */
+    double getFontSize();
+
+    /**
+     * Gets the height of a line in multiplies of the base line height.
+     */
+    double getLineHeight();
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
new file mode 100644
index 0000000000..278e25ff3d
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+
+/**
+ * Abstract device that can draw primitive shapes and text. All sizes and coordinates are specified
+ * in inches.
+ */
+public interface GridDevice {
+    void openNewPage();
+
+    void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width);
+
+    void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length);
+
+    void drawString(DrawingContext ctx, double x, double y, double rotation, String text);
+
+    /**
+     * @return The width of the device in inches.
+     */
+    double getWidth();
+
+    /**
+     * @return The height of the device in inches.
+     */
+    double getHeight();
+
+    /**
+     * May change the default values the of the initial drawing context instance.
+     * 
+     * @param ctx instance of drawing context to be altered.
+     */
+    default void initDrawingContext(DrawingContext ctx) {
+        // nop
+    }
+
+    double getStringWidth(DrawingContext ctx, String text);
+
+    /**
+     * Gets the height of a line of text in inches, the default implementation uses only the
+     * parameters from the drawing context, but we allow the device to override this calculation
+     * with something more precise.
+     */
+    default double getStringHeight(DrawingContext ctx, String text) {
+        return (ctx.getLineHeight() * ctx.getFontSize()) / INCH_TO_POINTS_FACTOR;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
new file mode 100644
index 0000000000..aee82b6132
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Path2D;
+import java.awt.geom.Rectangle2D;
+import java.util.function.Supplier;
+
+import com.oracle.truffle.r.library.graphics.FastRFrame;
+
+public class JFrameDevice implements GridDevice {
+    // Grid's coordinate system has origin in left bottom corner and y axis grows from bottom to
+    // top. Moreover, the grid system uses inches as units. We use transformation to adjust the java
+    // coordinate system to the grid one. However, in the case of text rendering, we cannot simply
+    // turn upside down the y-axis, because the text would be upside down too, so for text rendering
+    // only, we reset the transformation completely and transform the coordinates ourselves
+
+    private FastRFrame currentFrame;
+    private Graphics2D graphics;
+
+    @Override
+    public void openNewPage() {
+        if (currentFrame == null) {
+            currentFrame = new FastRFrame();
+            currentFrame.setVisible(true);
+            graphics = (Graphics2D) currentFrame.getGraphics();
+            graphics.translate(0, currentFrame.getHeight());
+            graphics.scale(72, -72); // doc: 72 points ~ 1 inch
+            graphics.setStroke(new BasicStroke(1f / 72f));
+        } else {
+            noTranform(() -> {
+                graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
+                return null;
+            });
+        }
+    }
+
+    @Override
+    public void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width) {
+        setContext(ctx);
+        graphics.draw(new Rectangle2D.Double(leftX, topY, heigh, width));
+    }
+
+    @Override
+    public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        assert startIndex >= 0 && startIndex < x.length && startIndex < y.length : "startIndex out of bounds";
+        assert length > 0 && (startIndex + length) <= Math.min(x.length, y.length) : "length out of bounds";
+        setContext(ctx);
+        Path2D.Double path = new Path2D.Double();
+        path.moveTo(x[startIndex], y[startIndex]);
+        for (int i = startIndex + 1; i < length; i++) {
+            path.lineTo(x[i], y[i]);
+        }
+        graphics.draw(path);
+    }
+
+    @Override
+    public void drawString(DrawingContext ctx, double x, double y, double rotation, String text) {
+        setContext(ctx);
+        noTranform(() -> {
+            graphics.rotate(rotation);
+            graphics.drawString(text, (float) x * 72f, (float) (currentFrame.getContentPane().getHeight() - y * 72f));
+            return null;
+        });
+    }
+
+    @Override
+    public double getWidth() {
+        return currentFrame.getContentPane().getWidth() / 72.0;
+    }
+
+    @Override
+    public double getHeight() {
+        return currentFrame.getContentPane().getHeight() / 72.0;
+    }
+
+    @Override
+    public double getStringWidth(DrawingContext ctx, String text) {
+        setContext(ctx);
+        return noTranform(() -> {
+            int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
+            return swingUnits / 72.;
+        });
+    }
+
+    @Override
+    public double getStringHeight(DrawingContext ctx, String text) {
+        setContext(ctx);
+        return noTranform(() -> {
+            // int swingUnits = graphics.getFontMetrics(graphics.getFont()).getHeight();
+            int swingUnits = graphics.getFont().getSize();
+            return swingUnits / 72.;
+        });
+    }
+
+    private void setContext(DrawingContext ctx) {
+        graphics.setFont(graphics.getFont().deriveFont((float) ctx.getFontSize()));
+        graphics.setColor(Color.decode(ctx.getColor()));
+    }
+
+    private <T> T noTranform(Supplier<T> action) {
+        AffineTransform transform = graphics.getTransform();
+        graphics.setTransform(new AffineTransform());
+        T result = action.get();
+        graphics.setTransform(transform);
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
new file mode 100644
index 0000000000..0dae5cec37
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -0,0 +1,46 @@
+
+# Returns list with elements [[1]] - depth, zero if not found, [[2]] - the viewport, NULL if not found
+find.viewport <- function(name, strict, pvp, depth) {
+    if (length(ls(env=pvp$children)) == 0) {
+        return(list(FALSE, NULL))
+    } else if (exists(name, env=pvp$children, inherits=FALSE)) {
+        return(list(depth, get(name, env=pvp$children, inherits=FALSE)))
+    } else if (strict) {
+        return(list(FALSE, NULL))
+    } else {
+        return(find.in.children(name, pvp$children, depth + 1L))
+    }
+}
+
+# Note: in GnuR this takes "strict" from find.viewport and forwards it to recursive calls to find.viewport,
+# however, strict must be constant FALSE if find.in.children is called, so we leave it out.
+find.in.children <- function(name, children, depth) {
+  cpvps <- ls(env=children)
+  ncpvp <- length(cpvps)
+  count <- 0L
+  found <- FALSE
+  while (count < ncpvp && !found) {
+    result <- find.viewport(name, FALSE, get(cpvps[count + 1L], env=children), depth)
+    if (result[[1L]]) {
+        return(result);
+    }
+    count <- count + 1L
+  }
+  list(FALSE, NULL) # not found
+}
+
+L_downviewport <- function(name, strict) {
+    currVp <- .Call(grid:::L_currentViewport)
+    result <- find.viewport(name, strict, currVp, 1L);
+    if (result[[1]]) {
+        .Internal(.fastr.grid.doSetViewPort(result[[2L]], FALSE, FALSE));
+        return(result[[1L]])
+    } else {
+        stop(paste0("Viewport '", name, "' was not found"));
+    }
+}
+
+L_setviewport <- function(vp, hasParent) {
+    pushedVP <- grid:::pushedvp(vp);
+    .Internal(.fastr.grid.doSetViewPort(pushedVP, hasParent, TRUE));
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java
index 9f1463e854..7446c48d59 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@ public class FastRFrame extends JFrame {
 
     private static final long serialVersionUID = 1L;
 
-    private final Dimension framePreferredSize = new Dimension(500, 500);
+    private final Dimension framePreferredSize = new Dimension(720, 720);
     private final FastRComponent fastRComponent = new FastRComponent();
 
     public FastRFrame() throws HeadlessException {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 16e97d3504..ac9d5aa0bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import java.util.function.Supplier;
 
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.r.library.fastrGrid.DoSetViewPortBuiltin;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.binary.BinaryArithmeticNodeGen;
@@ -717,6 +718,9 @@ public class BasePackage extends RBuiltinPackage {
         add(UpdateSubset.class, UpdateSubsetNodeGen::create, UpdateSubset::special);
         add(UpdateField.class, UpdateFieldNodeGen::create, UpdateField::createSpecial);
         add(WhileBuiltin.class, WhileBuiltinNodeGen::create);
+
+        // grid intrinsics
+        add(DoSetViewPortBuiltin.class, DoSetViewPortBuiltin::create);
     }
 
     private void addBinaryArithmetic(Class<?> builtinClass, BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index ab28e791fd..29c9cc4d62 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -22,6 +22,18 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.library.fastrGrid.GridStateGetNode;
+import com.oracle.truffle.r.library.fastrGrid.GridStateSetNode;
+import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal;
+import com.oracle.truffle.r.library.fastrGrid.LGridDirty;
+import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
+import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
+import com.oracle.truffle.r.library.fastrGrid.LLines;
+import com.oracle.truffle.r.library.fastrGrid.LNewPage;
+import com.oracle.truffle.r.library.fastrGrid.LRect;
+import com.oracle.truffle.r.library.fastrGrid.LSegments;
+import com.oracle.truffle.r.library.fastrGrid.LText;
+import com.oracle.truffle.r.library.fastrGrid.LUpViewPort;
 import com.oracle.truffle.r.library.grDevices.DevicesCCalls;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_Par;
@@ -79,6 +91,8 @@ import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalCode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -240,6 +254,9 @@ public class CallAndExternalFunctions {
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
             String name = lookupName(symbol);
+            if (FastROptions.UseInternalGridGraphics.getBooleanValue() && name != null && name.startsWith("L_")) {
+                return lookupFastRGridBuiltin(name);
+            }
             switch (name) {
                 // methods
                 case "R_initMethodDispatch":
@@ -652,11 +669,77 @@ public class CallAndExternalFunctions {
             }
         }
 
+        private RExternalBuiltinNode lookupFastRGridBuiltin(String name) {
+            switch (name) {
+                case "L_gridDirty":
+                    return new LGridDirty();
+                case "L_initGrid":
+                    return LInitGrid.create();
+                case "L_newpage":
+                    return new LNewPage();
+
+                // Viewport management
+                case "L_upviewport":
+                    return LUpViewPort.create();
+                case "L_initViewportStack":
+                    return new LInitViewPortStack();
+                case "L_setviewport":
+                case "L_downviewport":
+                    return getExternalFastRGridBuiltinNode(name);
+
+                // Drawing primitives
+                case "L_rect":
+                    return LRect.create();
+                case "L_lines":
+                    return LLines.create();
+                case "L_text":
+                    return LText.create();
+                case "L_segments":
+                    return LSegments.create();
+
+                // Simple grid state access
+                case "L_getGPar":
+                    return new GridStateGetNode(state -> state.getGpar());
+                case "L_setGPar":
+                    return GridStateSetNode.create((state, val) -> state.setGpar((RList) val));
+                case "L_getCurrentGrob":
+                    return new GridStateGetNode(state -> state.getCurrentGrob());
+                case "L_setCurrentGrob":
+                    return GridStateSetNode.create((state, val) -> state.setCurrentGrob(val));
+                case "L_currentViewport":
+                    return new GridStateGetNode(state -> state.getViewPort());
+
+                // Display list stuff: not implemented atm
+                case "L_getDisplayList":
+                    return new IgnoredGridExternal(RDataFactory.createList());
+                case "L_getDLindex":
+                    return new IgnoredGridExternal(0);
+                case "L_getDLon":
+                case "L_getEngineDLon":
+                    return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE);
+                case "L_initDisplayList":
+                case "L_newpagerecording":
+                case "L_setDisplayList":
+                case "L_setDLelt":
+                case "L_setDLindex":
+                case "L_setDLon":
+                    return new IgnoredGridExternal(RNull.instance);
+
+                // These methods do not use graphics system or any global state. For now,
+                // we can re-use the native implementation, which in the future should be rewritten
+                // to managed code.
+                case "L_validUnits":
+                    return null;
+                default:
+                    throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
+            }
+        }
+
         /**
          * {@code .NAME = NativeSymbolInfo} implemented as a builtin.
          */
         @SuppressWarnings("unused")
-        @Specialization(limit = "1", guards = {"cached == symbol", "builtin != null"})
+        @Specialization(limit = "99", guards = {"cached == symbol", "builtin != null"})
         protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
                         @Cached("symbol") RList cached,
                         @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin) {
@@ -668,9 +751,10 @@ public class CallAndExternalFunctions {
          * package)
          */
         @SuppressWarnings("unused")
-        @Specialization(limit = "2", guards = {"cached == symbol"})
+        @Specialization(limit = "2", guards = {"cached == symbol", "builtin == null"})
         protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
                         @Cached("symbol") RList cached,
+                        @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin,
                         @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) {
             return callRFFINode.execute(nativeCallInfo, args.getArguments());
         }
@@ -680,8 +764,12 @@ public class CallAndExternalFunctions {
          * such cases there is this generic version.
          */
         @SuppressWarnings("unused")
-        @Specialization(replaces = "callNamedFunction")
+        @Specialization(replaces = {"callNamedFunction", "doExternal"})
         protected Object callNamedFunctionGeneric(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName) {
+            RExternalBuiltinNode builtin = lookupBuiltin(symbol);
+            if (builtin != null) {
+                throw RInternalError.shouldNotReachHere("Cache for .Calls with FastR reimplementation (lookupBuiltin(...) != null) exceeded the limit");
+            }
             NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
             return callRFFINode.execute(nativeCallInfo, args.getArguments());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index 31f230f522..84c0278f50 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodes;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -177,6 +178,10 @@ abstract class LookupAdapter extends RBuiltinNode {
         return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(RandFunctionsNodes.class, "model.R"), name);
     }
 
+    protected static RExternalBuiltinNode getExternalFastRGridBuiltinNode(String name) {
+        return new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name);
+    }
+
     protected static final int CallNST = DLL.NativeSymbolType.Call.ordinal();
     protected static final int ExternalNST = DLL.NativeSymbolType.External.ordinal();
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 925e1f3904..157526ea1d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -52,6 +52,7 @@ public enum FastROptions {
     InvisibleArgs("Argument writes do not trigger state transitions", true),
     RefCountIncrementOnly("Disable reference count decrements for experimental state transition implementation", false),
     UseInternalGraphics("Whether the internal (Java) graphics subsystem should be used", false),
+    UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", false),
     UseSpecials("Whether the fast-path special call nodes should be created for simple enough arguments.", true),
     ForceSources("Generate source sections for unserialized code", false),
 
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index f6786e5110..b9a4e7de5c 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -766,3 +766,24 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java,gnu_r.copyright
-- 
GitLab


From 853ac156ea123c6aa4c336bdf0baedeba9414632 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Mon, 6 Mar 2017 16:48:31 +0100
Subject: [PATCH 152/402] FastR grid: circle primitive

---
 .../truffle/r/library/fastrGrid/LCircle.java  | 64 +++++++++++++++++++
 .../library/fastrGrid/device/GridDevice.java  |  8 ++-
 .../fastrGrid/device/JFrameDevice.java        | 14 +++-
 .../foreign/CallAndExternalFunctions.java     |  3 +
 mx.fastr/copyrights/overrides                 |  1 +
 5 files changed, 87 insertions(+), 3 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
new file mode 100644
index 0000000000..e4aee83200
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -0,0 +1,64 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    static {
+        Casts casts = new Casts(LCircle.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(abstractVectorValue());
+    }
+
+    public static LCircle create() {
+        return LCircleNodeGen.create();
+    }
+
+    @Specialization
+    Object doCircle(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector radiusVec) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
+        for (int i = 0; i < length; i++) {
+            double radius = unitToInches.convertX(radiusVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
+            dev.drawCircle(drawingCtx, loc.x, loc.y, radius);
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 278e25ff3d..3d878b99c0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -33,9 +33,15 @@ public interface GridDevice {
 
     void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width);
 
+    /**
+     * Connects given points with a line, there has to be at least two points in order to actually
+     * draw somethig.
+     */
     void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length);
 
-    void drawString(DrawingContext ctx, double x, double y, double rotation, String text);
+    void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius);
+
+    void drawString(DrawingContext ctx, double leftX, double bottomY, double rotation, String text);
 
     /**
      * @return The width of the device in inches.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index aee82b6132..cf13bfd232 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -25,7 +25,9 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics2D;
+import java.awt.RenderingHints;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Ellipse2D;
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
 import java.util.function.Supplier;
@@ -51,6 +53,8 @@ public class JFrameDevice implements GridDevice {
             graphics.translate(0, currentFrame.getHeight());
             graphics.scale(72, -72); // doc: 72 points ~ 1 inch
             graphics.setStroke(new BasicStroke(1f / 72f));
+            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+            graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
         } else {
             noTranform(() -> {
                 graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
@@ -79,11 +83,17 @@ public class JFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawString(DrawingContext ctx, double x, double y, double rotation, String text) {
+    public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
+        setContext(ctx);
+        graphics.draw(new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2d, radius * 2d));
+    }
+
+    @Override
+    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotation, String text) {
         setContext(ctx);
         noTranform(() -> {
             graphics.rotate(rotation);
-            graphics.drawString(text, (float) x * 72f, (float) (currentFrame.getContentPane().getHeight() - y * 72f));
+            graphics.drawString(text, (float) leftX * 72f, (float) (currentFrame.getContentPane().getHeight() - bottomY * 72f));
             return null;
         });
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 29c9cc4d62..f5e5f53006 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -25,6 +25,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.library.fastrGrid.GridStateGetNode;
 import com.oracle.truffle.r.library.fastrGrid.GridStateSetNode;
 import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal;
+import com.oracle.truffle.r.library.fastrGrid.LCircle;
 import com.oracle.truffle.r.library.fastrGrid.LGridDirty;
 import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
 import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
@@ -696,6 +697,8 @@ public class CallAndExternalFunctions {
                     return LText.create();
                 case "L_segments":
                     return LSegments.create();
+                case "L_circle":
+                    return LCircle.create();
 
                 // Simple grid state access
                 case "L_getGPar":
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index b9a4e7de5c..86618d197a 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -787,3 +787,4 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.j
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
-- 
GitLab


From a70121df49eeae7b1776f367ca252057f0628679 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 7 Mar 2017 13:34:56 +0100
Subject: [PATCH 153/402] FastR grid: implement L_textBounds

---
 .../r/library/fastrGrid/EdgeDetection.java    | 223 ++++++++++++++++
 .../r/library/fastrGrid/GridState.java        |   6 +
 .../r/library/fastrGrid/GridTextNode.java     | 247 ++++++++++++++++++
 .../r/library/fastrGrid/GridUtils.java        |  21 ++
 .../truffle/r/library/fastrGrid/LText.java    | 130 +++------
 .../r/library/fastrGrid/LTextBounds.java      |  56 ++++
 .../r/library/fastrGrid/TransformMatrix.java  |  17 ++
 .../foreign/CallAndExternalFunctions.java     |  12 +-
 mx.fastr/copyrights/overrides                 |   3 +-
 9 files changed, 610 insertions(+), 105 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
new file mode 100644
index 0000000000..4b556280fc
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
@@ -0,0 +1,223 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin;
+import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI;
+import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
+import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2;
+import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+/**
+ * Contains static method related to edge detection for bounds calculations.
+ */
+public final class EdgeDetection {
+    private EdgeDetection() {
+        // only static members
+    }
+
+    /**
+     * Do two lines intersect? Algorithm from Paul Bourke
+     * (http://www.swin.edu.au/astronomy/pbourke/geometry/lineline2d/index.html)
+     */
+    static boolean linesIntersect(double x1, double x2, double x3, double x4,
+                    double y1, double y2, double y3, double y4) {
+        double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
+        double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3));
+        // If the lines are parallel ...
+        if (denom == 0) {
+            // If the lines are coincident ...
+            if (ua == 0) {
+                // If the lines are vertical ...
+                if (x1 == x2) {
+                    // Compare y-values
+                    if (!((y1 < y3 && fmax2(y1, y2) < fmin2(y3, y4)) ||
+                                    (y3 < y1 && fmax2(y3, y4) < fmin2(y1, y2))))
+                        return true;
+                } else {
+                    // Compare x-values
+                    if (!((x1 < x3 && fmax2(x1, x2) < fmin2(x3, x4)) ||
+                                    (x3 < x1 && fmax2(x3, x4) < fmin2(x1, x2))))
+                        return true;
+                }
+            }
+        }
+        // ... otherwise, calculate where the lines intersect ...
+        else {
+            double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3));
+            ua = ua / denom;
+            ub = ub / denom;
+            // Check for overlap
+            if ((ua > 0 && ua < 1) && (ub > 0 && ub < 1))
+                return true;
+        }
+        return false;
+    }
+
+    static boolean edgesIntersect(double x1, double x2, double y1, double y2, Rectangle r) {
+        return linesIntersect(x1, x2, r.x[0], r.x[1], y1, y2, r.y[0], r.y[1]) ||
+                        linesIntersect(x1, x2, r.x[1], r.x[2], y1, y2, r.y[1], r.y[2]) ||
+                        linesIntersect(x1, x2, r.x[2], r.x[3], y1, y2, r.y[2], r.y[3]) ||
+                        linesIntersect(x1, x2, r.x[3], r.x[0], y1, y2, r.y[3], r.y[0]);
+    }
+
+    static Point rectEdge(double xmin, double ymin, double xmax, double ymax, double theta) {
+        double xm = (xmin + xmax) / 2;
+        double ym = (ymin + ymax) / 2;
+        double dx = (xmax - xmin) / 2;
+        double dy = (ymax - ymin) / 2;
+        /*
+         * GNUR fixme: Special case 0 width or 0 height
+         */
+        // Special case angles
+        if (theta == 0) {
+            return new Point(xmax, ym);
+        } else if (theta == 270) {
+            return new Point(xm, ymin);
+        } else if (theta == 180) {
+            return new Point(xmin, ym);
+        } else if (theta == 90) {
+            return new Point(xm, ymax);
+        } else {
+            double cutoff = dy / dx;
+            double angle = theta / 180 * M_PI;
+            double tanTheta = Math.tan(angle);
+            double cosTheta = Math.cos(angle);
+            double sinTheta = Math.sin(angle);
+            if (fabs(tanTheta) < cutoff) { /* Intersect with side */
+                if (cosTheta > 0) { /* Right side */
+                    return new Point(xmax, ym + tanTheta * dx);
+                } else { /* Left side */
+                    return new Point(xmin, ym - tanTheta * dx);
+                }
+            } else { /* Intersect with top/bottom */
+                if (sinTheta > 0) { /* Top */
+                    return new Point(ymax, xm + dy / tanTheta);
+                } else { /* Bottom */
+                    return new Point(ymin, xm - dy / tanTheta);
+                }
+            }
+        }
+    }
+
+    static Point polygonEdge(double[] x, double[] y, int n, double theta) {
+        // centre of the polygon
+        double xmin = fmin(Double.MAX_VALUE, x);
+        double xmax = fmax(Double.MIN_VALUE, x);
+        double ymin = fmin(Double.MAX_VALUE, y);
+        double ymax = fmax(Double.MIN_VALUE, y);
+        double xm = (xmin + xmax) / 2;
+        double ym = (ymin + ymax) / 2;
+
+        // Special case zero-width or zero-height
+        if (fabs(xmin - xmax) < 1e-6) {
+            double resultY = theta == 90 ? ymax : theta == 270 ? ymin : ym;
+            return new Point(xmin, ymin);
+        }
+        if (fabs(ymin - ymax) < 1e-6) {
+            double resultY = theta == 0 ? xmax : theta == 180 ? xmin : xm;
+            return new Point(ymin, resultY);
+        }
+
+        /*
+         * Find edge that intersects line from centre at angle theta
+         */
+        boolean found = false;
+        double angle = theta / 180 * M_PI;
+        double vangle1;
+        double vangle2;
+        int v1 = 0;
+        int v2 = 1;
+        for (int i = 0; i < n; i++) {
+            v1 = i;
+            v2 = v1 + 1;
+            if (v2 == n) {
+                v2 = 0;
+            }
+            /*
+             * Result of atan2 is in range -PI, PI so convert to 0, 360 to correspond to angle
+             */
+            vangle1 = Math.atan2(y[v1] - ym, x[v1] - xm);
+            if (vangle1 < 0) {
+                vangle1 = vangle1 + 2 * M_PI;
+            }
+            vangle2 = Math.atan2(y[v2] - ym, x[v2] - xm);
+            if (vangle2 < 0) {
+                vangle2 = vangle2 + 2 * M_PI;
+            }
+            /*
+             * If vangle1 < vangle2 then angles are either side of 0 so check is more complicated
+             */
+            if ((vangle1 >= vangle2 &&
+                            vangle1 >= angle && vangle2 < angle) ||
+                            (vangle1 < vangle2 &&
+                                            ((vangle1 >= angle && 0 <= angle) ||
+                                                            (vangle2 < angle && 2 * M_PI >= angle)))) {
+                found = true;
+                break;
+            }
+        }
+        /*
+         * Find intersection point of "line from centre to bounding rect" and edge
+         */
+        if (!found) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "polygon edge not found");
+        }
+        double x3 = x[v1];
+        double y3 = y[v1];
+        double x4 = x[v2];
+        double y4 = y[v2];
+        Point tmp = rectEdge(xmin, ymin, xmax, ymax, theta);
+        double x2 = tmp.x;
+        double y2 = tmp.y;
+        double numa = ((x4 - x3) * (ym - y3) - (y4 - y3) * (xm - x3));
+        double denom = ((y4 - y3) * (x2 - xm) - (x4 - x3) * (y2 - ym));
+        double ua = numa / denom;
+        if (!Double.isFinite(ua)) {
+            /*
+             * Should only happen if lines are parallel, which shouldn't happen! Unless, perhaps the
+             * polygon has zero extent vertically or horizontally ... ?
+             */
+            throw RInternalError.shouldNotReachHere("polygon edge not found (zero-width or zero-height?)");
+        }
+        /*
+         * numb = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)); ub = numb/denom;
+         */
+        return new Point(xm + ua * (x2 - xm), ym + ua * (y2 - ym));
+    }
+
+    /**
+     * An arbitrarily-oriented rectangle. The vertices are assumed to be in order going
+     * anticlockwise around the rectangle.
+     */
+    public static final class Rectangle {
+        public final double[] x;
+        public final double[] y;
+
+        public Rectangle(Point p1, Point p2, Point p3, Point p4) {
+            x = new double[]{p1.x, p2.x, p3.x, p4.x};
+            y = new double[]{p1.y, p2.y, p3.y, p4.y};
+        }
+
+        public boolean intersects(Rectangle r2) {
+            return edgesIntersect(this.x[0], this.x[1], this.y[0], this.y[1], r2) ||
+                            edgesIntersect(this.x[1], this.x[2], this.y[1], this.y[2], r2) ||
+                            edgesIntersect(this.x[2], this.x[3], this.y[2], this.y[3], r2) ||
+                            edgesIntersect(this.x[3], this.x[0], this.y[3], this.y[0], r2);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 4d77162e3d..d2c548069a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -20,6 +20,7 @@ public final class GridState {
     private RList gpar;
     private RList viewPort;
     private REnvironment gridEnv;
+    private double scale = 1;
     private boolean deviceInitialized;
 
     /**
@@ -79,4 +80,9 @@ public final class GridState {
     public void setCurrentGrob(Object currentGrob) {
         this.currentGrob = currentGrob;
     }
+
+    public double getScale() {
+        return scale;
+    }
+
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
new file mode 100644
index 0000000000..f60dc1dff8
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -0,0 +1,247 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 2001-2015, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.transLocation;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+/**
+ * Implements what is in the original grid code implemented by {@code gridText} function.
+ *
+ * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the
+ * 'length' dispatches to S3 method giving us unit length like {@link Unit.UnitLengthNode}.
+ */
+public final class GridTextNode extends RBaseNode {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+    private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile();
+    private final boolean draw;
+
+    static void addGridTextCasts(Casts casts) {
+        casts.arg(0).asStringVector();
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(abstractVectorValue());
+        casts.arg(3).mustBe(numericValue()).asDoubleVector();
+        casts.arg(4).mustBe(numericValue()).asDoubleVector();
+        casts.arg(5).mustBe(numericValue()).asDoubleVector();
+    }
+
+    private GridTextNode(boolean draw) {
+        this.draw = draw;
+    }
+
+    public static GridTextNode createDraw() {
+        return new GridTextNode(true);
+    }
+
+    public static GridTextNode createCalculateBounds() {
+        return new GridTextNode(false);
+    }
+
+    public Object gridText(RAbstractStringVector textVec, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjustVec, RAbstractDoubleVector vjustVec, RAbstractDoubleVector rotationVec,
+                    boolean checkOverlapIn, double theta) {
+        if (textVec.getLength() == 0) {
+            return RNull.instance;
+        }
+
+        boolean checkOverlap = checkOverlapProfile.profile(checkOverlapIn);
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        int length = GridUtils.maxLength(unitLength, x, y);
+
+        // following variables will hold the (intermediate) results of bounds checking
+        int boundsCount = 0;
+        Point edge = null;
+        double xmin = Double.MAX_VALUE;
+        double xmax = Double.MIN_VALUE;
+        double ymin = Double.MAX_VALUE;
+        double ymax = Double.MIN_VALUE;
+        int ntxt = 0;   // number of texts that were actually used for bounds computation
+        EdgeDetection.Rectangle[] bounds = null;
+        if (checkOverlap || !draw) {
+            bounds = new EdgeDetection.Rectangle[length];
+        }
+
+        for (int i = 0; i < length; i++) {
+            Point loc = Point.fromUnits(unitToInches, x, y, i, conversionCtx);
+            if (draw) {
+                // transformation not necessary for bounds calculation
+                loc = transLocation(loc, vpTransform.transform);
+            }
+
+            String text = textVec.getDataAt(i % textVec.getLength());
+            double hjust = getDataAtMod(hjustVec, i);
+            double vjust = getDataAtMod(vjustVec, i);
+            double rotation = getDataAtMod(rotationVec, i);
+
+            // update bounds if necessary
+            boolean doDraw = true;
+            Rectangle trect = null;
+            if (checkOverlap || !draw) {
+                trect = textRect(loc, hjust, vjust, rotation, text, drawingCtx, dev);
+                for (int j = 0; j < boundsCount; j++) {
+                    if (trect.intersects(bounds[j])) {
+                        doDraw = false;
+                        break;
+                    }
+                }
+                if (doDraw) {
+                    bounds[boundsCount++] = trect;
+                }
+            }
+
+            // actual drawing
+            if (draw && doDraw) {
+                text(loc.x, loc.y, text, hjust, vjust, rotation, drawingCtx, dev);
+            }
+
+            // or bounds checking
+            if (!draw) {
+                if (Double.isFinite(loc.x) && Double.isFinite(loc.y)) {
+                    xmin = fmin(xmin, trect.x);
+                    xmax = fmax(xmax, trect.x);
+                    ymin = fmin(ymin, trect.y);
+                    ymax = fmax(ymax, trect.y);
+                    // Calculate edgex and edgey for case where this is the only rect
+                    edge = EdgeDetection.polygonEdge(trect.x, trect.y, 4, theta);
+                    ntxt++;
+                }
+            }
+        }
+
+        if (!draw && ntxt > 0) {
+            // If there is more than one text, just produce edge based on bounding rect of all text
+            if (ntxt > 1) {
+                // Produce edge of rect bounding all text
+                edge = EdgeDetection.rectEdge(xmin, ymin, xmax, ymax, theta);
+            }
+
+            double scale = GridContext.getContext().getGridState().getScale();
+            double[] result = new double[4];
+            result[0] = edge.x / scale;
+            result[1] = edge.y / scale;
+            result[2] = (xmax - xmin) / scale;
+            result[3] = (ymax - ymin) / scale;
+            return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
+        }
+
+        // NULL is OK result even for bound checking if there was no text actually "drawn", the R
+        // wrapper deals with NULL in such case. For actual drawing case, we should always return
+        // NULL
+        return RNull.instance;
+    }
+
+    // transcribed from utils.c
+
+    private EdgeDetection.Rectangle textRect(Point loc, double xadj, double yadj, double rotation, String text, DrawingContext drawingCtx, GridDevice device) {
+        // TODO: for expressions the h and w are calculated differently
+        double h = device.getStringHeight(drawingCtx, text);
+        double w = device.getStringWidth(drawingCtx, text);
+
+        double[][] thisJustification = translation(-xadj * w, -yadj * h);
+        double[][] thisRotation = TransformMatrix.rotation(rotation);
+        double[][] transform = multiply(multiply(thisJustification, thisRotation), translation(loc.x, loc.y));
+
+        Point bl = transLocation(new Point(0, 0), transform);
+        Point br = transLocation(new Point(w, 0), transform);
+        Point tr = transLocation(new Point(w, h), transform);
+        Point tl = transLocation(new Point(0, h), transform);
+        return new Rectangle(bl, br, tr, tl);
+    }
+
+    // transcribed from engine.c
+
+    private void text(double x, double y, String text, double xadjIn, double yadj, double rotation, DrawingContext drawingCtx, GridDevice device) {
+        if (!Double.isFinite(yadj)) {
+            throw RInternalError.unimplemented("'exact' vertical centering, see engine.c:1700");
+        }
+        double xadj = Double.isFinite(xadjIn) ? xadjIn : 0.5;
+
+        double radRotation = Math.toRadians(rotation);
+        double cosRot = Math.cos(radRotation);
+        double sinRot = Math.sin(radRotation);
+        String[] lines = text.split("\n");
+        for (int lineIdx = 0; lineIdx < lines.length; lineIdx++) {
+            double xoff;
+            double yoff;
+            if (lines.length == 1) {
+                // simplification for single line
+                xoff = x;
+                yoff = y;
+            } else {
+                yoff = (1 - yadj) * (lines.length - 1) - lineIdx;
+                // TODO: in the original the following formula uses "dd->dev->cra[1]"
+                yoff *= (drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+                xoff = -yoff * sinRot;
+                yoff = yoff * cosRot;
+                xoff = x + xoff;
+                yoff = y + yoff;
+            }
+
+            double xleft = xoff;
+            double ybottom = yoff;
+            // now determine bottom-left for THIS line
+            if (xadj != 0.0 || yadj != 0.0) {
+                // otherwise simply the initial values for xleft and ybottom are OK
+                double width = device.getStringWidth(drawingCtx, lines[lineIdx]);
+                double height = device.getStringHeight(drawingCtx, lines[lineIdx]);
+                xleft = xoff - (xadj) * width * cosRot + yadj * height * sinRot;
+                ybottom = yoff - (xadj) * width * sinRot - yadj * height * cosRot;
+            }
+
+            device.drawString(drawingCtx, xleft, ybottom, rotation, lines[lineIdx]);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 89bf150002..b6acae809c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -11,6 +11,9 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
+import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2;
+
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -46,4 +49,22 @@ final class GridUtils {
         }
         return result;
     }
+
+    @ExplodeLoop
+    static double fmax(double firstVal, double... vals) {
+        double result = firstVal;
+        for (double val : vals) {
+            result = fmax2(result, val);
+        }
+        return result;
+    }
+
+    @ExplodeLoop
+    static double fmin(double firstVal, double... vals) {
+        double result = firstVal;
+        for (double val : vals) {
+            result = fmin2(result, val);
+        }
+        return result;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java
index cc3b9082a4..c22cf068da 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java
@@ -1,54 +1,46 @@
 /*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- * Copyright (C) 2001-3 Paul Murrell
- * Copyright (c) 1998-2013, The R Core Team
- * Copyright (c) 2017, Oracle and/or its affiliates
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- * All rights reserved.
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
-import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.library.fastrGrid.GridTextNode.addGridTextCasts;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
-import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-/**
- * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the
- * 'length' dispatches to S3 method giving us unit length like {@link Unit.UnitLengthNode}.
- */
+@NodeInfo(cost = NodeCost.NONE)
 public abstract class LText extends RExternalBuiltinNode.Arg7 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
-
     static {
         Casts casts = new Casts(LText.class);
-        // TODO: expressions and maybe other types should have special handling, not only simple
-        // String coercion
-        casts.arg(0).asStringVector();
-        casts.arg(1).mustBe(abstractVectorValue());
-        casts.arg(2).mustBe(abstractVectorValue());
-        casts.arg(3).mustBe(numericValue()).asDoubleVector();
-        casts.arg(4).mustBe(numericValue()).asDoubleVector();
-        casts.arg(5).mustBe(numericValue()).asDoubleVector();
+        addGridTextCasts(casts);
+        casts.arg(6).mustBe(logicalValue()).asLogicalVector().findFirst().map(toBoolean());
     }
 
     public static LText create() {
@@ -56,70 +48,8 @@ public abstract class LText extends RExternalBuiltinNode.Arg7 {
     }
 
     @Specialization
-    Object drawText(RAbstractStringVector text, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, RAbstractDoubleVector rotation,
-                    Object checkOverlapIgnored) {
-        if (text.getLength() == 0) {
-            return RNull.instance;
-        }
-
-        GridContext ctx = GridContext.getContext();
-        GridDevice dev = ctx.getCurrentDevice();
-
-        RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
-
-        int length = GridUtils.maxLength(unitLength, x, y);
-        for (int i = 0; i < length; i++) {
-            Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x, y, i, conversionCtx), vpTransform.transform);
-            text(loc.x, loc.y, text.getDataAt(i % text.getLength()), getDataAtMod(hjust, i), getDataAtMod(vjust, i), getDataAtMod(rotation, i), drawingCtx, dev);
-        }
-        return RNull.instance;
-    }
-
-    // transcribed from engine.c
-
-    private void text(double x, double y, String text, double xadjIn, double yadj, double rotation, DrawingContext drawingCtx, GridDevice device) {
-        if (!Double.isFinite(yadj)) {
-            throw new RuntimeException("Not implemented: 'exact' vertical centering, see engine.c:1700");
-        }
-        double xadj = Double.isFinite(xadjIn) ? xadjIn : 0.5;
-
-        double radRotation = Math.toRadians(rotation);
-        double cosRot = Math.cos(radRotation);
-        double sinRot = Math.sin(radRotation);
-        String[] lines = text.split("\n");
-        for (int lineIdx = 0; lineIdx < lines.length; lineIdx++) {
-            double xoff;
-            double yoff;
-            if (lines.length == 1) {
-                // simplification for single line
-                xoff = x;
-                yoff = y;
-            } else {
-                yoff = (1 - yadj) * (lines.length - 1) - lineIdx;
-                // TODO: in the original the following formula uses "dd->dev->cra[1]"
-                yoff *= (drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
-                xoff = -yoff * sinRot;
-                yoff = yoff * cosRot;
-                xoff = x + xoff;
-                yoff = y + yoff;
-            }
-
-            double xleft = xoff;
-            double ybottom = yoff;
-            // now determine bottom-left for THIS line
-            if (xadj != 0.0 || yadj != 0.0) {
-                // otherwise simply the initial values for xleft and ybottom are OK
-                double width = device.getStringWidth(drawingCtx, lines[lineIdx]);
-                double height = device.getStringHeight(drawingCtx, lines[lineIdx]);
-                xleft = xoff - (xadj) * width * cosRot + yadj * height * sinRot;
-                ybottom = yoff - (xadj) * width * sinRot - yadj * height * cosRot;
-            }
-
-            device.drawString(drawingCtx, xleft, ybottom, rotation, lines[lineIdx]);
-        }
+    Object drawText(RAbstractStringVector text, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, RAbstractDoubleVector rotation, boolean checkOverlap,
+                    @Cached("createDraw()") GridTextNode gridText) {
+        return gridText.gridText(text, x, y, hjust, vjust, rotation, checkOverlap, 0);
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java
new file mode 100644
index 0000000000..fa1ec97d72
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LTextBounds.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridTextNode.addGridTextCasts;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+@NodeInfo(cost = NodeCost.NONE)
+public abstract class LTextBounds extends RExternalBuiltinNode.Arg7 {
+    static {
+        Casts casts = new Casts(LTextBounds.class);
+        addGridTextCasts(casts);
+        casts.arg(6).returnIf(missingValue().or(nullValue()), constant(0)).asDoubleVector().findFirst();
+    }
+
+    public static LTextBounds create() {
+        return LTextBoundsNodeGen.create();
+    }
+
+    @Specialization
+    public Object textBounds(RAbstractStringVector text, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, RAbstractDoubleVector rotation, double theta,
+                    @Cached("createCalculateBounds()") GridTextNode gridText) {
+        return gridText.gridText(text, x, y, hjust, vjust, rotation, false, theta);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
index 7b66ab2bae..e1051c98a4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
@@ -11,6 +11,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI;
+
 /**
  * Operations on transformation (3x3) matrices.
  */
@@ -40,6 +42,21 @@ final class TransformMatrix {
         return m;
     }
 
+    static double[][] rotation(double theta) {
+        double thetarad = theta / 180 * M_PI;
+        double costheta = Math.cos(thetarad);
+        double sintheta = Math.sin(thetarad);
+        double[][] result = identity();
+        if (theta == 0) {
+            return result;
+        }
+        result[0][0] = costheta;
+        result[0][1] = sintheta;
+        result[1][0] = -sintheta;
+        result[1][1] = costheta;
+        return result;
+    }
+
     static double[][] identity() {
         double[][] result = new double[3][3];
         result[0][0] = 1;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index f5e5f53006..9a51634737 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -22,6 +22,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.library.fastrGrid.GridState;
 import com.oracle.truffle.r.library.fastrGrid.GridStateGetNode;
 import com.oracle.truffle.r.library.fastrGrid.GridStateSetNode;
 import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal;
@@ -34,6 +35,7 @@ import com.oracle.truffle.r.library.fastrGrid.LNewPage;
 import com.oracle.truffle.r.library.fastrGrid.LRect;
 import com.oracle.truffle.r.library.fastrGrid.LSegments;
 import com.oracle.truffle.r.library.fastrGrid.LText;
+import com.oracle.truffle.r.library.fastrGrid.LTextBounds;
 import com.oracle.truffle.r.library.fastrGrid.LUpViewPort;
 import com.oracle.truffle.r.library.grDevices.DevicesCCalls;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
@@ -695,6 +697,8 @@ public class CallAndExternalFunctions {
                     return LLines.create();
                 case "L_text":
                     return LText.create();
+                case "L_textBounds":
+                    return LTextBounds.create();
                 case "L_segments":
                     return LSegments.create();
                 case "L_circle":
@@ -702,15 +706,15 @@ public class CallAndExternalFunctions {
 
                 // Simple grid state access
                 case "L_getGPar":
-                    return new GridStateGetNode(state -> state.getGpar());
+                    return new GridStateGetNode(GridState::getGpar);
                 case "L_setGPar":
                     return GridStateSetNode.create((state, val) -> state.setGpar((RList) val));
                 case "L_getCurrentGrob":
-                    return new GridStateGetNode(state -> state.getCurrentGrob());
+                    return new GridStateGetNode(GridState::getCurrentGrob);
                 case "L_setCurrentGrob":
-                    return GridStateSetNode.create((state, val) -> state.setCurrentGrob(val));
+                    return GridStateSetNode.create(GridState::setCurrentGrob);
                 case "L_currentViewport":
-                    return new GridStateGetNode(state -> state.getViewPort());
+                    return new GridStateGetNode(GridState::getViewPort);
 
                 // Display list stuff: not implemented atm
                 case "L_getDisplayList":
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 86618d197a..670e335899 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -773,7 +773,6 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewP
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LText.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
@@ -788,3 +787,5 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
-- 
GitLab


From cf4551064e7d6a2531e1859a24dd9dbea2cccdbf Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 7 Mar 2017 14:16:07 +0100
Subject: [PATCH 154/402] FastR grid: implement L_convert

---
 .../truffle/r/library/fastrGrid/LConvert.java | 98 +++++++++++++++++++
 .../truffle/r/library/fastrGrid/Unit.java     | 84 ++++++++++++----
 .../foreign/CallAndExternalFunctions.java     |  3 +
 mx.fastr/copyrights/overrides                 |  1 +
 4 files changed, 167 insertions(+), 19 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
new file mode 100644
index 0000000000..0733409cb1
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -0,0 +1,98 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.Unit.NATIVE;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.NPC;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.VALID_UNIT_ATTR;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    static {
+        Casts casts = new Casts(LConvert.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(3)));
+        casts.arg(2).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(3)));
+        casts.arg(3).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(Unit.LAST_NORMAL_UNIT)));
+    }
+
+    public static LConvert create() {
+        return LConvertNodeGen.create();
+    }
+
+    @Specialization
+    Object doConvert(RAbstractVector units, int axisFrom, int axisTo, int unitTo) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        int length = unitLength.execute(units);
+        double[] result = new double[length];
+
+        int fromUnitId = RRuntime.asInteger(units.getAttr(VALID_UNIT_ATTR));
+        boolean relativeUnits = isRelative(unitTo) || isRelative(fromUnitId);
+        if ((vpTransform.size.getHeight() < 1e-6 || vpTransform.size.getWidth() < 1e-6) && relativeUnits) {
+            throw RInternalError.unimplemented("L_convert: relative units with close to zero width or height");
+        }
+
+        for (int i = 0; i < length; i++) {
+            double inches;
+            if (isXAxis(axisFrom)) {
+                inches = unitToInches.convertX(units, i, conversionCtx);
+            } else {
+                inches = unitToInches.convertY(units, i, conversionCtx);
+            }
+            if (isXAxis(axisTo)) {
+                result[i] = Unit.convertFromInches(inches, unitTo, vpTransform.size.getWidth(), vpContext.xscalemin, vpContext.xscalemax, drawingCtx);
+            } else {
+                result[i] = Unit.convertFromInches(inches, unitTo, vpTransform.size.getHeight(), vpContext.yscalemin, vpContext.yscalemax, drawingCtx);
+            }
+        }
+
+        return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
+    }
+
+    private static boolean isRelative(int unitId) {
+        return unitId == NPC || unitId == NATIVE;
+    }
+
+    // what = 0 means x, 1 means y, 2 means width, 3 means height
+    private static boolean isXAxis(int what) {
+        return what % 2 == 0;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index c12899186e..f646edaf0c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -34,13 +34,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
  * enter our system.
  */
 public class Unit {
-    private static final String VALID_UNIT_ATTR = "valid.unit";
+    static final String VALID_UNIT_ATTR = "valid.unit";
 
-    private static final int NPC = 0;
+    public static final int NPC = 0;
     public static final int CM = 1;
     public static final int INCHES = 2;
-    private static final int LINES = 3;
-    private static final int NATIVE = 4;
+    public static final int LINES = 3;
+    public static final int NATIVE = 4;
     public static final int NULL = 5; /* only used in layout specifications (?) */
     public static final int SNPC = 6;
     public static final int MM = 7;
@@ -71,6 +71,7 @@ public class Unit {
     public static final int GROBHEIGHT = 22;
     public static final int GROBASCENT = 23;
     public static final int GROBDESCENT = 24;
+    public static final int LAST_NORMAL_UNIT = GROBDESCENT;
     /*
      * No longer used
      */
@@ -97,6 +98,65 @@ public class Unit {
         return UnitToInchesNode.create();
     }
 
+    static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+        switch (unitId) {
+            case NATIVE:
+                return ((value + scalemin) * (scalemax - scalemin)) / vpSize;
+            case NPC:
+                return value / vpSize;
+            case CM:
+                return value * CM_IN_INCH;
+            case MM:
+                return value * CM_IN_INCH * 10;
+            case INCHES:
+                return value;
+            case POINTS:
+                return value * INCH_TO_POINTS_FACTOR;
+            case LINES:
+                return (value * INCH_TO_POINTS_FACTOR) / (drawingCtx.getFontSize() * drawingCtx.getLineHeight());
+            // following units are not supported even by original grid
+            case SNPC:
+            case MYCHAR:
+            case MYLINES:
+            case STRINGWIDTH:
+            case MYSTRINGWIDTH:
+            case STRINGHEIGHT:
+            case MYSTRINGHEIGHT:
+            case GROBX:
+            case GROBY:
+            case GROBWIDTH:
+            case GROBHEIGHT:
+            case NULL:
+            default:
+                throw RInternalError.unimplemented("unit type " + unitId + " in convertFromInches");
+        }
+    }
+
+    static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+        switch (unitId) {
+            case NATIVE:
+                return ((value - scalemin) / (scalemax - scalemin)) * vpSize;
+            case NPC:
+                return value * vpSize;
+            case POINTS:
+                return value / INCH_TO_POINTS_FACTOR;
+            case CM:
+                return value / CM_IN_INCH;
+            case MM:
+                return value / (CM_IN_INCH * 10);
+            case LINES:
+            case MYLINES:
+                return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+
+            default:
+                throw RInternalError.unimplemented("unit type " + unitId + " in convertToInches");
+        }
+    }
+
+    public static UnitElementAtNode createElementAtNode() {
+        return UnitElementAtNode.create();
+    }
+
     public abstract static class UnitNodeBase extends Node {
         @Child private InheritsCheckNode inheritsCheckNode = new InheritsCheckNode("unit.arithmetic");
 
@@ -191,7 +251,7 @@ public class Unit {
         @Specialization(guards = "!isArithmetic(value)")
         double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
             int unitId = (Integer) castUnitId.execute(value.getAttr(VALID_UNIT_ATTR));
-            return convert(elementAtNode.execute(value, index % value.getLength()), unitId, vpSize, scalemin, scalemax, drawingCtx);
+            return convertToInches(elementAtNode.execute(value, index % value.getLength()), unitId, vpSize, scalemin, scalemax, drawingCtx);
         }
 
         @Specialization(guards = "isArithmetic(list)")
@@ -199,19 +259,5 @@ public class Unit {
             throw RInternalError.unimplemented("UnitToInches for arithmetic units");
         }
 
-        private static double convert(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
-            switch (unitId) {
-                case NATIVE:
-                    return ((value - scalemin) / (scalemax - scalemin)) * vpSize;
-                case NPC:
-                    return value * vpSize;
-                case LINES:
-                case MYLINES:
-                    return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
-
-                default:
-                    throw RInternalError.unimplemented("unit type " + unitId + " in UnitToInches");
-            }
-        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 9a51634737..9e39ceca94 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.r.library.fastrGrid.GridStateGetNode;
 import com.oracle.truffle.r.library.fastrGrid.GridStateSetNode;
 import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal;
 import com.oracle.truffle.r.library.fastrGrid.LCircle;
+import com.oracle.truffle.r.library.fastrGrid.LConvert;
 import com.oracle.truffle.r.library.fastrGrid.LGridDirty;
 import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
 import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
@@ -680,6 +681,8 @@ public class CallAndExternalFunctions {
                     return LInitGrid.create();
                 case "L_newpage":
                     return new LNewPage();
+                case "L_convert":
+                    return LConvert.create();
 
                 // Viewport management
                 case "L_upviewport":
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 670e335899..8119e383c8 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -789,3 +789,4 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNam
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright
-- 
GitLab


From eb31ea8cb8005f92e92918ffd2363687bc55d55b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 7 Mar 2017 16:03:37 +0100
Subject: [PATCH 155/402] FastR grid: simple graphics emulation + L_initGPar

---
 .../r/library/fastrGrid/GridState.java        |  2 +-
 .../r/library/fastrGrid/LInitGPar.java        | 39 ++++++++++
 .../r/library/fastrGrid/graphics/CPar.java    | 71 +++++++++++++++++++
 .../fastrGrid/graphics/package-info.java      |  7 ++
 .../foreign/CallAndExternalFunctions.java     | 37 +++++-----
 5 files changed, 139 insertions(+), 17 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index d2c548069a..72a3c45c74 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -38,7 +38,7 @@ public final class GridState {
         initGPar(currentDevice);
     }
 
-    private void initGPar(GridDevice currentDevice) {
+    void initGPar(GridDevice currentDevice) {
         gpar = GPar.createNew();
         currentDevice.initDrawingContext(GPar.asDrawingContext(gpar));
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
new file mode 100644
index 0000000000..c0bd6650a5
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class LInitGPar extends RExternalBuiltinNode {
+    static {
+        Casts.noCasts(LInitGPar.class);
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        GridContext.getContext().getGridState().initGPar(GridContext.getContext().getCurrentDevice());
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
new file mode 100644
index 0000000000..2e59a39796
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.graphics;
+
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+
+public class CPar extends RExternalBuiltinNode {
+    static {
+        Casts.noCasts(CPar.class);
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        if (args.getSignature().getNonNullCount() > 0) {
+            throw error(Message.GENERIC, "Using par for setting device parameters is not supported in FastR grid emulation mode.");
+        }
+
+        GridDevice device = GridContext.getContext().getCurrentDevice();
+        Object[] names = args.getArguments();
+        if (names.length == 1) {
+            Object first = args.getArgument(0);
+            if (first instanceof RList) {
+                names = ((RList) first).getDataWithoutCopying();
+            }
+            if (names.length == 1) {
+                // if there is a single name, do not wrap the result in a list
+                return getParam(RRuntime.asString(names[0]), device);
+            }
+        }
+
+        throw error(Message.GENERIC, "Querying par for anything else than 'din' is not supported in FastR grid emulation mode.");
+    }
+
+    private Object getParam(String name, GridDevice device) {
+        switch (name) {
+            case "din":
+                return RDataFactory.createDoubleVector(new double[]{device.getWidth(), device.getHeight()}, RDataFactory.COMPLETE_VECTOR);
+            default:
+                throw RError.nyi(RError.NO_CALLER, "C_Par paramter '" + name + "'");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java
new file mode 100644
index 0000000000..f358dfb3c0
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java
@@ -0,0 +1,7 @@
+/**
+ * Compatibility layer for graphics package.
+ *
+ * Some R code that uses mainly grid for drawing resorts to several graphics package functions,
+ * especially in order to control or query information about device(s).
+ */
+package com.oracle.truffle.r.library.fastrGrid.graphics;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 9e39ceca94..9a10b92b97 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal;
 import com.oracle.truffle.r.library.fastrGrid.LCircle;
 import com.oracle.truffle.r.library.fastrGrid.LConvert;
 import com.oracle.truffle.r.library.fastrGrid.LGridDirty;
+import com.oracle.truffle.r.library.fastrGrid.LInitGPar;
 import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
 import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
 import com.oracle.truffle.r.library.fastrGrid.LLines;
@@ -38,9 +39,8 @@ import com.oracle.truffle.r.library.fastrGrid.LSegments;
 import com.oracle.truffle.r.library.fastrGrid.LText;
 import com.oracle.truffle.r.library.fastrGrid.LTextBounds;
 import com.oracle.truffle.r.library.fastrGrid.LUpViewPort;
-import com.oracle.truffle.r.library.grDevices.DevicesCCalls;
+import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
-import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_Par;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_PlotXY;
 import com.oracle.truffle.r.library.grid.GridFunctionsFactory.InitGridNodeGen;
 import com.oracle.truffle.r.library.grid.GridFunctionsFactory.ValidUnitsNodeGen;
@@ -71,10 +71,10 @@ import com.oracle.truffle.r.library.stats.RandFunctionsNodes.RandFunction3Node;
 import com.oracle.truffle.r.library.stats.SignrankFreeNode;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineCoefNodeGen;
 import com.oracle.truffle.r.library.stats.SplineFunctionsFactory.SplineEvalNodeGen;
-import com.oracle.truffle.r.library.stats.deriv.D;
-import com.oracle.truffle.r.library.stats.deriv.Deriv;
 import com.oracle.truffle.r.library.stats.StatsFunctionsNodes;
 import com.oracle.truffle.r.library.stats.WilcoxFreeNode;
+import com.oracle.truffle.r.library.stats.deriv.D;
+import com.oracle.truffle.r.library.stats.deriv.Deriv;
 import com.oracle.truffle.r.library.tools.C_ParseRdNodeGen;
 import com.oracle.truffle.r.library.tools.DirChmodNodeGen;
 import com.oracle.truffle.r.library.tools.Rmd5NodeGen;
@@ -258,8 +258,11 @@ public class CallAndExternalFunctions {
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
             String name = lookupName(symbol);
-            if (FastROptions.UseInternalGridGraphics.getBooleanValue() && name != null && name.startsWith("L_")) {
-                return lookupFastRGridBuiltin(name);
+            if (FastROptions.UseInternalGridGraphics.getBooleanValue() && name != null) {
+                RExternalBuiltinNode gridExternal = lookupFastRGridBuiltin(name);
+                if (gridExternal != null) {
+                    return gridExternal;
+                }
             }
             switch (name) {
                 // methods
@@ -718,6 +721,8 @@ public class CallAndExternalFunctions {
                     return GridStateSetNode.create(GridState::setCurrentGrob);
                 case "L_currentViewport":
                     return new GridStateGetNode(GridState::getViewPort);
+                case "L_initGPar":
+                    return new LInitGPar();
 
                 // Display list stuff: not implemented atm
                 case "L_getDisplayList":
@@ -741,7 +746,11 @@ public class CallAndExternalFunctions {
                 case "L_validUnits":
                     return null;
                 default:
-                    throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
+                    if (name.startsWith("L_")) {
+                        throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
+                    } else {
+                        return null;
+                    }
             }
         }
 
@@ -831,14 +840,10 @@ public class CallAndExternalFunctions {
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList f) {
             String name = lookupName(f);
-            if (FastROptions.UseInternalGraphics.getBooleanValue()) {
+            if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
                 switch (name) {
-                    case "PDF":
-                        return new DevicesCCalls.C_PDF();
-                    case "devoff":
-                        return DevicesCCalls.C_DevOff.create();
-                    case "devcur":
-                        return new DevicesCCalls.C_DevCur();
+                    case "devholdflush":
+                        return new IgnoredGridExternal(RNull.instance);
                 }
             }
             switch (name) {
@@ -952,10 +957,10 @@ public class CallAndExternalFunctions {
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
-            if (FastROptions.UseInternalGraphics.getBooleanValue()) {
+            if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
                 switch (lookupName(symbol)) {
                     case "C_par":
-                        return new C_Par();
+                        return new CPar();
                 }
             }
             String name = lookupName(symbol);
-- 
GitLab


From fd368eb96993a183112699912b25c7b1cd2c03e2 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 8 Mar 2017 12:26:41 +0100
Subject: [PATCH 156/402] FastR grid: arithmetic units support, fix
 width/length conversions

---
 .../truffle/r/library/fastrGrid/LCircle.java  |   4 +-
 .../truffle/r/library/fastrGrid/LConvert.java |  42 +++-
 .../truffle/r/library/fastrGrid/LRect.java    |   7 +-
 .../truffle/r/library/fastrGrid/Point.java    |   4 +
 .../truffle/r/library/fastrGrid/Size.java     |  10 +
 .../truffle/r/library/fastrGrid/Unit.java     | 203 ++++++++++++++----
 6 files changed, 208 insertions(+), 62 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index e4aee83200..60448d3fa7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -23,6 +23,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
@@ -54,7 +55,8 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
-            double radius = unitToInches.convertX(radiusVec, i, conversionCtx);
+            Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
+            double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             dev.drawCircle(drawingCtx, loc.x, loc.y, radius);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 0733409cb1..6ddbce8084 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -20,6 +20,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
@@ -37,6 +38,9 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
     @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+    private final ValueProfile unitToProfile = ValueProfile.createEqualityProfile();
+    private final ValueProfile axisToProfile = ValueProfile.createEqualityProfile();
+    private final ValueProfile axisFromProfile = ValueProfile.createEqualityProfile();
 
     static {
         Casts casts = new Casts(LConvert.class);
@@ -51,7 +55,11 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doConvert(RAbstractVector units, int axisFrom, int axisTo, int unitTo) {
+    Object doConvert(RAbstractVector units, int axisFromIn, int axisToIn, int unitToIn) {
+        int axisFrom = axisFromProfile.profile(axisFromIn);
+        int axisTo = axisToProfile.profile(axisToIn);
+        int unitTo = unitToProfile.profile(unitToIn);
+
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
 
@@ -71,20 +79,30 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         }
 
         for (int i = 0; i < length; i++) {
-            double inches;
-            if (isXAxis(axisFrom)) {
-                inches = unitToInches.convertX(units, i, conversionCtx);
+            double inches = toInches(units, i, axisFrom, conversionCtx);
+            double vpSize = isXAxis(axisTo) ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
+            result[i] = Unit.convertFromInches(inches, unitTo, vpSize, vpContext.xscalemin, vpContext.xscalemax, isDimension(axisTo), drawingCtx);
+        }
+
+        return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
+    }
+
+    private double toInches(RAbstractVector units, int index, int axisFrom, UnitConversionContext conversionCtx) {
+        double inches;
+        if (isXAxis(axisFrom)) {
+            if (isDimension(axisFrom)) {
+                inches = unitToInches.convertWidth(units, index, conversionCtx);
             } else {
-                inches = unitToInches.convertY(units, i, conversionCtx);
+                inches = unitToInches.convertX(units, index, conversionCtx);
             }
-            if (isXAxis(axisTo)) {
-                result[i] = Unit.convertFromInches(inches, unitTo, vpTransform.size.getWidth(), vpContext.xscalemin, vpContext.xscalemax, drawingCtx);
+        } else {
+            if (isDimension(axisFrom)) {
+                inches = unitToInches.convertHeight(units, index, conversionCtx);
             } else {
-                result[i] = Unit.convertFromInches(inches, unitTo, vpTransform.size.getHeight(), vpContext.yscalemin, vpContext.yscalemax, drawingCtx);
+                inches = unitToInches.convertY(units, index, conversionCtx);
             }
         }
-
-        return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
+        return inches;
     }
 
     private static boolean isRelative(int unitId) {
@@ -95,4 +113,8 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     private static boolean isXAxis(int what) {
         return what % 2 == 0;
     }
+
+    private static boolean isDimension(int what) {
+        return what >= 2;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index e775dde053..a7557972f3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -60,14 +60,13 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
-            double w = unitToInches.convertX(wVec, i, conversionCtx);
-            double h = unitToInches.convertY(hVec, i, conversionCtx);
+            Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
             // Note: once this is factored to drawing/recording: this transformation is necessary
             // only for drawing
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
-            Point loc = transLoc.justify(w, h, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
-            dev.drawRect(drawingCtx, loc.x, loc.y, w, h);
+            Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
+            dev.drawRect(drawingCtx, loc.x, loc.y, size.getWidth(), size.getHeight());
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
index 7bd1158d1d..a6a68509ef 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
@@ -41,6 +41,10 @@ public final class Point {
         return new Point(newX, newY);
     }
 
+    public Point justify(Size size, double hjust, double vjust) {
+        return justify(size.getWidth(), size.getHeight(), hjust, vjust);
+    }
+
     public Point justify(double width, double height, double hjust, double vjust) {
         return new Point(GridUtils.justify(x, width, hjust), GridUtils.justify(y, height, vjust));
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
index 803a07eb12..c428af3df6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
@@ -22,6 +22,10 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
 public final class Size {
     private final double width;
     private final double height;
@@ -31,6 +35,12 @@ public final class Size {
         this.height = height;
     }
 
+    public static Size fromUnits(UnitToInchesNode unitToInches, RAbstractVector wVec, RAbstractVector hVec, int index, UnitConversionContext conversionCtx) {
+        double w = unitToInches.convertWidth(wVec, index, conversionCtx);
+        double h = unitToInches.convertHeight(hVec, index, conversionCtx);
+        return new Size(w, h);
+    }
+
     public double getWidth() {
         return width;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index f646edaf0c..2dc08f5b5c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -12,21 +12,27 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
+import java.util.function.Function;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitElementAtNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitLengthNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Note: internally in FastR Grid everything is in inches. However, some lists that are exposed to
@@ -98,10 +104,11 @@ public class Unit {
         return UnitToInchesNode.create();
     }
 
-    static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+    static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
         switch (unitId) {
             case NATIVE:
-                return ((value + scalemin) * (scalemax - scalemin)) / vpSize;
+                double tmp = isDimension ? value : (value + scalemin);
+                return (tmp * (scalemax - scalemin)) / vpSize;
             case NPC:
                 return value / vpSize;
             case CM:
@@ -132,10 +139,11 @@ public class Unit {
         }
     }
 
-    static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+    static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
         switch (unitId) {
             case NATIVE:
-                return ((value - scalemin) / (scalemax - scalemin)) * vpSize;
+                double tmp = isDimension ? value : (value - scalemin);
+                return (tmp / (scalemax - scalemin)) * vpSize;
             case NPC:
                 return value * vpSize;
             case POINTS:
@@ -153,22 +161,73 @@ public class Unit {
         }
     }
 
-    public static UnitElementAtNode createElementAtNode() {
-        return UnitElementAtNode.create();
+    private static final class ArithmeticUnit {
+        public final String op;
+        public final RAbstractContainer arg1;
+        public final RAbstractContainer arg2;
+
+        ArithmeticUnit(String op, RAbstractContainer arg1, RAbstractContainer arg2) {
+            this.op = op;
+            this.arg1 = arg1;
+            this.arg2 = arg2;
+        }
+
+        public boolean isBinary() {
+            return arg2 != null;
+        }
     }
 
-    public abstract static class UnitNodeBase extends Node {
-        @Child private InheritsCheckNode inheritsCheckNode = new InheritsCheckNode("unit.arithmetic");
+    abstract static class UnitNodeBase extends RBaseNode {
+        @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode("unit.arithmetic");
+        @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode("unit.list");
+        @Child private CastNode stringCast;
+        @Child private CastNode abstractContainerCast;
+
+        boolean isSimple(Object obj) {
+            return !inheritsArithmeticCheckNode.execute(obj) && !inheritsUnitListCheckNode.execute(obj);
+        }
 
         boolean isArithmetic(Object obj) {
-            return obj instanceof RList && inheritsCheckNode.execute(obj);
+            return inheritsArithmeticCheckNode.execute(obj);
+        }
+
+        boolean isUnitList(Object obj) {
+            return inheritsUnitListCheckNode.execute(obj);
+        }
+
+        ArithmeticUnit asArithmeticUnit(RList unit) {
+            if (unit.getLength() <= 1) {
+                throw error(Message.GENERIC, "Invalid arithmetic unit (length <= 1).");
+            }
+            if (stringCast == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                stringCast = newCastBuilder().asStringVector().findFirst().buildCastNode();
+            }
+            if (abstractContainerCast == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                abstractContainerCast = newCastBuilder().mustBe(abstractVectorValue()).boxPrimitive().buildCastNode();
+            }
+            // Note: the operator is usually of type character, however in the R code, grid compares
+            // it to symbols, e.g. `x`. Our implementation here should work with symbols too thanks
+            // to the asStringVector() conversion.
+            String op = (String) stringCast.execute(unit.getDataAt(0));
+            RAbstractContainer arg1 = (RAbstractContainer) abstractContainerCast.execute(unit.getDataAt(1));
+            if (op.equals("+") || op.equals("-") || op.equals("*")) {
+                if (unit.getLength() != 3) {
+                    throw error(Message.GENERIC, "Invalid arithmetic unit with binary operator and missing operand.");
+                }
+                return new ArithmeticUnit(op, arg1, (RAbstractContainer) abstractContainerCast.execute(unit.getDataAt(2)));
+            }
+            if (op.equals("max") || op.equals("min") || op.equals("sum")) {
+                return new ArithmeticUnit(op, arg1, null);
+            }
+            throw error(Message.GENERIC, "Unexpected unit operator " + op);
         }
     }
 
     /**
-     * A unit object can represent more or fewer values that the number of elements underlying list
-     * or vector. This node gives the length if the unit in a sense of the upper limit on what can
-     * be used as an index for {@link UnitElementAtNode}.
+     * Arithmetic unit objects can represent 'vectorized' expressions, in such case the 'length' is
+     * not simply the length of the underlying vector/list.
      */
     public abstract static class UnitLengthNode extends UnitNodeBase {
         public static UnitLengthNode create() {
@@ -183,31 +242,17 @@ public class Unit {
         }
 
         @Specialization(guards = "isArithmetic(list)")
-        int doArithmetic(RList list) {
-            throw RInternalError.unimplemented("Length for arithmetic units");
-        }
-    }
-
-    /**
-     * @see UnitLengthNode
-     */
-    public abstract static class UnitElementAtNode extends UnitNodeBase {
-        @Child private CastNode castToDouble = newCastBuilder().asDoubleVector().buildCastNode();
-
-        public static UnitElementAtNode create() {
-            return UnitElementAtNodeGen.create();
-        }
-
-        public abstract double execute(RAbstractContainer vector, int index);
-
-        @Specialization(guards = "!isArithmetic(value)")
-        double doNormal(RAbstractContainer value, int index) {
-            return ((RAbstractDoubleVector) castToDouble.execute(value)).getDataAt(index);
+        int doArithmetic(RList list,
+                        @Cached("create()") UnitLengthNode recursiveLen) {
+            ArithmeticUnit arithmeticUnit = asArithmeticUnit(list);
+            if (arithmeticUnit.isBinary()) {
+                return Math.max(recursiveLen.execute(arithmeticUnit.arg1), recursiveLen.execute(arithmeticUnit.arg2));
+            }
+            return 1;   // op is max, min, sum
         }
 
-        @Specialization(guards = "isArithmetic(list)")
-        double doArithmetic(RList list, int index) {
-            throw RInternalError.unimplemented("UnitElementAt for arithmetic units");
+        static CastNode createStringCast() {
+            return newCastBuilder().asStringVector().findFirst().buildCastNode();
         }
     }
 
@@ -228,36 +273,100 @@ public class Unit {
 
     /**
      * Normalizes grid unit object to a double value in inches. For convenience the index is
-     * interpreted as cyclic unlike in {@link UnitElementAtNode}.
+     * interpreted as cyclic.
      */
     public abstract static class UnitToInchesNode extends UnitNodeBase {
         @Child private CastNode castUnitId = newCastBuilder().mustBe(numericValue()).asIntegerVector().findFirst().buildCastNode();
-        @Child private UnitElementAtNode elementAtNode = UnitElementAtNode.create();
+        @Child private CastNode castDoubleVec = newCastBuilder().mustBe(numericValue()).boxPrimitive().asDoubleVector().buildCastNode();
 
         public static UnitToInchesNode create() {
             return UnitToInchesNodeGen.create();
         }
 
         public double convertX(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
-            return execute(vector, index, conversionCtx.viewPortSize.getWidth(), conversionCtx.viewPortContext.xscalemin, conversionCtx.viewPortContext.xscalemax, conversionCtx.drawingContext);
+            return execute(vector, index, conversionCtx.viewPortSize.getWidth(), conversionCtx.viewPortContext.xscalemin, conversionCtx.viewPortContext.xscalemax, false, conversionCtx.drawingContext);
         }
 
         public double convertY(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
-            return execute(vector, index, conversionCtx.viewPortSize.getHeight(), conversionCtx.viewPortContext.yscalemin, conversionCtx.viewPortContext.yscalemax, conversionCtx.drawingContext);
+            return execute(vector, index, conversionCtx.viewPortSize.getHeight(), conversionCtx.viewPortContext.yscalemin, conversionCtx.viewPortContext.yscalemax, false,
+                            conversionCtx.drawingContext);
         }
 
-        public abstract double execute(RAbstractContainer vector, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx);
+        public double convertWidth(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
+            return execute(vector, index, conversionCtx.viewPortSize.getWidth(), conversionCtx.viewPortContext.xscalemin, conversionCtx.viewPortContext.xscalemax, true, conversionCtx.drawingContext);
+        }
 
-        @Specialization(guards = "!isArithmetic(value)")
-        double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
+        public double convertHeight(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
+            return execute(vector, index, conversionCtx.viewPortSize.getHeight(), conversionCtx.viewPortContext.yscalemin, conversionCtx.viewPortContext.yscalemax, true, conversionCtx.drawingContext);
+        }
+
+        public abstract double execute(RAbstractContainer vector, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx);
+
+        @Specialization(guards = "isSimple(value)")
+        double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
             int unitId = (Integer) castUnitId.execute(value.getAttr(VALID_UNIT_ATTR));
-            return convertToInches(elementAtNode.execute(value, index % value.getLength()), unitId, vpSize, scalemin, scalemax, drawingCtx);
+            RAbstractDoubleVector vector = (RAbstractDoubleVector) castDoubleVec.execute(value);
+            return convertToInches(vector.getDataAt(index % vector.getLength()), unitId, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+        }
+
+        @Specialization(guards = "isUnitList(value)")
+        double doList(RList value, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx,
+                        @Cached("create()") UnitToInchesNode recursiveNode) {
+            Object unwrapped = value.getDataAt(index % value.getLength());
+            if (unwrapped instanceof RAbstractVector) {
+                return recursiveNode.execute((RAbstractContainer) unwrapped, index, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+            }
+            throw error(Message.GENERIC, "Unexpected unit list with non-vector like element at index " + index);
         }
 
         @Specialization(guards = "isArithmetic(list)")
-        double doArithmetic(RList list, int index, double vpSize, double scalemin, double scalemax, DrawingContext drawingCtx) {
-            throw RInternalError.unimplemented("UnitToInches for arithmetic units");
+        double doArithmetic(RList list, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx,
+                        @Cached("createAsDoubleCast()") CastNode asDoubleCast,
+                        @Cached("create()") UnitLengthNode unitLengthNode,
+                        @Cached("create()") UnitToInchesNode recursiveNode) {
+            ArithmeticUnit expr = asArithmeticUnit(list);
+            Function<RAbstractContainer, Double> recursive = x -> recursiveNode.execute(x, index, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+            switch (expr.op) {
+                case "+":
+                    return recursive.apply(expr.arg1) + recursive.apply(expr.arg2);
+                case "-":
+                    return recursive.apply(expr.arg1) + recursive.apply(expr.arg2);
+                case "*":
+                    RAbstractDoubleVector left = (RAbstractDoubleVector) asDoubleCast.execute(expr.arg1);
+                    return left.getDataAt(index % left.getLength()) + recursive.apply(expr.arg2);
+                default:
+                    break;
+            }
+
+            // must be aggregate operation
+            int len = unitLengthNode.execute(expr.arg1);
+            double[] values = new double[len];
+            for (int i = 0; i < len; i++) {
+                values[i] = recursiveNode.execute(expr.arg1, i, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+            }
+
+            switch (expr.op) {
+                case "min":
+                    return GridUtils.fmin(Double.MAX_VALUE, values);
+                case "max":
+                    return GridUtils.fmax(Double.MAX_VALUE, values);
+                case "sum":
+                    return sum(values);
+                default:
+                    throw RInternalError.shouldNotReachHere("The operation should have been validated in asArithmeticUnit method.");
+            }
+        }
+
+        static CastNode createAsDoubleCast() {
+            return newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
         }
 
+        static double sum(double[] values) {
+            double result = 0;
+            for (int i = 0; i < values.length; i++) {
+                result += values[i];
+            }
+            return result;
+        }
     }
 }
-- 
GitLab


From f12f277af89be405c74ad683b34172d8bf14c938 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 9 Mar 2017 17:06:28 +0100
Subject: [PATCH 157/402] FastR grid: initial layout support + few fixes in
 existing code

---
 .../r/library/fastrGrid/DoSetViewPort.java    | 269 ++++++++++-
 .../r/library/fastrGrid/EdgeDetection.java    |  30 +-
 .../truffle/r/library/fastrGrid/GPar.java     |  23 +-
 .../r/library/fastrGrid/GridState.java        |   7 +
 .../r/library/fastrGrid/GridTextNode.java     |   8 +-
 .../r/library/fastrGrid/GridUtils.java        |  87 ++++
 .../truffle/r/library/fastrGrid/LConvert.java |  97 +++-
 .../r/library/fastrGrid/LInitGPar.java        |   2 +-
 .../truffle/r/library/fastrGrid/LLines.java   |   7 +-
 .../truffle/r/library/fastrGrid/Point.java    |   2 +-
 .../r/library/fastrGrid/RGridCodeCall.java    |  61 +++
 .../truffle/r/library/fastrGrid/Unit.java     | 430 ++++++++++++++----
 .../truffle/r/library/fastrGrid/ViewPort.java |  64 ++-
 .../library/fastrGrid/ViewPortTransform.java  |   2 +
 .../library/fastrGrid/device/GridDevice.java  |   2 +-
 .../truffle/r/library/fastrGrid/fastrGrid.R   | 118 ++++-
 .../r/library/fastrGrid/graphics/CPar.java    |  16 +-
 .../fastrGrid/graphics/package-info.java      |  22 +
 18 files changed, 1063 insertions(+), 184 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 133d02cacb..7134c501c4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -11,14 +11,21 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.flatten;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.fromFlat;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.identity;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
+import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
+import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortLocation.VPLocationFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
@@ -31,7 +38,9 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -43,6 +52,7 @@ class DoSetViewPort extends RBaseNode {
     @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
     @Child private VPLocationFromVPNode vpLocationFromVP = new VPLocationFromVPNode();
     @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+    @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
 
     public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
         GridState gridState = GridContext.getContext().getGridState();
@@ -55,7 +65,8 @@ class DoSetViewPort extends RBaseNode {
         }
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
-        calcViewportTransform(pushedViewPort, pushedViewPort.getDataAt(ViewPort.PVP_PARENT), !hasParent, currentDevice, GPar.asDrawingContext(gridState.getGpar()));
+        DrawingContext deviceDrawingContext = GridState.getInitialGPar(currentDevice);
+        calcViewportTransform(pushedViewPort, pushedViewPort.getDataAt(ViewPort.PVP_PARENT), !hasParent, currentDevice, deviceDrawingContext);
 
         // TODO: clipping
         pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
@@ -64,40 +75,46 @@ class DoSetViewPort extends RBaseNode {
         return pushedViewPort;
     }
 
-    private void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext drawingContext) {
+    private void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
         Size parentSize;
+        DrawingContext drawingContext;
         if (parent == null || parent == RNull.instance) {
             parentTransform = TransformMatrix.identity();
             parentContext = ViewPortContext.createDefault();
             parentSize = new Size(device.getWidth(), device.getHeight());
             vpl = vpLocationFromVP.execute(viewPort);
+            drawingContext = deviceDrawingContext;
         } else {
             assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list";
-            RList parentList = (RList) parent;
-            Object[] parentData = parentList.getDataWithoutCopying();
+            RList parentVPList = (RList) parent;
+            Object[] parentData = parentVPList.getDataWithoutCopying();
             if (!incremental) {
-                calcViewportTransform(parentList, parentData[ViewPort.PVP_PARENT], false, device, drawingContext);
+                calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceDrawingContext);
             }
             parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
             parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
-            parentContext = vpContextFromVP.execute(parentList);
+            parentContext = vpContextFromVP.execute(parentVPList);
 
-            // TODO: gcontextFromgpar(viewportParentGPar(vp), 0, &parentgc, dd);
-            // TODO: if (....)
-            vpl = vpLocationFromVP.execute(viewPort);
+            drawingContext = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
+            boolean noLayout = (isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSROW)) && isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSCOL))) || isNull(parentData[ViewPort.VP_LAYOUT]);
+            if (noLayout) {
+                vpl = vpLocationFromVP.execute(viewPort);
+            } else {
+                vpl = calcViewportLocationFromLayout(getLayoutPos(viewPort, parentVPList), parentVPList, parentSize);
+            }
         }
 
         UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, drawingContext);
         double xInches = unitsToInches.convertX(vpl.x, 0, conversionCtx);
         double yInches = unitsToInches.convertY(vpl.y, 0, conversionCtx);
-        double width = unitsToInches.convertX(vpl.width, 0, conversionCtx);
-        double height = unitsToInches.convertY(vpl.height, 0, conversionCtx);
+        double width = unitsToInches.convertWidth(vpl.width, 0, conversionCtx);
+        double height = unitsToInches.convertHeight(vpl.height, 0, conversionCtx);
 
         if (!Double.isFinite(xInches) || !Double.isFinite(yInches) || !Double.isFinite(width) || !Double.isFinite(height)) {
-            error(Message.GENERIC, "non-finite location and/or size for viewport");
+            throw error(Message.GENERIC, "non-finite location and/or size for viewport");
         }
 
         double xadj = GridUtils.justification(width, vpl.hjust);
@@ -119,7 +136,13 @@ class DoSetViewPort extends RBaseNode {
         // Sum up the rotation angles
         // TODO: rotationAngle = parentAngle + viewportAngle(vp);
         double rotationAngle = 0;
-        // TODO: Finally, allocate the rows and columns for this viewport's layout if it has one
+
+        // Finally, allocate the rows and columns for this viewport's layout if it has one
+        if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) {
+            ViewPortContext vpCtx = vpContextFromVP.execute(viewPort);
+            DrawingContext drawingCtx = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)));
+            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, drawingCtx);
+        }
 
         Object[] viewPortData = viewPort.getDataWithoutCopying();
         viewPortData[ViewPort.PVP_WIDTHCM] = scalar(Unit.inchesToCm(width));
@@ -128,6 +151,173 @@ class DoSetViewPort extends RBaseNode {
         viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
     }
 
+    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, DrawingContext drawingCtx) {
+        LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort);
+        double[] npcWidths = new double[layoutSize.ncol];
+        double[] npcHeights = new double[layoutSize.nrow];
+        boolean[] relativeWidths = new boolean[layoutSize.ncol];
+        boolean[] relativeHeights = new boolean[layoutSize.nrow];
+        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, drawingCtx);
+
+        // For both dimensions we find out which units are other than "null" for those we can
+        // immediately calculate the physical size in npcWidth/npcHeights. The reducedWidth/Height
+        // gives us how much of width/height is left after we take up the space by physical units
+        Object[] layoutData = asList(viewPort.getDataAt(ViewPort.VP_LAYOUT)).getDataWithoutCopying();
+        RAbstractContainer layoutWidths = asAbstractContainer(layoutData[ViewPort.LAYOUT_WIDTHS]);
+        assert layoutWidths.getLength() == layoutSize.ncol : "inconsistent layout size with layout widths";
+        double reducedWidth = getReducedDimension(layoutWidths, npcWidths, relativeWidths, size.getWidth(), conversionCtx, true);
+
+        RAbstractContainer layoutHeights = asAbstractContainer(layoutData[ViewPort.LAYOUT_HEIGHTS]);
+        assert layoutHeights.getLength() == layoutSize.nrow : "inconsistent layout size with layout height";
+        double reducedHeight = getReducedDimension(layoutHeights, npcHeights, relativeHeights, size.getHeight(), conversionCtx, false);
+
+        // npcHeight (and npcWidth) has some 'holes' in them, at indexes with
+        // relativeHeights[index]==true, we will calculate the values for them now.
+        // Firstly allocate the respected widths/heights and calculate how much space remains
+        RList layoutAsList = asList(viewPort.getDataAt(ViewPort.VP_LAYOUT));
+        int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT));
+        int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying();
+        if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) {
+            double sumRelWidth = sumRelativeDimension(layoutSize, layoutWidths, relativeWidths, parentVPCtx, drawingCtx, true);
+            double sumRelHeight = sumRelativeDimension(layoutSize, layoutHeights, relativeHeights, parentVPCtx, drawingCtx, false);
+            double tempWidth = reducedWidth;
+            double tempHeight = reducedHeight;
+            double denom;
+            double mult;
+            // Determine whether aspect ratio of available space is bigger or smaller than
+            // aspect ratio of layout
+            if (tempHeight * sumRelWidth > sumRelHeight * tempWidth) {
+                denom = sumRelWidth;
+                mult = tempWidth;
+            } else {
+                denom = sumRelHeight;
+                mult = tempHeight;
+            }
+            for (int i = 0; i < layoutSize.ncol; i++) {
+                if (relativeWidths[i] && colRespected(respect, i, layoutRespectMat, layoutSize)) {
+                    /*
+                     * Special case of respect, but sumHeight = 0. Action is to allocate widths as
+                     * if unrespected. Ok to test == 0 because will only be 0 if all relative
+                     * heights are actually exactly 0.
+                     */
+                    if (sumRelHeight == 0) {
+                        denom = sumRelWidth;
+                        mult = tempWidth;
+                    }
+                    // Build a unit SEXP with a single value and no data
+                    npcWidths[i] = Unit.pureNullUnitValue(layoutWidths, i) / denom * mult;
+                    reducedWidth -= npcWidths[i];
+                }
+            }
+            for (int i = 0; i < layoutSize.nrow; i++) {
+                if (relativeHeights[i] && rowRespected(respect, i, layoutRespectMat, layoutSize)) {
+                    if (sumRelWidth == 0) {
+                        denom = sumRelHeight;
+                        mult = tempHeight;
+                    }
+                    npcHeights[i] = Unit.pureNullUnitValue(layoutHeights, i) / denom * mult;
+                    reducedHeight -= npcHeights[i];
+                }
+            }
+        } else if (respect > 0) {
+            for (int i = 0; i < layoutSize.ncol; i++) {
+                if (relativeWidths[i] && colRespected(respect, i, layoutRespectMat, layoutSize)) {
+                    npcWidths[i] = 0;
+                }
+            }
+            for (int i = 0; i < layoutSize.nrow; i++) {
+                if (relativeHeights[i] && rowRespected(respect, i, layoutRespectMat, layoutSize)) {
+                    npcHeights[i] = 0;
+                }
+            }
+        }
+
+        // Secondly, allocate remaining relative widths and heights in the remaining space
+        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, drawingCtx, parentVPCtx, true);
+        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, drawingCtx, parentVPCtx, false);
+
+        // Create the result
+        Object[] vpData = viewPort.getDataWithoutCopying();
+        vpData[ViewPort.PVP_WIDTHS] = RDataFactory.createDoubleVector(npcWidths, RDataFactory.COMPLETE_VECTOR);
+        vpData[ViewPort.PVP_HEIGHTS] = RDataFactory.createDoubleVector(npcHeights, RDataFactory.COMPLETE_VECTOR);
+    }
+
+    private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
+                    DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, drawingCtx, 1, 0);
+        double totalUnrespectedSize = 0;
+        if (reducedDim > 0) {
+            for (int i = 0; i < layoutSize.ncol; i++) {
+                if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
+                    totalUnrespectedSize += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
+                }
+            }
+        }
+        // set the remaining width/height to zero or to proportion of totalUnrespectedSize
+        for (int i = 0; i < layoutSize.ncol; i++) {
+            if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
+                npcItems[i] = 0;
+                if (totalUnrespectedSize > 0) {
+                    // if there was some with left, then totalUnrespectedSize contains sum of it
+                    npcItems[i] = reducedDim * unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth) / totalUnrespectedSize;
+                }
+            }
+        }
+    }
+
+    private boolean rowColRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
+        return isColumn ? colRespected(respected, respected, layoutRespectMat, layoutSize) : rowRespected(respected, row, layoutRespectMat, layoutSize);
+    }
+
+    private boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
+        if (respected == 1) {
+            return true;
+        }
+        for (int i = 0; i < layoutSize.ncol; i++) {
+            if (layoutRespectMat[i * layoutSize.nrow + row] != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean colRespected(int respected, int col, int[] layoutRespectMat, LayoutSize layoutSize) {
+        if (respected == 1) {
+            return true;
+        }
+        for (int i = 0; i < layoutSize.nrow; i++) {
+            if (layoutRespectMat[col * layoutSize.nrow + i] != 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private double sumRelativeDimension(LayoutSize layoutSize, RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, DrawingContext drawingCtx, boolean isWidth) {
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, drawingCtx, 0, 1);
+        double totalWidth = 0;
+        for (int i = 0; i < layoutSize.ncol; i++) {
+            if (relativeItems[i]) {
+                totalWidth += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
+            }
+        }
+        return totalWidth;
+    }
+
+    private double getReducedDimension(RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double initialSize, UnitConversionContext conversionCtx,
+                    boolean isWidth) {
+        double reducedSize = initialSize;
+        for (int i = 0; i < npcItems.length; i++) {
+            boolean currIsRel = isRelativeUnit.execute(layoutItems, i);
+            relativeItems[i] = currIsRel;
+            if (!currIsRel) {
+                npcItems[i] = unitsToInches.convertDimension(layoutItems, i, conversionCtx, isWidth);
+                reducedSize -= npcItems[i];
+            }
+        }
+        return reducedSize;
+    }
+
     private RAbstractDoubleVector castDoubleVector(Object obj) {
         return (RAbstractDoubleVector) castDoubleVector.execute(obj);
     }
@@ -144,7 +334,58 @@ class DoSetViewPort extends RBaseNode {
         try {
             children.put(RRuntime.asString(pushedVPDatum), pushedViewPort);
         } catch (PutException e) {
-            RInternalError.shouldNotReachHere("Cannot update children environment in a view port list");
+            throw RInternalError.shouldNotReachHere("Cannot update children environment in a view port list");
         }
     }
+
+    // Note: unlike the GnuR conterpart of this method, we expect the LayoutPos to have the NULL
+    // positions replaced with nrow/ncol already.
+    private ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) {
+        // unlike in GnuR, we maintain parent viewport widths/heights in inches like anything else
+        double[] widths = castDoubleVector(parentVP.getDataAt(ViewPort.PVP_WIDTHS)).materialize().getDataWithoutCopying();
+        double[] heights = castDoubleVector(parentVP.getDataAt(ViewPort.PVP_HEIGHTS)).materialize().getDataWithoutCopying();
+        double totalWidth = sum(widths, 0, pos.layoutSize.ncol);
+        double totalHeight = sum(heights, 0, pos.layoutSize.nrow);
+        double width = sum(widths, pos.colMin, pos.colMax - pos.colMin + 1);
+        double height = sum(heights, pos.rowMin, pos.rowMax - pos.rowMin + 1);
+        double left = parentSize.getWidth() * pos.layoutSize.hjust - totalWidth * pos.layoutSize.hjust + sum(widths, 0, pos.colMin - 1);
+        double bottom = parentSize.getHeight() * pos.layoutSize.vjust + (1 - pos.layoutSize.vjust) * totalHeight - sum(heights, 0, pos.rowMax + 1);
+        ViewPortLocation result = new ViewPortLocation();
+        result.width = newUnit(width, Unit.INCHES);
+        result.height = newUnit(height, Unit.INCHES);
+        result.x = newUnit(left, Unit.INCHES);
+        result.y = newUnit(bottom, Unit.INCHES);
+        result.hjust = result.vjust = 0;
+        return result;
+    }
+
+    private LayoutPos getLayoutPos(RList vp, RList parent) {
+        LayoutSize size = LayoutSize.fromViewPort(parent);
+        Object rowObj = vp.getDataAt(ViewPort.VP_VALIDLPOSROW);
+        int rowMin = 1;
+        int rowMax = size.nrow;
+        if (rowObj instanceof RAbstractIntVector) {
+            rowMin = ((RAbstractIntVector) rowObj).getDataAt(0);
+            rowMax = ((RAbstractIntVector) rowObj).getDataAt(1);
+            if (rowMin < 1 || rowMax > size.nrow) {
+                throw error(Message.GENERIC, "invalid 'layout.pos.row'");
+            }
+        }
+        Object colObj = vp.getDataAt(ViewPort.VP_VALIDLPOSCOL);
+        int colMin = 1;
+        int colMax = size.ncol;
+        if (colObj instanceof RAbstractIntVector) {
+            colMin = ((RAbstractIntVector) colObj).getDataAt(0);
+            colMax = ((RAbstractIntVector) colObj).getDataAt(1);
+            if (colMin < 1 || colMax > size.ncol) {
+                throw error(Message.GENERIC, "invalid 'layout.pos.row'");
+            }
+        }
+        // the indexes in LayoutPos are to be interpreted as 0-based
+        return new LayoutPos(colMin - 1, colMax - 1, rowMin - 1, rowMax - 1, size);
+    }
+
+    private static boolean isNull(Object value) {
+        return value == null || value == RNull.instance;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
index 4b556280fc..b9d4070415 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
@@ -25,7 +25,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 /**
  * Contains static method related to edge detection for bounds calculations.
  */
-public final class EdgeDetection {
+final class EdgeDetection {
     private EdgeDetection() {
         // only static members
     }
@@ -34,7 +34,7 @@ public final class EdgeDetection {
      * Do two lines intersect? Algorithm from Paul Bourke
      * (http://www.swin.edu.au/astronomy/pbourke/geometry/lineline2d/index.html)
      */
-    static boolean linesIntersect(double x1, double x2, double x3, double x4,
+    private static boolean linesIntersect(double x1, double x2, double x3, double x4,
                     double y1, double y2, double y3, double y4) {
         double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
         double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3));
@@ -45,30 +45,30 @@ public final class EdgeDetection {
                 // If the lines are vertical ...
                 if (x1 == x2) {
                     // Compare y-values
-                    if (!((y1 < y3 && fmax2(y1, y2) < fmin2(y3, y4)) ||
-                                    (y3 < y1 && fmax2(y3, y4) < fmin2(y1, y2))))
+                    if (!((y1 < y3 && fmax2(y1, y2) < fmin2(y3, y4)) || (y3 < y1 && fmax2(y3, y4) < fmin2(y1, y2)))) {
                         return true;
+                    }
                 } else {
                     // Compare x-values
-                    if (!((x1 < x3 && fmax2(x1, x2) < fmin2(x3, x4)) ||
-                                    (x3 < x1 && fmax2(x3, x4) < fmin2(x1, x2))))
+                    if (!((x1 < x3 && fmax2(x1, x2) < fmin2(x3, x4)) || (x3 < x1 && fmax2(x3, x4) < fmin2(x1, x2)))) {
                         return true;
+                    }
                 }
             }
-        }
-        // ... otherwise, calculate where the lines intersect ...
-        else {
+        } else {
+            // ... otherwise, calculate where the lines intersect ...
             double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3));
             ua = ua / denom;
             ub = ub / denom;
             // Check for overlap
-            if ((ua > 0 && ua < 1) && (ub > 0 && ub < 1))
+            if ((ua > 0 && ua < 1) && (ub > 0 && ub < 1)) {
                 return true;
+            }
         }
         return false;
     }
 
-    static boolean edgesIntersect(double x1, double x2, double y1, double y2, Rectangle r) {
+    private static boolean edgesIntersect(double x1, double x2, double y1, double y2, Rectangle r) {
         return linesIntersect(x1, x2, r.x[0], r.x[1], y1, y2, r.y[0], r.y[1]) ||
                         linesIntersect(x1, x2, r.x[1], r.x[2], y1, y2, r.y[1], r.y[2]) ||
                         linesIntersect(x1, x2, r.x[2], r.x[3], y1, y2, r.y[2], r.y[3]) ||
@@ -126,11 +126,11 @@ public final class EdgeDetection {
         // Special case zero-width or zero-height
         if (fabs(xmin - xmax) < 1e-6) {
             double resultY = theta == 90 ? ymax : theta == 270 ? ymin : ym;
-            return new Point(xmin, ymin);
+            return new Point(xmin, resultY);
         }
         if (fabs(ymin - ymax) < 1e-6) {
-            double resultY = theta == 0 ? xmax : theta == 180 ? xmin : xm;
-            return new Point(ymin, resultY);
+            double resultX = theta == 0 ? xmax : theta == 180 ? xmin : xm;
+            return new Point(resultX, ymin);
         }
 
         /*
@@ -208,7 +208,7 @@ public final class EdgeDetection {
         public final double[] x;
         public final double[] y;
 
-        public Rectangle(Point p1, Point p2, Point p3, Point p4) {
+        Rectangle(Point p1, Point p2, Point p3, Point p4) {
             x = new double[]{p1.x, p2.x, p3.x, p4.x};
             y = new double[]{p1.y, p2.y, p3.y, p4.y};
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index d714b28ef4..c17dbe5d15 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -14,15 +14,12 @@ package com.oracle.truffle.r.library.fastrGrid;
 import java.util.Arrays;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 /**
  * In the context of grid package, GPar is a list that contains the parameters for the drawing, like
@@ -126,29 +123,13 @@ public final class GPar {
 
         @Override
         public double getFontSize() {
-            return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
+            return GridUtils.asDouble(data[GP_FONTSIZE]) * GridUtils.asDouble(data[GP_CEX]);
         }
 
         @Override
         public double getLineHeight() {
-            return asDouble(data[GP_LINEHEIGHT]);
+            return GridUtils.asDouble(data[GP_LINEHEIGHT]);
         }
 
-        private static double asDouble(Object val) {
-            if (val instanceof Double) {
-                return (double) val;
-            } else if (val instanceof RAbstractDoubleVector) {
-                if (((RAbstractDoubleVector) val).getLength() > 0) {
-                    return ((RAbstractDoubleVector) val).getDataAt(0);
-                }
-            } else if (val instanceof Integer) {
-                return (int) val;
-            } else if (val instanceof RAbstractIntVector) {
-                if (((RAbstractIntVector) val).getLength() > 0) {
-                    return ((RAbstractIntVector) val).getDataAt(0);
-                }
-            }
-            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value in GPar.");
-        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 72a3c45c74..5d840cbf68 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -43,6 +44,12 @@ public final class GridState {
         currentDevice.initDrawingContext(GPar.asDrawingContext(gpar));
     }
 
+    public static DrawingContext getInitialGPar(GridDevice device) {
+        DrawingContext result = GPar.asDrawingContext(GPar.createNew());
+        device.initDrawingContext(result);
+        return result;
+    }
+
     public RList getGpar() {
         assert gridEnv != null : "GridState not initialized";
         return gpar;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index f60dc1dff8..8d390d72e4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -154,8 +154,14 @@ public final class GridTextNode extends RBaseNode {
                     xmax = fmax(xmax, trect.x);
                     ymin = fmin(ymin, trect.y);
                     ymax = fmax(ymax, trect.y);
+                    double[] xxx = new double[4];
+                    double[] yyy = new double[4];
+                    for (int j = 0; j < 4; j++) {
+                        xxx[j] = trect.x[3 - j];
+                        yyy[j] = trect.y[3 - j];
+                    }
                     // Calculate edgex and edgey for case where this is the only rect
-                    edge = EdgeDetection.polygonEdge(trect.x, trect.y, 4, theta);
+                    edge = EdgeDetection.polygonEdge(xxx, yyy, 4, theta);
                     ntxt++;
                 }
             }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index b6acae809c..782150456a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -16,7 +16,16 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2;
 
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RDouble;
+import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 final class GridUtils {
@@ -67,4 +76,82 @@ final class GridUtils {
         }
         return result;
     }
+
+    static boolean hasRClass(RAttributable obj, String clazz) {
+        RStringVector classAttr = obj.getClassAttr();
+        if (classAttr == null) {
+            return false;
+        }
+        for (int i = 0; i < classAttr.getLength(); i++) {
+            if (classAttr.getDataAt(i).equals(clazz)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static RList asList(Object value) {
+        if (!(value instanceof RList)) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Expected list");
+        }
+        return (RList) value;
+    }
+
+    static double asDouble(Object val) {
+        if (val instanceof Double) {
+            return (double) val;
+        } else if (val instanceof RAbstractDoubleVector) {
+            if (((RAbstractDoubleVector) val).getLength() > 0) {
+                return ((RAbstractDoubleVector) val).getDataAt(0);
+            }
+        } else if (val instanceof Integer) {
+            return (int) val;
+        } else if (val instanceof RAbstractIntVector) {
+            if (((RAbstractIntVector) val).getLength() > 0) {
+                return ((RAbstractIntVector) val).getDataAt(0);
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value " + val.getClass().getSimpleName());
+    }
+
+    static RAbstractIntVector asIntVector(Object value) {
+        if (value instanceof Integer) {
+            return RInteger.valueOf((Integer) value);
+        } else if (value instanceof RAbstractIntVector) {
+            return (RAbstractIntVector) value;
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + value.getClass().getSimpleName());
+    }
+
+    public static RAbstractDoubleVector asDoubleVector(Object obj) {
+        if (obj instanceof Double) {
+            return RDouble.valueOf((Double) obj);
+        } else if (obj instanceof RAbstractDoubleVector) {
+            return (RAbstractDoubleVector) obj;
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double value " + obj.getClass().getSimpleName());
+    }
+
+    static RAbstractContainer asAbstractContainer(Object value) {
+        if (value instanceof Integer) {
+            return RInteger.valueOf((Integer) value);
+        } else if (value instanceof Double) {
+            return RDouble.valueOf((Double) value);
+        } else if (value instanceof RAbstractContainer) {
+            return (RAbstractContainer) value;
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non abstract container type " + value.getClass().getSimpleName());
+    }
+
+    static double sum(double[] values) {
+        return sum(values, 0, values.length);
+    }
+
+    static double sum(double[] values, int from, int length) {
+        double result = 0;
+        for (int i = 0; i < length; i++) {
+            result += values[from + i];
+        }
+        return result;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 6ddbce8084..04f325f485 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -13,24 +13,22 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.Unit.NATIVE;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.NPC;
-import static com.oracle.truffle.r.library.fastrGrid.Unit.VALID_UNIT_ATTR;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.isArithmeticUnit;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.isListUnit;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
@@ -38,16 +36,13 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
     @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
-    private final ValueProfile unitToProfile = ValueProfile.createEqualityProfile();
-    private final ValueProfile axisToProfile = ValueProfile.createEqualityProfile();
-    private final ValueProfile axisFromProfile = ValueProfile.createEqualityProfile();
 
     static {
         Casts casts = new Casts(LConvert.class);
         casts.arg(0).mustBe(abstractVectorValue());
-        casts.arg(1).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(3)));
-        casts.arg(2).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(3)));
-        casts.arg(3).mustBe(numericValue()).asIntegerVector().findFirst().mustBe(gte(0).and(lte(Unit.LAST_NORMAL_UNIT)));
+        casts.arg(1).mustBe(numericValue()).asIntegerVector();
+        casts.arg(2).mustBe(numericValue()).asIntegerVector();
+        casts.arg(3).mustBe(numericValue()).asIntegerVector();
     }
 
     public static LConvert create() {
@@ -55,10 +50,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doConvert(RAbstractVector units, int axisFromIn, int axisToIn, int unitToIn) {
-        int axisFrom = axisFromProfile.profile(axisFromIn);
-        int axisTo = axisToProfile.profile(axisToIn);
-        int unitTo = unitToProfile.profile(unitToIn);
+    Object doConvert(RAbstractVector units, RAbstractIntVector axisFromVec, RAbstractIntVector axisToVec, RAbstractIntVector unitToVec) {
 
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
@@ -72,16 +64,41 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         int length = unitLength.execute(units);
         double[] result = new double[length];
 
-        int fromUnitId = RRuntime.asInteger(units.getAttr(VALID_UNIT_ATTR));
-        boolean relativeUnits = isRelative(unitTo) || isRelative(fromUnitId);
-        if ((vpTransform.size.getHeight() < 1e-6 || vpTransform.size.getWidth() < 1e-6) && relativeUnits) {
-            throw RInternalError.unimplemented("L_convert: relative units with close to zero width or height");
-        }
+        RAbstractIntVector unitIds = GridUtils.asIntVector(units.getAttr(Unit.VALID_UNIT_ATTR));
+        boolean fromUnitIsSimple = !isArithmeticUnit(units) && !isListUnit(units);
 
         for (int i = 0; i < length; i++) {
-            double inches = toInches(units, i, axisFrom, conversionCtx);
-            double vpSize = isXAxis(axisTo) ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
-            result[i] = Unit.convertFromInches(inches, unitTo, vpSize, vpContext.xscalemin, vpContext.xscalemax, isDimension(axisTo), drawingCtx);
+            // scalar values used in current iteration
+            int axisFrom = axisFromVec.getDataAt(i % axisFromVec.getLength());
+            int axisTo = axisToVec.getDataAt(i % axisToVec.getLength());
+            boolean compatibleAxes = axisFrom == axisTo ||
+                            (axisFrom == 0 && axisTo == 2) ||
+                            (axisFrom == 2 && axisTo == 0) ||
+                            (axisFrom == 1 && axisTo == 3) ||
+                            (axisFrom == 3 && axisTo == 1);
+            double vpToSize = isXAxis(axisTo) ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
+            double vpFromSize = isXAxis(axisFrom) ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
+            int unitTo = unitToVec.getDataAt(i % unitToVec.getLength());
+            int fromUnitId = unitIds.getDataAt(i % unitIds.getLength());
+
+            // actual conversion:
+            // if the units are both relative, we are converting compatible axes and the vpSize for
+            // 'from' axis is small, we will not convert through inches, but directly to avoid
+            // divide by zero, but still do something useful
+            boolean bothRelative = isRelative(unitTo) && isRelative(fromUnitId);
+            boolean realativeConversion = bothRelative && fromUnitIsSimple && compatibleAxes && vpFromSize < 1e-6;
+            if (realativeConversion) {
+                // if the unit is not "unit.arithmetic" or "unit.list", it must be double vector
+                RAbstractDoubleVector simpleUnits = (RAbstractDoubleVector) units;
+                double fromValue = simpleUnits.getDataAt(i % simpleUnits.getLength());
+                result[i] = transformFromNPC(tranfromToNPC(fromValue, fromUnitId, axisFrom, vpContext), unitTo, axisTo, vpContext);
+            } else {
+                double inches = toInches(units, i, axisFrom, conversionCtx);
+                boolean isX = isXAxis(axisTo);
+                double scalemin = isX ? vpContext.xscalemin : vpContext.yscalemin;
+                double scalemax = isX ? vpContext.xscalemax : vpContext.yscalemax;
+                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, isDimension(axisTo), drawingCtx);
+            }
         }
 
         return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
@@ -105,6 +122,38 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         return inches;
     }
 
+    private static double tranfromToNPC(double value, int fromUnitId, int axisFrom, ViewPortContext vpContext) {
+        if (fromUnitId == Unit.NPC) {
+            return value;
+        }
+        assert fromUnitId == Unit.NATIVE : "relative conversion should only happen when units are NPC or NATIVE";
+        boolean isX = isXAxis(axisFrom);
+        double min = isX ? vpContext.xscalemin : vpContext.yscalemin;
+        double max = isX ? vpContext.xscalemax : vpContext.yscalemax;
+        if (isDimension(axisFrom)) {
+            return value / (max - min);
+        } else {
+            return (value - min) / (max - min);
+        }
+    }
+
+    private static double transformFromNPC(double value, int unitTo, int axisTo, ViewPortContext vpContext) {
+        if (unitTo == Unit.NPC) {
+            return value;
+        }
+        assert unitTo == Unit.NATIVE : "relative conversion should only happen when units are NPC or NATIVE";
+        boolean isX = isXAxis(axisTo);
+        double min = isX ? vpContext.xscalemin : vpContext.yscalemin;
+        double max = isX ? vpContext.xscalemax : vpContext.yscalemax;
+        if (isDimension(axisTo)) {
+            return value * (max - min);
+        } else {
+            return min + value * (max - min);
+        }
+    }
+
+    // Note: this is not relative in the same sense as IsRelativeUnitNode. The later checks for
+    // special NULL unit used only in layouting.
     private static boolean isRelative(int unitId) {
         return unitId == NPC || unitId == NATIVE;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
index c0bd6650a5..38388451db 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
index 87a5269c34..0f429081b6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -11,9 +11,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
@@ -22,7 +21,6 @@ import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTrans
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -34,7 +32,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  * {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode}.
  */
 public abstract class LLines extends RExternalBuiltinNode.Arg4 {
-    @Child private CastNode toIntVector = newCastBuilder().mustBe(integerValue()).boxPrimitive().asIntegerVector().buildCastNode();
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
     @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
@@ -66,7 +63,7 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
         RAbstractIntVector[] unitIndexesList = new RAbstractIntVector[lengths.getLength()];
         int maxIndexesLen = 0;
         for (int i = 0; i < lengths.getLength(); i++) {
-            unitIndexesList[i] = (RAbstractIntVector) toIntVector.execute(lengths.getDataAt(i));
+            unitIndexesList[i] = asIntVector(lengths.getDataAt(i));
             maxIndexesLen = Math.max(maxIndexesLen, unitIndexesList[i].getLength());
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
index a6a68509ef..ba2c513520 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
@@ -45,7 +45,7 @@ public final class Point {
         return justify(size.getWidth(), size.getHeight(), hjust, vjust);
     }
 
-    public Point justify(double width, double height, double hjust, double vjust) {
+    private Point justify(double width, double height, double hjust, double vjust) {
         return new Point(GridUtils.justify(x, width, hjust), GridUtils.justify(y, height, vjust));
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
new file mode 100644
index 0000000000..7f6b3f18ea
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RArguments;
+import com.oracle.truffle.r.runtime.RInternalCode;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+
+/**
+ * Allows to call arbitrary R function from {@code fastrGrid.R} source.
+ */
+class RGridCodeCall extends Node {
+    private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("<fastrGrid.R tmp frame>");
+    @Child private RInternalCodeBuiltinNode child;
+
+    RGridCodeCall(String functionName) {
+        child = new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(GPar.class, "fastrGrid.R"), functionName);
+    }
+
+    static {
+        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<fastrGrid.R tmp frame>", emptyFrameDescriptor);
+    }
+
+    public Object call(Object arg1) {
+        return execute(new RArgsValuesAndNames(new Object[]{arg1}, ArgumentsSignature.empty(1)));
+    }
+
+    public Object execute(RArgsValuesAndNames args) {
+        Object[] dummyFrameArgs = RArguments.createUnitialized();
+        VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor);
+        return child.call(dummyFrame, args);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 2dc08f5b5c..06952fdba7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -11,26 +11,47 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.hasRClass;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum;
 import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
-import java.util.function.Function;
+import java.util.function.BiFunction;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitLengthNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -43,17 +64,17 @@ public class Unit {
     static final String VALID_UNIT_ATTR = "valid.unit";
 
     public static final int NPC = 0;
-    public static final int CM = 1;
+    private static final int CM = 1;
     public static final int INCHES = 2;
-    public static final int LINES = 3;
+    private static final int LINES = 3;
     public static final int NATIVE = 4;
-    public static final int NULL = 5; /* only used in layout specifications (?) */
-    public static final int SNPC = 6;
-    public static final int MM = 7;
+    private static final int NULL = 5; /* only used in layout specifications */
+    private static final int SNPC = 6;
+    private static final int MM = 7;
     /*
      * Some units based on TeX's definition thereof
      */
-    public static final int POINTS = 8; /* 72.27 pt = 1 in */
+    private static final int POINTS = 8; /* 72.27 pt = 1 in */
     public static final int PICAS = 9; /* 1 pc = 12 pt */
     public static final int BIGPOINTS = 10; /* 72 bp = 1 in */
     public static final int DIDA = 11; /* 1157 dd = 1238 pt */
@@ -62,29 +83,37 @@ public class Unit {
     /*
      * Some units which require an object to query for a value.
      */
-    public static final int STRINGWIDTH = 14;
-    public static final int STRINGHEIGHT = 15;
+    private static final int STRINGWIDTH = 14;
+    private static final int STRINGHEIGHT = 15;
     public static final int STRINGASCENT = 16;
     public static final int STRINGDESCENT = 17;
     /*
-     * public static final int LINES now means multiples of the line height. This is multiples of
-     * the font size.
+     * LINES now means multiples of the line height. This is multiples of the font size.
      */
-    public static final int CHAR = 18;
-    public static final int GROBX = 19;
-    public static final int GROBY = 20;
-    public static final int GROBWIDTH = 21;
-    public static final int GROBHEIGHT = 22;
+    private static final int CHAR = 18;
+    private static final int GROBX = 19;
+    private static final int GROBY = 20;
+    private static final int GROBWIDTH = 21;
+    private static final int GROBHEIGHT = 22;
     public static final int GROBASCENT = 23;
-    public static final int GROBDESCENT = 24;
-    public static final int LAST_NORMAL_UNIT = GROBDESCENT;
+    private static final int GROBDESCENT = 24;
+    private static final int LAST_NORMAL_UNIT = GROBDESCENT;
     /*
      * No longer used
      */
     private static final int MYLINES = 103;
-    public static final int MYCHAR = 104;
-    public static final int MYSTRINGWIDTH = 105;
-    public static final int MYSTRINGHEIGHT = 106;
+    private static final int MYCHAR = 104;
+    private static final int MYSTRINGWIDTH = 105;
+    private static final int MYSTRINGHEIGHT = 106;
+
+    // null layout arithmetic mode
+    private static final int L_adding = 1;
+    private static final int L_subtracting = 2;
+    private static final int L_summing = 3;
+    private static final int L_plain = 4;
+    private static final int L_maximising = 5;
+    private static final int L_minimising = 6;
+    private static final int L_multiplying = 7;
 
     private static final double CM_IN_INCH = 2.54;
 
@@ -96,6 +125,15 @@ public class Unit {
         return cm / CM_IN_INCH;
     }
 
+    public static RAbstractDoubleVector newUnit(double value, int unitId) {
+        assert unitId > 0 && unitId <= LAST_NORMAL_UNIT;
+        RDoubleVector result = RDataFactory.createDoubleVector(new double[]{value}, RDataFactory.COMPLETE_VECTOR);
+        result.setClassAttr(RDataFactory.createStringVectorFromScalar("unit"));
+        result.setAttr("valid.unit", unitId);
+        result.setAttr("data", RNull.instance);
+        return result;
+    }
+
     public static UnitLengthNode createLengthNode() {
         return UnitLengthNode.create();
     }
@@ -107,8 +145,8 @@ public class Unit {
     static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
         switch (unitId) {
             case NATIVE:
-                double tmp = isDimension ? value : (value + scalemin);
-                return (tmp * (scalemax - scalemin)) / vpSize;
+                double addition = isDimension ? 0 : scalemin;
+                return addition + (value / vpSize) * (scalemax - scalemin);
             case NPC:
                 return value / vpSize;
             case CM:
@@ -139,8 +177,10 @@ public class Unit {
         }
     }
 
-    static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
+    private static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx) {
         switch (unitId) {
+            case INCHES:
+                return value;
             case NATIVE:
                 double tmp = isDimension ? value : (value - scalemin);
                 return (tmp / (scalemax - scalemin)) * vpSize;
@@ -152,15 +192,89 @@ public class Unit {
                 return value / CM_IN_INCH;
             case MM:
                 return value / (CM_IN_INCH * 10);
+            case CHAR:
+            case MYCHAR:
+                return (value * drawingCtx.getFontSize()) / INCH_TO_POINTS_FACTOR;
             case LINES:
             case MYLINES:
                 return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
-
+            case NULL:
+                return evaluateNullUnit(value, vpSize, nullLMode, nullAMode);
             default:
                 throw RInternalError.unimplemented("unit type " + unitId + " in convertToInches");
         }
     }
 
+    private static double evaluateNullUnit(double value, double vpSize, int nullLMode, int nullAMode) {
+        if (nullLMode > 0) {
+            return value;
+        }
+        switch (nullAMode) {
+            case L_plain:
+            case L_adding:
+            case L_subtracting:
+            case L_summing:
+            case L_multiplying:
+            case L_maximising:
+                return 0;
+            case L_minimising:
+                return vpSize;  // Note: GnuR has vpSize in "cm", so this will be in "cm"
+                                // too, does it matter?
+        }
+        return value;
+    }
+
+    static boolean isListUnit(Object unit) {
+        return unit instanceof RList && hasRClass((RAttributable) unit, "unit.list");
+    }
+
+    static boolean isArithmeticUnit(Object unit) {
+        return unit instanceof RList && hasRClass((RAttributable) unit, "unit.arithmetic");
+    }
+
+    private static boolean isGrobUnit(int unitId) {
+        return unitId >= GROBX && unitId <= GROBDESCENT;
+    }
+
+    static double pureNullUnitValue(RAbstractContainer unit, int index) {
+        // TODO: convert to unit visitor
+        if (unit instanceof RAbstractDoubleVector) {
+            RAbstractDoubleVector simpleUnit = (RAbstractDoubleVector) unit;
+            return simpleUnit.getDataAt(index % simpleUnit.getLength());
+        } else if (isListUnit(unit)) {
+            return pureNullUnitValue((RAbstractContainer) ((RList) unit).getDataAt(index % unit.getLength()), 0);
+        } else if (isArithmeticUnit(unit)) {
+            ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit((RList) unit);
+            switch (expr.op) {
+                case "+":
+                    return pureNullUnitValue(expr.arg1, index) + pureNullUnitValue(expr.arg2, index);
+                case "-":
+                    return pureNullUnitValue(expr.arg1, index) - pureNullUnitValue(expr.arg2, index);
+                case "*":
+                    return asDouble(expr.arg1) * pureNullUnitValue(expr.arg2, index);
+                case "min":
+                case "max":
+                case "sum":
+                    double[] values = new double[expr.arg1.getLength()];
+                    for (int i = 0; i < values.length; i++) {
+                        values[i] = pureNullUnitValue(expr.arg1, i);
+                    }
+                    switch (expr.op) {
+                        case "min":
+                            return fmin(Double.MAX_VALUE, values);
+                        case "max":
+                            return fmax(Double.MIN_VALUE, values);
+                        case "sum":
+                            return sum(values);
+                        default:
+                            throw RInternalError.shouldNotReachHere("unexpected arithmetic unit operation");
+                    }
+            }
+
+        }
+        throw RInternalError.shouldNotReachHere("unexpected arithmetic unit type");
+    }
+
     private static final class ArithmeticUnit {
         public final String op;
         public final RAbstractContainer arg1;
@@ -172,6 +286,27 @@ public class Unit {
             this.arg2 = arg2;
         }
 
+        static ArithmeticUnit asArithmeticUnit(RList unit) {
+            if (unit.getLength() <= 1) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid arithmetic unit (length <= 1).");
+            }
+            // Note: the operator is usually of type character, however in the R code, grid compares
+            // it to symbols, e.g. `x`. Our implementation here should work with symbols too thanks
+            // to the asStringVector() conversion.
+            String op = RRuntime.asString(unit.getDataAt(0));
+            RAbstractContainer arg1 = asAbstractContainer(unit.getDataAt(1));
+            if (op.equals("+") || op.equals("-") || op.equals("*")) {
+                if (unit.getLength() != 3) {
+                    throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid arithmetic unit with binary operator and missing operand.");
+                }
+                return new ArithmeticUnit(op, arg1, asAbstractContainer(unit.getDataAt(2)));
+            }
+            if (op.equals("max") || op.equals("min") || op.equals("sum")) {
+                return new ArithmeticUnit(op, arg1, null);
+            }
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected unit operator " + op);
+        }
+
         public boolean isBinary() {
             return arg2 != null;
         }
@@ -180,8 +315,6 @@ public class Unit {
     abstract static class UnitNodeBase extends RBaseNode {
         @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode("unit.arithmetic");
         @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode("unit.list");
-        @Child private CastNode stringCast;
-        @Child private CastNode abstractContainerCast;
 
         boolean isSimple(Object obj) {
             return !inheritsArithmeticCheckNode.execute(obj) && !inheritsUnitListCheckNode.execute(obj);
@@ -194,34 +327,36 @@ public class Unit {
         boolean isUnitList(Object obj) {
             return inheritsUnitListCheckNode.execute(obj);
         }
+    }
 
-        ArithmeticUnit asArithmeticUnit(RList unit) {
-            if (unit.getLength() <= 1) {
-                throw error(Message.GENERIC, "Invalid arithmetic unit (length <= 1).");
-            }
-            if (stringCast == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                stringCast = newCastBuilder().asStringVector().findFirst().buildCastNode();
-            }
-            if (abstractContainerCast == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                abstractContainerCast = newCastBuilder().mustBe(abstractVectorValue()).boxPrimitive().buildCastNode();
-            }
-            // Note: the operator is usually of type character, however in the R code, grid compares
-            // it to symbols, e.g. `x`. Our implementation here should work with symbols too thanks
-            // to the asStringVector() conversion.
-            String op = (String) stringCast.execute(unit.getDataAt(0));
-            RAbstractContainer arg1 = (RAbstractContainer) abstractContainerCast.execute(unit.getDataAt(1));
-            if (op.equals("+") || op.equals("-") || op.equals("*")) {
-                if (unit.getLength() != 3) {
-                    throw error(Message.GENERIC, "Invalid arithmetic unit with binary operator and missing operand.");
-                }
-                return new ArithmeticUnit(op, arg1, (RAbstractContainer) abstractContainerCast.execute(unit.getDataAt(2)));
-            }
-            if (op.equals("max") || op.equals("min") || op.equals("sum")) {
-                return new ArithmeticUnit(op, arg1, null);
+    public static final class UnitUnitIdNode extends Node {
+        @Child private GetFixedAttributeNode getValidUnitsAttr = GetFixedAttributeNode.create(VALID_UNIT_ATTR);
+
+        public int execute(RAbstractContainer unit, int index) {
+            RAbstractIntVector validUnits = asIntVector(getValidUnitsAttr.execute(unit));
+            return validUnits.getDataAt(index % validUnits.getLength());
+        }
+
+        public static UnitUnitIdNode create() {
+            return new UnitUnitIdNode();
+        }
+    }
+
+    public static final class IsRelativeUnitNode extends UnitNodeBase {
+        @Child private RGridCodeCall isPureNullCall = new RGridCodeCall("isPureNullUnit");
+
+        public boolean execute(Object unit, int index) {
+            // Note: converting 0-based java index to 1-based R index
+            Object result = isPureNullCall.execute(new RArgsValuesAndNames(new Object[]{unit, index + 1}, ArgumentsSignature.empty(2)));
+            byte resultByte;
+            if (result instanceof Byte) {
+                resultByte = (Byte) result;
+            } else if (result instanceof RAbstractLogicalVector) {
+                resultByte = ((RAbstractLogicalVector) result).getDataAt(0);
+            } else {
+                throw RInternalError.shouldNotReachHere("unexpected result type form isPuteNullUnit");
             }
-            throw error(Message.GENERIC, "Unexpected unit operator " + op);
+            return RRuntime.fromLogical(resultByte);
         }
     }
 
@@ -244,30 +379,37 @@ public class Unit {
         @Specialization(guards = "isArithmetic(list)")
         int doArithmetic(RList list,
                         @Cached("create()") UnitLengthNode recursiveLen) {
-            ArithmeticUnit arithmeticUnit = asArithmeticUnit(list);
+            ArithmeticUnit arithmeticUnit = ArithmeticUnit.asArithmeticUnit(list);
             if (arithmeticUnit.isBinary()) {
                 return Math.max(recursiveLen.execute(arithmeticUnit.arg1), recursiveLen.execute(arithmeticUnit.arg2));
             }
             return 1;   // op is max, min, sum
         }
-
-        static CastNode createStringCast() {
-            return newCastBuilder().asStringVector().findFirst().buildCastNode();
-        }
     }
 
     /**
-     * Wraps the data necessary for converting a unit to another unit.
+     * Wraps the data necessary for converting a unit to another unit. Note: {@code nullLMode} and
+     * {@code nullAMode} is only used for converting 'NULL' units and is only explicitly set when
+     * calculating layout. When e.g. drawing or calculating bounds, both should have default zero
+     * value.
      */
     public static final class UnitConversionContext {
         public final Size viewPortSize;
         public final ViewPortContext viewPortContext;
         public final DrawingContext drawingContext;
+        public final int nullLayoutMode;
+        public final int nullArithmeticMode;
 
         public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, DrawingContext drawingContext) {
+            this(viewPortSize, viewPortContext, drawingContext, 0, 0);
+        }
+
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, DrawingContext drawingContext, int nullLMode, int nullAMode) {
             this.viewPortSize = viewPortSize;
             this.viewPortContext = viewPortContext;
             this.drawingContext = drawingContext;
+            this.nullLayoutMode = nullLMode;
+            this.nullArithmeticMode = nullAMode;
         }
     }
 
@@ -276,73 +418,89 @@ public class Unit {
      * interpreted as cyclic.
      */
     public abstract static class UnitToInchesNode extends UnitNodeBase {
-        @Child private CastNode castUnitId = newCastBuilder().mustBe(numericValue()).asIntegerVector().findFirst().buildCastNode();
-        @Child private CastNode castDoubleVec = newCastBuilder().mustBe(numericValue()).boxPrimitive().asDoubleVector().buildCastNode();
+        @Child GrobUnitToInches grobUnitToInches = new GrobUnitToInches();
 
         public static UnitToInchesNode create() {
             return UnitToInchesNodeGen.create();
         }
 
-        public double convertX(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
-            return execute(vector, index, conversionCtx.viewPortSize.getWidth(), conversionCtx.viewPortContext.xscalemin, conversionCtx.viewPortContext.xscalemax, false, conversionCtx.drawingContext);
+        public double convertX(RAbstractContainer vector, int index, UnitConversionContext ctx) {
+            return execute(vector, index, ctx.viewPortSize.getWidth(), ctx.viewPortContext.xscalemin, ctx.viewPortContext.xscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, false,
+                            ctx.drawingContext);
+        }
+
+        public double convertY(RAbstractContainer vector, int index, UnitConversionContext ctx) {
+            return execute(vector, index, ctx.viewPortSize.getHeight(), ctx.viewPortContext.yscalemin, ctx.viewPortContext.yscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, false,
+                            ctx.drawingContext);
         }
 
-        public double convertY(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
-            return execute(vector, index, conversionCtx.viewPortSize.getHeight(), conversionCtx.viewPortContext.yscalemin, conversionCtx.viewPortContext.yscalemax, false,
-                            conversionCtx.drawingContext);
+        public double convertWidth(RAbstractContainer vector, int index, UnitConversionContext ctx) {
+            return execute(vector, index, ctx.viewPortSize.getWidth(), ctx.viewPortContext.xscalemin, ctx.viewPortContext.xscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, true,
+                            ctx.drawingContext);
         }
 
-        public double convertWidth(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
-            return execute(vector, index, conversionCtx.viewPortSize.getWidth(), conversionCtx.viewPortContext.xscalemin, conversionCtx.viewPortContext.xscalemax, true, conversionCtx.drawingContext);
+        public double convertHeight(RAbstractContainer vector, int index, UnitConversionContext ctx) {
+            return execute(vector, index, ctx.viewPortSize.getHeight(), ctx.viewPortContext.yscalemin, ctx.viewPortContext.yscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, true,
+                            ctx.drawingContext);
         }
 
-        public double convertHeight(RAbstractContainer vector, int index, UnitConversionContext conversionCtx) {
-            return execute(vector, index, conversionCtx.viewPortSize.getHeight(), conversionCtx.viewPortContext.yscalemin, conversionCtx.viewPortContext.yscalemax, true, conversionCtx.drawingContext);
+        public double convertDimension(RAbstractContainer vector, int index, UnitConversionContext ctx, boolean isWidth) {
+            return isWidth ? convertWidth(vector, index, ctx) : convertHeight(vector, index, ctx);
         }
 
-        public abstract double execute(RAbstractContainer vector, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx);
+        public abstract double execute(RAbstractContainer vector, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension,
+                        DrawingContext drawingCtx);
 
         @Specialization(guards = "isSimple(value)")
-        double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
-            int unitId = (Integer) castUnitId.execute(value.getAttr(VALID_UNIT_ATTR));
-            RAbstractDoubleVector vector = (RAbstractDoubleVector) castDoubleVec.execute(value);
-            return convertToInches(vector.getDataAt(index % vector.getLength()), unitId, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+        double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx,
+                        @Cached("createAsDoubleCast()") CastNode asDoubleCast,
+                        @Cached("create()") UnitUnitIdNode unitUnitId) {
+            int unitId = unitUnitId.execute(value, index);
+            RAbstractDoubleVector vector = (RAbstractDoubleVector) asDoubleCast.execute(value);
+            double scalarValue = vector.getDataAt(index % vector.getLength());
+            if (isGrobUnit(unitId)) {
+                RList grobList = asList(vector.getAttr("data"));
+                return grobUnitToInches.execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), nullLMode, nullAMode);
+            }
+            return convertToInches(scalarValue, unitId, vpSize, scalemin, scalemax, nullLMode, nullAMode, isDimension, drawingCtx);
         }
 
         @Specialization(guards = "isUnitList(value)")
-        double doList(RList value, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx,
+        double doList(RList value, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx,
                         @Cached("create()") UnitToInchesNode recursiveNode) {
             Object unwrapped = value.getDataAt(index % value.getLength());
             if (unwrapped instanceof RAbstractVector) {
-                return recursiveNode.execute((RAbstractContainer) unwrapped, index, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+                return recursiveNode.execute((RAbstractContainer) unwrapped, 0, vpSize, scalemin, scalemax, nullLMode, nullAMode, isDimension, drawingCtx);
             }
             throw error(Message.GENERIC, "Unexpected unit list with non-vector like element at index " + index);
         }
 
         @Specialization(guards = "isArithmetic(list)")
-        double doArithmetic(RList list, int index, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx,
-                        @Cached("createAsDoubleCast()") CastNode asDoubleCast,
+        double doArithmetic(RList list, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx,
                         @Cached("create()") UnitLengthNode unitLengthNode,
                         @Cached("create()") UnitToInchesNode recursiveNode) {
-            ArithmeticUnit expr = asArithmeticUnit(list);
-            Function<RAbstractContainer, Double> recursive = x -> recursiveNode.execute(x, index, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+            ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit(list);
+            // Note the catch: newNullAMode is applied only if isDimension == true
+            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> recursiveNode.execute(x, index, vpSize, scalemin, scalemax, nullLMode,
+                            isDimension ? newNullAMode : nullAMode, isDimension, drawingCtx);
             switch (expr.op) {
                 case "+":
-                    return recursive.apply(expr.arg1) + recursive.apply(expr.arg2);
+                    return recursive.apply(expr.arg1, L_adding) + recursive.apply(expr.arg2, L_adding);
                 case "-":
-                    return recursive.apply(expr.arg1) + recursive.apply(expr.arg2);
+                    return recursive.apply(expr.arg1, L_subtracting) - recursive.apply(expr.arg2, L_subtracting);
                 case "*":
-                    RAbstractDoubleVector left = (RAbstractDoubleVector) asDoubleCast.execute(expr.arg1);
-                    return left.getDataAt(index % left.getLength()) + recursive.apply(expr.arg2);
+                    RAbstractDoubleVector left = GridUtils.asDoubleVector(expr.arg1);
+                    return left.getDataAt(index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying);
                 default:
                     break;
             }
 
             // must be aggregate operation
+            int newNullAMode = isDimension ? getNullAMode(expr.op) : nullAMode;
             int len = unitLengthNode.execute(expr.arg1);
             double[] values = new double[len];
             for (int i = 0; i < len; i++) {
-                values[i] = recursiveNode.execute(expr.arg1, i, vpSize, scalemin, scalemax, isDimension, drawingCtx);
+                values[i] = recursiveNode.execute(expr.arg1, i, vpSize, scalemin, scalemax, nullLMode, newNullAMode, isDimension, drawingCtx);
             }
 
             switch (expr.op) {
@@ -351,22 +509,108 @@ public class Unit {
                 case "max":
                     return GridUtils.fmax(Double.MAX_VALUE, values);
                 case "sum":
-                    return sum(values);
+                    return GridUtils.sum(values);
                 default:
                     throw RInternalError.shouldNotReachHere("The operation should have been validated in asArithmeticUnit method.");
             }
         }
 
+        private static int getNullAMode(String op) {
+            switch (op) {
+                case "min":
+                    return L_minimising;
+                case "max":
+                    return L_maximising;
+                case "sum":
+                    return L_summing;
+            }
+            return L_plain;
+        }
+
         static CastNode createAsDoubleCast() {
             return newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
         }
+    }
 
-        static double sum(double[] values) {
-            double result = 0;
-            for (int i = 0; i < values.length; i++) {
-                result += values[i];
+    public static final class GrobUnitToInches extends Node {
+        @Child private RGridCodeCall preDrawCode = new RGridCodeCall("grobConversionPreDraw");
+        @Child private RGridCodeCall getUnitXY = new RGridCodeCall("grobConversionGetUnitXY");
+        @Child private RGridCodeCall postDrawCode = new RGridCodeCall("grobConversionPostDraw");
+        @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+        @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+        @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
+        @Child private UnitToInchesNode unitToInchesNode;
+
+        // transcribed from unit.c function evaluateGrobUnit
+
+        public double execute(double value, int unitId, Object grob, int nullLMode, int nullAMode) {
+            GridContext ctx = GridContext.getContext();
+            RList currentVP = ctx.getGridState().getViewPort();
+            getViewPortTransform.execute(currentVP);
+
+            RList savedGPar = ctx.getGridState().getGpar();
+            Object savedGrob = ctx.getGridState().getCurrentGrob();
+
+            Object updatedGrob = preDrawCode.call(grob);
+
+            /*
+             * The call to preDraw may have pushed viewports and/or enforced gpar settings, SO we
+             * need to re-establish the current viewport and gpar settings before evaluating the
+             * width unit.
+             */
+            currentVP = ctx.getGridState().getViewPort();
+            RList currentGP = ctx.getGridState().getGpar();
+            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+            ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+
+            // getUnitXY returns a list with either one or two items
+            RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId}, ArgumentsSignature.empty(2)));
+            double result;
+            switch (unitId) {
+                case GROBX:
+                case GROBY:
+                    if (unitId == GROBY && isRelativeUnit.execute(unitxy.getDataAt(1), 0)) {
+                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
+                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), nullLMode, nullAMode);
+                    } else if (isRelativeUnit.execute(unitxy.getDataAt(0), 0)) {
+                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
+                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), nullLMode, nullAMode);
+                    } else {
+                        throw RInternalError.unimplemented("GrobUnitToInches from unit.c: 610");
+                    }
+                    break;
+                default:
+                    // should still be GROB_SOMETHING unit
+                    if (isRelativeUnit.execute(unitxy.getDataAt(0), 0)) {
+                        // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
+                        // GROBHEIGHT, bug?
+                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
+                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), nullLMode, nullAMode);
+                    } else {
+                        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, GPar.asDrawingContext(currentGP));
+                        initUnitToInchesNode();
+                        if (unitId == GROBWIDTH) {
+                            result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, conversionCtx);
+                        } else {
+                            // Note: GnuR uses height transform for both grobascent, grobdescent and
+                            // for height
+                            result = unitToInchesNode.convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, conversionCtx);
+                        }
+                    }
+                    break;
+            }
+
+            postDrawCode.call(updatedGrob);
+            ctx.getGridState().setGpar(savedGPar);
+            ctx.getGridState().setCurrentGrob(savedGrob);
+            return value * result;
+        }
+
+        private void initUnitToInchesNode() {
+            if (unitToInchesNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                unitToInchesNode = UnitToInchesNode.create();
             }
-            return result;
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 820e2ef119..7bf24ec0aa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -11,15 +11,19 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 /**
  * There is a notion of a view point, which is an ordinary list that user creates to define a view
@@ -51,7 +55,7 @@ class ViewPort {
      * Additional structure of a pushedvp
      */
     public static final int PVP_PARENTGPAR = 17;
-    private static final int PVP_GPAR = 18;
+    public static final int PVP_GPAR = 18;
     public static final int PVP_TRANS = 19;
     public static final int PVP_WIDTHS = 20;
     public static final int PVP_HEIGHTS = 21;
@@ -63,6 +67,64 @@ class ViewPort {
     public static final int PVP_CHILDREN = 27;
     public static final int PVP_DEVWIDTHCM = 28;
     public static final int PVP_DEVHEIGHTCM = 29;
+    /*
+     * Structure of a layout
+     */
+    private static final int LAYOUT_NROW = 0;
+    private static final int LAYOUT_NCOL = 1;
+    public static final int LAYOUT_WIDTHS = 2;
+    public static final int LAYOUT_HEIGHTS = 3;
+    public static final int LAYOUT_RESPECT = 4;
+    public static final int LAYOUT_VRESPECT = 5;
+    public static final int LAYOUT_MRESPECT = 6;
+    public static final int LAYOUT_JUST = 7;
+    private static final int LAYOUT_VJUST = 8;
+
+    /**
+     * Represents the integer values extracted from {@link #LAYOUT_NCOL} and {@link #LAYOUT_NROW}.
+     * In the R world, RNulls are valid values for those, we convert them to -1 to keep type safety.
+     * The values should be interpreted as 0-based indexes.
+     */
+    public static final class LayoutPos {
+        public final int colMin;
+        public final int colMax;
+        public final int rowMin;
+        public final int rowMax;
+        public final LayoutSize layoutSize;
+
+        LayoutPos(int colMin, int colMax, int rowMin, int rowMax, LayoutSize layoutSize) {
+            this.colMin = colMin;
+            this.colMax = colMax;
+            this.rowMin = rowMin;
+            this.rowMax = rowMax;
+            this.layoutSize = layoutSize;
+        }
+    }
+
+    /**
+     * The values should be interpreted as 0-based indexes.
+     */
+    public static final class LayoutSize {
+        public final int ncol;
+        public final int nrow;
+        public final double hjust;
+        public final double vjust;
+
+        private LayoutSize(int nrow, int ncol, double hjust, double vjust) {
+            this.ncol = ncol;
+            this.nrow = nrow;
+            this.hjust = hjust;
+            this.vjust = vjust;
+        }
+
+        public static LayoutSize fromViewPort(RList vp) {
+            RList layout = asList(vp.getDataAt(ViewPort.VP_LAYOUT));
+            int ncol = RRuntime.asInteger(layout.getDataAt(ViewPort.LAYOUT_NCOL));
+            int nrow = RRuntime.asInteger(layout.getDataAt(ViewPort.LAYOUT_NROW));
+            RAbstractDoubleVector just = (RAbstractDoubleVector) layout.getDataAt(ViewPort.LAYOUT_VJUST);
+            return new LayoutSize(nrow, ncol, just.getDataAt(0), just.getDataAt(1));
+        }
+    }
 
     public static final class InitViewPortNode extends Node {
         @Child private ReadVariableNode readGridTopLevel = ReadVariableNode.create("grid.top.level.vp");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
index 016e90247a..cc7656af20 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -38,6 +38,8 @@ public final class ViewPortTransform {
         @Child private CastNode castScalarDouble = newCastBuilder().mustBe(numericValue()).asDoubleVector().findFirst().buildCastNode();
 
         public ViewPortTransform execute(RList viewPort) {
+            // TODO: if device has changed, recalculate the VP transform!!! Some code, e.g.
+            // GrobUnitToInches relies on that
             double width = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
             double height = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
             double rotationAngle = getScalar(viewPort.getDataAt(ViewPort.VP_ANGLE));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 3d878b99c0..16299f7a2e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -69,7 +69,7 @@ public interface GridDevice {
      * parameters from the drawing context, but we allow the device to override this calculation
      * with something more precise.
      */
-    default double getStringHeight(DrawingContext ctx, String text) {
+    default double getStringHeight(DrawingContext ctx, @SuppressWarnings("unused") String text) {
         return (ctx.getLineHeight() * ctx.getFontSize()) / INCH_TO_POINTS_FACTOR;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index 0dae5cec37..84f733bb59 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -43,4 +43,120 @@ L_downviewport <- function(name, strict) {
 L_setviewport <- function(vp, hasParent) {
     pushedVP <- grid:::pushedvp(vp);
     .Internal(.fastr.grid.doSetViewPort(pushedVP, hasParent, TRUE));
-}
\ No newline at end of file
+}
+
+###################################################
+# Helper functions to deal with null and grob units
+# these functions are invoked from Java directly
+
+# Should be in sync with constants in Unit java class
+L_GROBX <- 19
+L_GROBY <- 20
+L_GROBWIDTH <- 21
+L_GROBHEIGHT <- 22
+L_GROBASCENT <- 23
+L_GROBDESCENT <- 24
+
+indexMod <- function(i, mod) ((i - 1) %% mod) + 1
+
+# if the grob is gPath, use it to find an actual grob
+# savedgrob - the grob from grid context
+findGrob <- function(grob, savedgrob) {
+    if (inherits(grob, "gPath")) {
+        if (is.null(savedgrob)) {
+            return(grid:::findGrobinDL(grob$name))
+        } else {
+            return(grid:::findGrobinChildren(grob$name, savedgrob$children))
+        }
+    }
+    grob
+}
+
+# this is called from FastR, it is simpler to implement this whole function in R.
+# GnuR uses series of install -> lang2 -> eval calls to achieve this from C.
+isPureNullUnit <- function(unit, index) {
+    if (inherits(unit, "unit.arithmetic")) {
+        return(isPureNullUnitArithmetic(unit, index));
+    } else if (inherits(unit, "unit.list")) {
+        return(isPureNullUnit(unit[[indexMod(index, length(unit))]], 1))
+    }
+    unitId <- attr(unit, "valid.unit")
+    if (unitId == L_GROBWIDTH) {
+        return(isPureNullUnitGrobDim(unit, index, grid:::width))
+    } else if (unitId == L_GROBHEIGHT) {
+        return(isPureNullUnitGrobDim(unit, index, grid:::height))
+    }
+    unitId == 5 # L_NULL
+}
+
+getUnitData <- function(unit, index) {
+    result <- attr(unit, "data")
+    if (!is.list(result)) {
+        return(result)
+    }
+    result[[indexMod(index, length(result))]]
+}
+
+isPureNullUnitGrobDim <- function(unit, index, dimFunction) {
+    # Can a grob have "null" width/height?
+    # to be sure we cover everything, we keep the check here (like in GnuR)
+    savedgpar <- .Call(grid:::L_getGPar)
+    savedgrob <- .Call(grid:::L_getCurrentGrob)
+
+    grob <- findGrob(getUnitData(unit, index), savedgrob)
+
+    updatedgrob <- grid:::preDraw(grob)
+    result <- isPureNullUnit(dimFunction(updatedgrob), 1)
+    grid:::postDraw(updatedgrob)
+
+    .Call(grid:::L_setGPar, savedgpar)
+    .Call(grid:::L_setCurrentGrob, savedgrob)
+    result
+}
+
+isPureNullUnitArithmetic <- function(x, index) {
+    if (x$fname %in% c('+', '-')) {
+        # can this ever happen when Ops.unit raises error for two null units added/subtracted?
+        # to be sure we cover everything, we keep the check here (like in GnuR)
+        return(isPureNullUnit(x$arg1, index) && isPureNullUnit(x$arg2, index))
+    } else if (x$fname == '*') {
+        return(isPureNullUnit(x$arg2, index))
+    } else if (x$fname %in% c('min', 'max', 'sum')) {
+        return(all(sapply(seq_along(x$arg1), function(i) isPureNullUnit(x$arg1, i))))
+    } else {
+        error("unimplemented unit function");
+    }
+}
+
+# tests:
+# isPureNullUnit(grid:::unit.list(unit(c(1,2,3),c('mm', 'cm', 'null'))), 1) == FALSE
+# isPureNullUnit(grid:::unit.list(unit(c(1,2,3),c('mm', 'cm', 'null'))), 3) == TRUE
+# isPureNullUnit(3*unit(1,'mm'), 2) == FALSE
+# isPureNullUnit(3*unit(1,'null'), 2) == TRUE
+# isPureNullUnit(min(unit(1,'null')), 1) == TRUE
+# { gt <- grid.text("Hi there"); isPureNullUnit(unit(1, "grobwidth", gt), 1) } == FALSE
+# { gt <- grid.text("Hi there"); isPureNullUnit(unit(1, "grobheight", gt), 1) } == FALSE
+
+grobConversionPreDraw <- function(grobIn) {
+    grob <- findGrob(grobIn, .Call(grid:::L_getCurrentGrob))
+    grid:::preDraw(grob)
+}
+
+grobConversionGetUnitXY <- function(grob, unitId) {
+    if (unitId == L_GROBX || unitId == L_GROBY) {
+        return(list(grid:::xDetails(grob), grid:::yDetails(grob)))
+    } else if (unitId == L_GROBWIDTH) {
+        return(list(grid:::width(grob)))
+    } else if (unitId == L_GROBHEIGHT) {
+        return(list(grid:::height(grob)))
+    } else if (unitId == L_GROBDESCENT) {
+        return(list(grid:::descentDetails(grob)))
+    } else if (unitId == L_GROBASCENT) {
+        return(list(grid:::ascentDetails(grob)))
+    }
+    error("grobConversionGetUnitXY: not a grob unit.")
+}
+
+grobConversionPostDraw <- function(grob) {
+    grid:::postDraw(grob)
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
index 2e59a39796..e4b6fd0f7e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.graphics;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
@@ -31,7 +32,6 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 public class CPar extends RExternalBuiltinNode {
     static {
@@ -39,6 +39,7 @@ public class CPar extends RExternalBuiltinNode {
     }
 
     @Override
+    @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
         if (args.getSignature().getNonNullCount() > 0) {
             throw error(Message.GENERIC, "Using par for setting device parameters is not supported in FastR grid emulation mode.");
@@ -46,18 +47,21 @@ public class CPar extends RExternalBuiltinNode {
 
         GridDevice device = GridContext.getContext().getCurrentDevice();
         Object[] names = args.getArguments();
+        // unwrap list if it is the first argument
         if (names.length == 1) {
             Object first = args.getArgument(0);
             if (first instanceof RList) {
                 names = ((RList) first).getDataWithoutCopying();
             }
-            if (names.length == 1) {
-                // if there is a single name, do not wrap the result in a list
-                return getParam(RRuntime.asString(names[0]), device);
-            }
         }
 
-        throw error(Message.GENERIC, "Querying par for anything else than 'din' is not supported in FastR grid emulation mode.");
+        Object[] result = new Object[names.length];
+        String[] resultNames = new String[names.length];
+        for (int i = 0; i < names.length; i++) {
+            resultNames[i] = RRuntime.asString(names[i]);
+            result[i] = getParam(resultNames[i], device);
+        }
+        return RDataFactory.createList(result, RDataFactory.createStringVector(resultNames, RDataFactory.COMPLETE_VECTOR));
     }
 
     private Object getParam(String name, GridDevice device) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java
index f358dfb3c0..4e19a7b99e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/package-info.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 /**
  * Compatibility layer for graphics package.
  *
-- 
GitLab


From f575808a362155266dd2b27954e27cd2eb73d474 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 15 Mar 2017 16:15:17 +0100
Subject: [PATCH 158/402] FastR Grid: implement L_points

---
 .../truffle/r/library/fastrGrid/GPar.java     |  38 ++++-
 .../r/library/fastrGrid/GridUtils.java        |  11 +-
 .../truffle/r/library/fastrGrid/LPoints.java  | 141 ++++++++++++++++++
 .../fastrGrid/device/DrawingContext.java      |  18 +++
 .../foreign/CallAndExternalFunctions.java     |   3 +
 mx.fastr/copyrights/overrides                 |   1 +
 6 files changed, 199 insertions(+), 13 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index c17dbe5d15..49d587cf37 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -11,6 +11,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+
 import java.util.Arrays;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
@@ -97,6 +99,10 @@ public final class GPar {
         return RDataFactory.createList(data, NAMES_VECTOR);
     }
 
+    public static double getCex(RList gpar) {
+        return asDouble(gpar.getDataAt(GP_CEX));
+    }
+
     public static DrawingContext asDrawingContext(RList gpar) {
         return new GParDrawingContext(gpar);
     }
@@ -114,22 +120,40 @@ public final class GPar {
 
         @Override
         public String getColor() {
-            String result = RRuntime.asString(data[GP_COL]);
-            if (!result.startsWith("#")) {
-                result = ColorNames.findByName(result);
-            }
-            return result == null ? "#FFFFFF" : result;
+            return getHexColor(GP_COL);
+        }
+
+        @Override
+        public void setColor(String hexCode) {
+            data[GP_COL] = hexCode;
         }
 
         @Override
         public double getFontSize() {
-            return GridUtils.asDouble(data[GP_FONTSIZE]) * GridUtils.asDouble(data[GP_CEX]);
+            return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
         }
 
         @Override
         public double getLineHeight() {
-            return GridUtils.asDouble(data[GP_LINEHEIGHT]);
+            return asDouble(data[GP_LINEHEIGHT]);
         }
 
+        @Override
+        public String getFillColor() {
+            return getHexColor(GP_FILL);
+        }
+
+        @Override
+        public void setFillColor(String hexCode) {
+            data[GP_FILL] = hexCode;
+        }
+
+        private String getHexColor(int index) {
+            String result = RRuntime.asString(data[index]);
+            if (!result.startsWith("#")) {
+                result = ColorNames.findByName(result);
+            }
+            return result == null ? "#FFFFFF" : result;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 782150456a..0de2442c7b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -19,8 +19,7 @@ import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RAttributable;
-import com.oracle.truffle.r.runtime.data.RDouble;
-import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -116,7 +115,7 @@ final class GridUtils {
 
     static RAbstractIntVector asIntVector(Object value) {
         if (value instanceof Integer) {
-            return RInteger.valueOf((Integer) value);
+            return RDataFactory.createIntVectorFromScalar((Integer) value);
         } else if (value instanceof RAbstractIntVector) {
             return (RAbstractIntVector) value;
         }
@@ -125,7 +124,7 @@ final class GridUtils {
 
     public static RAbstractDoubleVector asDoubleVector(Object obj) {
         if (obj instanceof Double) {
-            return RDouble.valueOf((Double) obj);
+            return RDataFactory.createDoubleVectorFromScalar((Double) obj);
         } else if (obj instanceof RAbstractDoubleVector) {
             return (RAbstractDoubleVector) obj;
         }
@@ -134,9 +133,9 @@ final class GridUtils {
 
     static RAbstractContainer asAbstractContainer(Object value) {
         if (value instanceof Integer) {
-            return RInteger.valueOf((Integer) value);
+            return RDataFactory.createIntVectorFromScalar((Integer) value);
         } else if (value instanceof Double) {
-            return RDouble.valueOf((Double) value);
+            return RDataFactory.createDoubleVectorFromScalar((Double) value);
         } else if (value instanceof RAbstractContainer) {
             return (RAbstractContainer) value;
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
new file mode 100644
index 0000000000..5c40420695
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -0,0 +1,141 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2015, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
+    private static final double SMALL = 0.25;
+    private static final double RADIUS = 0.375;
+    private static final double SQRC = 0.88622692545275801364; /* sqrt(pi / 4) */
+    private static final double DMDC = 1.25331413731550025119; /* sqrt(pi / 4) * sqrt(2) */
+    private static final double TRC0 = 1.55512030155621416073; /* sqrt(4 * pi/(3 * sqrt(3))) */
+    private static final double TRC1 = 1.34677368708859836060; /* TRC0 * sqrt(3) / 2 */
+    private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
+    private static final String TRANSPARENT = "white";  // TODO: should be actually transparent
+
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+    @Child private UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
+
+    static {
+        Casts casts = new Casts(LPoints.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(numericValue(), Message.GENERIC, "grid.points: pch argument not implemented for characters yet").asIntegerVector();
+        casts.arg(3).mustBe(abstractVectorValue());
+    }
+
+    public static LPoints create() {
+        return LPointsNodeGen.create();
+    }
+
+    @Specialization
+    public Object doPoints(RAbstractVector xVec, RAbstractVector yVec, RAbstractIntVector pchVec, RAbstractVector sizeVec) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        RList gpar = ctx.getGridState().getGpar();
+        DrawingContext drawingCtx = GPar.asDrawingContext(gpar);
+        double cex = GPar.getCex(gpar);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+
+        // Note: unlike in other drawing primitives, we only consider length of x
+        int length = unitLength.execute(xVec);
+        for (int i = 0; i < length; i++) {
+            Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx), vpTransform.transform);
+            double size = unitToInches.convertWidth(sizeVec, i, conversionCtx);
+            if (loc.isFinite() && Double.isFinite(size)) {
+                drawSymbol(drawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
+            }
+        }
+        return RNull.instance;
+    }
+
+    // transcribed from engine.c function GESymbol
+
+    private void drawSymbol(DrawingContext drawingCtx, GridDevice dev, double cex, int pch, double size, double x, double y) {
+        // pch 0 - 25 are interpreted as geometrical shapes, pch from ascii code of ' ' are
+        // interpreted as corresponding ascii character, which should be drawn
+        switch (pch) {
+            case 46:
+                drawDot(drawingCtx, dev, cex, x, y);
+                break;
+            case 1:
+                drawOctahedron(drawingCtx, dev, GridColor.TRANSPARENT, size, x, y);
+                break;
+            case 16:
+                drawOctahedron(drawingCtx, dev, drawingCtx.getColor(), size, x, y);
+                break;
+            default:
+                throw RInternalError.unimplemented("grid.points unimplemented symbol " + pch);
+        }
+    }
+
+    private static void drawOctahedron(DrawingContext drawingCtx, GridDevice dev, GridColor fill, double size, double x, double y) {
+        GridColor originalFill = drawingCtx.getFillColor();
+        drawingCtx.setFillColor(fill);
+        dev.drawCircle(drawingCtx, x, y, RADIUS * size);
+        drawingCtx.setFillColor(originalFill);
+    }
+
+    private static void drawDot(DrawingContext drawingCtx, GridDevice dev, double cex, double x, double y) {
+        // NOTE: we are *filling* a rect with the current colour (we are not drawing the border AND
+        // we are not using the current fill colour)
+        String originalFill = drawingCtx.getFillColor();
+        drawingCtx.setFillColor(drawingCtx.getColor());
+        drawingCtx.setColor(TRANSPARENT);
+
+        /*
+         * The idea here is to use a 0.01" square, but to be of at least one device unit in each
+         * direction, assuming that corresponds to pixels. That may be odd if pixels are not square,
+         * but only on low resolution devices where we can do nothing better.
+         *
+         * For this symbol only, size is cex (see engine.c).
+         *
+         * Prior to 2.1.0 the offsets were always 0.5.
+         */
+        double xc = cex * 0.005;
+        double yc = cex * 0.005;
+        if (cex > 0 && xc < 0.5) {
+            xc = 0.5;
+        }
+        if (cex > 0 && yc < 0.5) {
+            yc = 0.5;
+        }
+        dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc);
+
+        drawingCtx.setColor(drawingCtx.getFillColor());
+        drawingCtx.setFillColor(originalFill);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index facac095e9..1cd94bdabf 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -34,6 +34,12 @@ public interface DrawingContext {
      */
     String getColor();
 
+    /**
+     * Alows to set the color. The parameter may also be a synonym defined in
+     * {@link com.oracle.truffle.r.library.fastrGrid.ColorNames}.
+     */
+    void setColor(String hexCode);
+
     /**
      * Gets the font size in points.
      *
@@ -45,4 +51,16 @@ public interface DrawingContext {
      * Gets the height of a line in multiplies of the base line height.
      */
     double getLineHeight();
+
+    /**
+     * @return Hexadecimal string of the color with leading '#', e.g. '#FFA8B2'. Never returns a
+     *         synonym.
+     */
+    String getFillColor();
+
+    /**
+     * Alows to set the fill color. The parameter may also be a synonym defined in
+     * {@link com.oracle.truffle.r.library.fastrGrid.ColorNames}.
+     */
+    void setFillColor(String hexCode);
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 9a10b92b97..6b0b5d88be 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
 import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
 import com.oracle.truffle.r.library.fastrGrid.LLines;
 import com.oracle.truffle.r.library.fastrGrid.LNewPage;
+import com.oracle.truffle.r.library.fastrGrid.LPoints;
 import com.oracle.truffle.r.library.fastrGrid.LRect;
 import com.oracle.truffle.r.library.fastrGrid.LSegments;
 import com.oracle.truffle.r.library.fastrGrid.LText;
@@ -709,6 +710,8 @@ public class CallAndExternalFunctions {
                     return LSegments.create();
                 case "L_circle":
                     return LCircle.create();
+                case "L_points":
+                    return LPoints.create();
 
                 // Simple grid state access
                 case "L_getGPar":
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 8119e383c8..2ed282f563 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -767,6 +767,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright
-- 
GitLab


From e225782ffcac7c0f7019dbcab12d920d0c02bb40 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 16 Mar 2017 16:19:07 +0100
Subject: [PATCH 159/402] FastR Grid: honor fill color + GUI framework
 independent color representation

---
 .../r/library/fastrGrid/ColorNames.java       | 686 ----------------
 .../truffle/r/library/fastrGrid/GPar.java     |  27 +-
 .../r/library/fastrGrid/GridColorUtils.java   | 745 ++++++++++++++++++
 .../truffle/r/library/fastrGrid/LPoints.java  |   6 +-
 .../fastrGrid/device/DrawingContext.java      |  22 +-
 .../r/library/fastrGrid/device/GridColor.java |  58 ++
 .../fastrGrid/device/JFrameDevice.java        |  34 +-
 .../fastrGrid/GridColorUtilsTests.java        |  93 +++
 mx.fastr/copyrights/overrides                 |   2 +-
 mx.fastr/mx_fastr.py                          |   2 +-
 10 files changed, 950 insertions(+), 725 deletions(-)
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java
deleted file mode 100644
index 18eb3b0964..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 1997-2014, The R Core Team
- * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2017, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.fastrGrid;
-
-import java.util.HashMap;
-
-final class ColorNames {
-    private static HashMap<String, String> synonymToHexName;
-
-    public static String findByName(String synonym) {
-        if (synonymToHexName == null) {
-            initialize();
-        }
-        return synonymToHexName.get(synonym);
-    }
-
-    private static void initialize() {
-        synonymToHexName = new HashMap<>(700);
-        synonymToHexName.put("white", "#FFFFFF");
-        synonymToHexName.put("aliceblue", "#F0F8FF");
-        synonymToHexName.put("antiquewhite", "#FAEBD7");
-        synonymToHexName.put("antiquewhite1", "#FFEFDB");
-        synonymToHexName.put("antiquewhite2", "#EEDFCC");
-        synonymToHexName.put("antiquewhite3", "#CDC0B0");
-        synonymToHexName.put("antiquewhite4", "#8B8378");
-        synonymToHexName.put("aquamarine", "#7FFFD4");
-        synonymToHexName.put("aquamarine1", "#7FFFD4");
-        synonymToHexName.put("aquamarine2", "#76EEC6");
-        synonymToHexName.put("aquamarine3", "#66CDAA");
-        synonymToHexName.put("aquamarine4", "#458B74");
-        synonymToHexName.put("azure", "#F0FFFF");
-        synonymToHexName.put("azure1", "#F0FFFF");
-        synonymToHexName.put("azure2", "#E0EEEE");
-        synonymToHexName.put("azure3", "#C1CDCD");
-        synonymToHexName.put("azure4", "#838B8B");
-        synonymToHexName.put("beige", "#F5F5DC");
-        synonymToHexName.put("bisque", "#FFE4C4");
-        synonymToHexName.put("bisque1", "#FFE4C4");
-        synonymToHexName.put("bisque2", "#EED5B7");
-        synonymToHexName.put("bisque3", "#CDB79E");
-        synonymToHexName.put("bisque4", "#8B7D6B");
-        synonymToHexName.put("black", "#000000");
-        synonymToHexName.put("blanchedalmond", "#FFEBCD");
-        synonymToHexName.put("blue", "#0000FF");
-        synonymToHexName.put("blue1", "#0000FF");
-        synonymToHexName.put("blue2", "#0000EE");
-        synonymToHexName.put("blue3", "#0000CD");
-        synonymToHexName.put("blue4", "#00008B");
-        synonymToHexName.put("blueviolet", "#8A2BE2");
-        synonymToHexName.put("brown", "#A52A2A");
-        synonymToHexName.put("brown1", "#FF4040");
-        synonymToHexName.put("brown2", "#EE3B3B");
-        synonymToHexName.put("brown3", "#CD3333");
-        synonymToHexName.put("brown4", "#8B2323");
-        synonymToHexName.put("burlywood", "#DEB887");
-        synonymToHexName.put("burlywood1", "#FFD39B");
-        synonymToHexName.put("burlywood2", "#EEC591");
-        synonymToHexName.put("burlywood3", "#CDAA7D");
-        synonymToHexName.put("burlywood4", "#8B7355");
-        synonymToHexName.put("cadetblue", "#5F9EA0");
-        synonymToHexName.put("cadetblue1", "#98F5FF");
-        synonymToHexName.put("cadetblue2", "#8EE5EE");
-        synonymToHexName.put("cadetblue3", "#7AC5CD");
-        synonymToHexName.put("cadetblue4", "#53868B");
-        synonymToHexName.put("chartreuse", "#7FFF00");
-        synonymToHexName.put("chartreuse1", "#7FFF00");
-        synonymToHexName.put("chartreuse2", "#76EE00");
-        synonymToHexName.put("chartreuse3", "#66CD00");
-        synonymToHexName.put("chartreuse4", "#458B00");
-        synonymToHexName.put("chocolate", "#D2691E");
-        synonymToHexName.put("chocolate1", "#FF7F24");
-        synonymToHexName.put("chocolate2", "#EE7621");
-        synonymToHexName.put("chocolate3", "#CD661D");
-        synonymToHexName.put("chocolate4", "#8B4513");
-        synonymToHexName.put("coral", "#FF7F50");
-        synonymToHexName.put("coral1", "#FF7256");
-        synonymToHexName.put("coral2", "#EE6A50");
-        synonymToHexName.put("coral3", "#CD5B45");
-        synonymToHexName.put("coral4", "#8B3E2F");
-        synonymToHexName.put("cornflowerblue", "#6495ED");
-        synonymToHexName.put("cornsilk", "#FFF8DC");
-        synonymToHexName.put("cornsilk1", "#FFF8DC");
-        synonymToHexName.put("cornsilk2", "#EEE8CD");
-        synonymToHexName.put("cornsilk3", "#CDC8B1");
-        synonymToHexName.put("cornsilk4", "#8B8878");
-        synonymToHexName.put("cyan", "#00FFFF");
-        synonymToHexName.put("cyan1", "#00FFFF");
-        synonymToHexName.put("cyan2", "#00EEEE");
-        synonymToHexName.put("cyan3", "#00CDCD");
-        synonymToHexName.put("cyan4", "#008B8B");
-        synonymToHexName.put("darkblue", "#00008B");
-        synonymToHexName.put("darkcyan", "#008B8B");
-        synonymToHexName.put("darkgoldenrod", "#B8860B");
-        synonymToHexName.put("darkgoldenrod1", "#FFB90F");
-        synonymToHexName.put("darkgoldenrod2", "#EEAD0E");
-        synonymToHexName.put("darkgoldenrod3", "#CD950C");
-        synonymToHexName.put("darkgoldenrod4", "#8B6508");
-        synonymToHexName.put("darkgray", "#A9A9A9");
-        synonymToHexName.put("darkgreen", "#006400");
-        synonymToHexName.put("darkgrey", "#A9A9A9");
-        synonymToHexName.put("darkkhaki", "#BDB76B");
-        synonymToHexName.put("darkmagenta", "#8B008B");
-        synonymToHexName.put("darkolivegreen", "#556B2F");
-        synonymToHexName.put("darkolivegreen1", "#CAFF70");
-        synonymToHexName.put("darkolivegreen2", "#BCEE68");
-        synonymToHexName.put("darkolivegreen3", "#A2CD5A");
-        synonymToHexName.put("darkolivegreen4", "#6E8B3D");
-        synonymToHexName.put("darkorange", "#FF8C00");
-        synonymToHexName.put("darkorange1", "#FF7F00");
-        synonymToHexName.put("darkorange2", "#EE7600");
-        synonymToHexName.put("darkorange3", "#CD6600");
-        synonymToHexName.put("darkorange4", "#8B4500");
-        synonymToHexName.put("darkorchid", "#9932CC");
-        synonymToHexName.put("darkorchid1", "#BF3EFF");
-        synonymToHexName.put("darkorchid2", "#B23AEE");
-        synonymToHexName.put("darkorchid3", "#9A32CD");
-        synonymToHexName.put("darkorchid4", "#68228B");
-        synonymToHexName.put("darkred", "#8B0000");
-        synonymToHexName.put("darksalmon", "#E9967A");
-        synonymToHexName.put("darkseagreen", "#8FBC8F");
-        synonymToHexName.put("darkseagreen1", "#C1FFC1");
-        synonymToHexName.put("darkseagreen2", "#B4EEB4");
-        synonymToHexName.put("darkseagreen3", "#9BCD9B");
-        synonymToHexName.put("darkseagreen4", "#698B69");
-        synonymToHexName.put("darkslateblue", "#483D8B");
-        synonymToHexName.put("darkslategray", "#2F4F4F");
-        synonymToHexName.put("darkslategray1", "#97FFFF");
-        synonymToHexName.put("darkslategray2", "#8DEEEE");
-        synonymToHexName.put("darkslategray3", "#79CDCD");
-        synonymToHexName.put("darkslategray4", "#528B8B");
-        synonymToHexName.put("darkslategrey", "#2F4F4F");
-        synonymToHexName.put("darkturquoise", "#00CED1");
-        synonymToHexName.put("darkviolet", "#9400D3");
-        synonymToHexName.put("deeppink", "#FF1493");
-        synonymToHexName.put("deeppink1", "#FF1493");
-        synonymToHexName.put("deeppink2", "#EE1289");
-        synonymToHexName.put("deeppink3", "#CD1076");
-        synonymToHexName.put("deeppink4", "#8B0A50");
-        synonymToHexName.put("deepskyblue", "#00BFFF");
-        synonymToHexName.put("deepskyblue1", "#00BFFF");
-        synonymToHexName.put("deepskyblue2", "#00B2EE");
-        synonymToHexName.put("deepskyblue3", "#009ACD");
-        synonymToHexName.put("deepskyblue4", "#00688B");
-        synonymToHexName.put("dimgray", "#696969");
-        synonymToHexName.put("dimgrey", "#696969");
-        synonymToHexName.put("dodgerblue", "#1E90FF");
-        synonymToHexName.put("dodgerblue1", "#1E90FF");
-        synonymToHexName.put("dodgerblue2", "#1C86EE");
-        synonymToHexName.put("dodgerblue3", "#1874CD");
-        synonymToHexName.put("dodgerblue4", "#104E8B");
-        synonymToHexName.put("firebrick", "#B22222");
-        synonymToHexName.put("firebrick1", "#FF3030");
-        synonymToHexName.put("firebrick2", "#EE2C2C");
-        synonymToHexName.put("firebrick3", "#CD2626");
-        synonymToHexName.put("firebrick4", "#8B1A1A");
-        synonymToHexName.put("floralwhite", "#FFFAF0");
-        synonymToHexName.put("forestgreen", "#228B22");
-        synonymToHexName.put("gainsboro", "#DCDCDC");
-        synonymToHexName.put("ghostwhite", "#F8F8FF");
-        synonymToHexName.put("gold", "#FFD700");
-        synonymToHexName.put("gold1", "#FFD700");
-        synonymToHexName.put("gold2", "#EEC900");
-        synonymToHexName.put("gold3", "#CDAD00");
-        synonymToHexName.put("gold4", "#8B7500");
-        synonymToHexName.put("goldenrod", "#DAA520");
-        synonymToHexName.put("goldenrod1", "#FFC125");
-        synonymToHexName.put("goldenrod2", "#EEB422");
-        synonymToHexName.put("goldenrod3", "#CD9B1D");
-        synonymToHexName.put("goldenrod4", "#8B6914");
-        synonymToHexName.put("gray", "#BEBEBE");
-        synonymToHexName.put("gray0", "#000000");
-        synonymToHexName.put("gray1", "#030303");
-        synonymToHexName.put("gray2", "#050505");
-        synonymToHexName.put("gray3", "#080808");
-        synonymToHexName.put("gray4", "#0A0A0A");
-        synonymToHexName.put("gray5", "#0D0D0D");
-        synonymToHexName.put("gray6", "#0F0F0F");
-        synonymToHexName.put("gray7", "#121212");
-        synonymToHexName.put("gray8", "#141414");
-        synonymToHexName.put("gray9", "#171717");
-        synonymToHexName.put("gray10", "#1A1A1A");
-        synonymToHexName.put("gray11", "#1C1C1C");
-        synonymToHexName.put("gray12", "#1F1F1F");
-        synonymToHexName.put("gray13", "#212121");
-        synonymToHexName.put("gray14", "#242424");
-        synonymToHexName.put("gray15", "#262626");
-        synonymToHexName.put("gray16", "#292929");
-        synonymToHexName.put("gray17", "#2B2B2B");
-        synonymToHexName.put("gray18", "#2E2E2E");
-        synonymToHexName.put("gray19", "#303030");
-        synonymToHexName.put("gray20", "#333333");
-        synonymToHexName.put("gray21", "#363636");
-        synonymToHexName.put("gray22", "#383838");
-        synonymToHexName.put("gray23", "#3B3B3B");
-        synonymToHexName.put("gray24", "#3D3D3D");
-        synonymToHexName.put("gray25", "#404040");
-        synonymToHexName.put("gray26", "#424242");
-        synonymToHexName.put("gray27", "#454545");
-        synonymToHexName.put("gray28", "#474747");
-        synonymToHexName.put("gray29", "#4A4A4A");
-        synonymToHexName.put("gray30", "#4D4D4D");
-        synonymToHexName.put("gray31", "#4F4F4F");
-        synonymToHexName.put("gray32", "#525252");
-        synonymToHexName.put("gray33", "#545454");
-        synonymToHexName.put("gray34", "#575757");
-        synonymToHexName.put("gray35", "#595959");
-        synonymToHexName.put("gray36", "#5C5C5C");
-        synonymToHexName.put("gray37", "#5E5E5E");
-        synonymToHexName.put("gray38", "#616161");
-        synonymToHexName.put("gray39", "#636363");
-        synonymToHexName.put("gray40", "#666666");
-        synonymToHexName.put("gray41", "#696969");
-        synonymToHexName.put("gray42", "#6B6B6B");
-        synonymToHexName.put("gray43", "#6E6E6E");
-        synonymToHexName.put("gray44", "#707070");
-        synonymToHexName.put("gray45", "#737373");
-        synonymToHexName.put("gray46", "#757575");
-        synonymToHexName.put("gray47", "#787878");
-        synonymToHexName.put("gray48", "#7A7A7A");
-        synonymToHexName.put("gray49", "#7D7D7D");
-        synonymToHexName.put("gray50", "#7F7F7F");
-        synonymToHexName.put("gray51", "#828282");
-        synonymToHexName.put("gray52", "#858585");
-        synonymToHexName.put("gray53", "#878787");
-        synonymToHexName.put("gray54", "#8A8A8A");
-        synonymToHexName.put("gray55", "#8C8C8C");
-        synonymToHexName.put("gray56", "#8F8F8F");
-        synonymToHexName.put("gray57", "#919191");
-        synonymToHexName.put("gray58", "#949494");
-        synonymToHexName.put("gray59", "#969696");
-        synonymToHexName.put("gray60", "#999999");
-        synonymToHexName.put("gray61", "#9C9C9C");
-        synonymToHexName.put("gray62", "#9E9E9E");
-        synonymToHexName.put("gray63", "#A1A1A1");
-        synonymToHexName.put("gray64", "#A3A3A3");
-        synonymToHexName.put("gray65", "#A6A6A6");
-        synonymToHexName.put("gray66", "#A8A8A8");
-        synonymToHexName.put("gray67", "#ABABAB");
-        synonymToHexName.put("gray68", "#ADADAD");
-        synonymToHexName.put("gray69", "#B0B0B0");
-        synonymToHexName.put("gray70", "#B3B3B3");
-        synonymToHexName.put("gray71", "#B5B5B5");
-        synonymToHexName.put("gray72", "#B8B8B8");
-        synonymToHexName.put("gray73", "#BABABA");
-        synonymToHexName.put("gray74", "#BDBDBD");
-        synonymToHexName.put("gray75", "#BFBFBF");
-        synonymToHexName.put("gray76", "#C2C2C2");
-        synonymToHexName.put("gray77", "#C4C4C4");
-        synonymToHexName.put("gray78", "#C7C7C7");
-        synonymToHexName.put("gray79", "#C9C9C9");
-        synonymToHexName.put("gray80", "#CCCCCC");
-        synonymToHexName.put("gray81", "#CFCFCF");
-        synonymToHexName.put("gray82", "#D1D1D1");
-        synonymToHexName.put("gray83", "#D4D4D4");
-        synonymToHexName.put("gray84", "#D6D6D6");
-        synonymToHexName.put("gray85", "#D9D9D9");
-        synonymToHexName.put("gray86", "#DBDBDB");
-        synonymToHexName.put("gray87", "#DEDEDE");
-        synonymToHexName.put("gray88", "#E0E0E0");
-        synonymToHexName.put("gray89", "#E3E3E3");
-        synonymToHexName.put("gray90", "#E5E5E5");
-        synonymToHexName.put("gray91", "#E8E8E8");
-        synonymToHexName.put("gray92", "#EBEBEB");
-        synonymToHexName.put("gray93", "#EDEDED");
-        synonymToHexName.put("gray94", "#F0F0F0");
-        synonymToHexName.put("gray95", "#F2F2F2");
-        synonymToHexName.put("gray96", "#F5F5F5");
-        synonymToHexName.put("gray97", "#F7F7F7");
-        synonymToHexName.put("gray98", "#FAFAFA");
-        synonymToHexName.put("gray99", "#FCFCFC");
-        synonymToHexName.put("gray100", "#FFFFFF");
-        synonymToHexName.put("green", "#00FF00");
-        synonymToHexName.put("green1", "#00FF00");
-        synonymToHexName.put("green2", "#00EE00");
-        synonymToHexName.put("green3", "#00CD00");
-        synonymToHexName.put("green4", "#008B00");
-        synonymToHexName.put("greenyellow", "#ADFF2F");
-        synonymToHexName.put("grey", "#BEBEBE");
-        synonymToHexName.put("grey0", "#000000");
-        synonymToHexName.put("grey1", "#030303");
-        synonymToHexName.put("grey2", "#050505");
-        synonymToHexName.put("grey3", "#080808");
-        synonymToHexName.put("grey4", "#0A0A0A");
-        synonymToHexName.put("grey5", "#0D0D0D");
-        synonymToHexName.put("grey6", "#0F0F0F");
-        synonymToHexName.put("grey7", "#121212");
-        synonymToHexName.put("grey8", "#141414");
-        synonymToHexName.put("grey9", "#171717");
-        synonymToHexName.put("grey10", "#1A1A1A");
-        synonymToHexName.put("grey11", "#1C1C1C");
-        synonymToHexName.put("grey12", "#1F1F1F");
-        synonymToHexName.put("grey13", "#212121");
-        synonymToHexName.put("grey14", "#242424");
-        synonymToHexName.put("grey15", "#262626");
-        synonymToHexName.put("grey16", "#292929");
-        synonymToHexName.put("grey17", "#2B2B2B");
-        synonymToHexName.put("grey18", "#2E2E2E");
-        synonymToHexName.put("grey19", "#303030");
-        synonymToHexName.put("grey20", "#333333");
-        synonymToHexName.put("grey21", "#363636");
-        synonymToHexName.put("grey22", "#383838");
-        synonymToHexName.put("grey23", "#3B3B3B");
-        synonymToHexName.put("grey24", "#3D3D3D");
-        synonymToHexName.put("grey25", "#404040");
-        synonymToHexName.put("grey26", "#424242");
-        synonymToHexName.put("grey27", "#454545");
-        synonymToHexName.put("grey28", "#474747");
-        synonymToHexName.put("grey29", "#4A4A4A");
-        synonymToHexName.put("grey30", "#4D4D4D");
-        synonymToHexName.put("grey31", "#4F4F4F");
-        synonymToHexName.put("grey32", "#525252");
-        synonymToHexName.put("grey33", "#545454");
-        synonymToHexName.put("grey34", "#575757");
-        synonymToHexName.put("grey35", "#595959");
-        synonymToHexName.put("grey36", "#5C5C5C");
-        synonymToHexName.put("grey37", "#5E5E5E");
-        synonymToHexName.put("grey38", "#616161");
-        synonymToHexName.put("grey39", "#636363");
-        synonymToHexName.put("grey40", "#666666");
-        synonymToHexName.put("grey41", "#696969");
-        synonymToHexName.put("grey42", "#6B6B6B");
-        synonymToHexName.put("grey43", "#6E6E6E");
-        synonymToHexName.put("grey44", "#707070");
-        synonymToHexName.put("grey45", "#737373");
-        synonymToHexName.put("grey46", "#757575");
-        synonymToHexName.put("grey47", "#787878");
-        synonymToHexName.put("grey48", "#7A7A7A");
-        synonymToHexName.put("grey49", "#7D7D7D");
-        synonymToHexName.put("grey50", "#7F7F7F");
-        synonymToHexName.put("grey51", "#828282");
-        synonymToHexName.put("grey52", "#858585");
-        synonymToHexName.put("grey53", "#878787");
-        synonymToHexName.put("grey54", "#8A8A8A");
-        synonymToHexName.put("grey55", "#8C8C8C");
-        synonymToHexName.put("grey56", "#8F8F8F");
-        synonymToHexName.put("grey57", "#919191");
-        synonymToHexName.put("grey58", "#949494");
-        synonymToHexName.put("grey59", "#969696");
-        synonymToHexName.put("grey60", "#999999");
-        synonymToHexName.put("grey61", "#9C9C9C");
-        synonymToHexName.put("grey62", "#9E9E9E");
-        synonymToHexName.put("grey63", "#A1A1A1");
-        synonymToHexName.put("grey64", "#A3A3A3");
-        synonymToHexName.put("grey65", "#A6A6A6");
-        synonymToHexName.put("grey66", "#A8A8A8");
-        synonymToHexName.put("grey67", "#ABABAB");
-        synonymToHexName.put("grey68", "#ADADAD");
-        synonymToHexName.put("grey69", "#B0B0B0");
-        synonymToHexName.put("grey70", "#B3B3B3");
-        synonymToHexName.put("grey71", "#B5B5B5");
-        synonymToHexName.put("grey72", "#B8B8B8");
-        synonymToHexName.put("grey73", "#BABABA");
-        synonymToHexName.put("grey74", "#BDBDBD");
-        synonymToHexName.put("grey75", "#BFBFBF");
-        synonymToHexName.put("grey76", "#C2C2C2");
-        synonymToHexName.put("grey77", "#C4C4C4");
-        synonymToHexName.put("grey78", "#C7C7C7");
-        synonymToHexName.put("grey79", "#C9C9C9");
-        synonymToHexName.put("grey80", "#CCCCCC");
-        synonymToHexName.put("grey81", "#CFCFCF");
-        synonymToHexName.put("grey82", "#D1D1D1");
-        synonymToHexName.put("grey83", "#D4D4D4");
-        synonymToHexName.put("grey84", "#D6D6D6");
-        synonymToHexName.put("grey85", "#D9D9D9");
-        synonymToHexName.put("grey86", "#DBDBDB");
-        synonymToHexName.put("grey87", "#DEDEDE");
-        synonymToHexName.put("grey88", "#E0E0E0");
-        synonymToHexName.put("grey89", "#E3E3E3");
-        synonymToHexName.put("grey90", "#E5E5E5");
-        synonymToHexName.put("grey91", "#E8E8E8");
-        synonymToHexName.put("grey92", "#EBEBEB");
-        synonymToHexName.put("grey93", "#EDEDED");
-        synonymToHexName.put("grey94", "#F0F0F0");
-        synonymToHexName.put("grey95", "#F2F2F2");
-        synonymToHexName.put("grey96", "#F5F5F5");
-        synonymToHexName.put("grey97", "#F7F7F7");
-        synonymToHexName.put("grey98", "#FAFAFA");
-        synonymToHexName.put("grey99", "#FCFCFC");
-        synonymToHexName.put("grey100", "#FFFFFF");
-        synonymToHexName.put("honeydew", "#F0FFF0");
-        synonymToHexName.put("honeydew1", "#F0FFF0");
-        synonymToHexName.put("honeydew2", "#E0EEE0");
-        synonymToHexName.put("honeydew3", "#C1CDC1");
-        synonymToHexName.put("honeydew4", "#838B83");
-        synonymToHexName.put("hotpink", "#FF69B4");
-        synonymToHexName.put("hotpink1", "#FF6EB4");
-        synonymToHexName.put("hotpink2", "#EE6AA7");
-        synonymToHexName.put("hotpink3", "#CD6090");
-        synonymToHexName.put("hotpink4", "#8B3A62");
-        synonymToHexName.put("indianred", "#CD5C5C");
-        synonymToHexName.put("indianred1", "#FF6A6A");
-        synonymToHexName.put("indianred2", "#EE6363");
-        synonymToHexName.put("indianred3", "#CD5555");
-        synonymToHexName.put("indianred4", "#8B3A3A");
-        synonymToHexName.put("ivory", "#FFFFF0");
-        synonymToHexName.put("ivory1", "#FFFFF0");
-        synonymToHexName.put("ivory2", "#EEEEE0");
-        synonymToHexName.put("ivory3", "#CDCDC1");
-        synonymToHexName.put("ivory4", "#8B8B83");
-        synonymToHexName.put("khaki", "#F0E68C");
-        synonymToHexName.put("khaki1", "#FFF68F");
-        synonymToHexName.put("khaki2", "#EEE685");
-        synonymToHexName.put("khaki3", "#CDC673");
-        synonymToHexName.put("khaki4", "#8B864E");
-        synonymToHexName.put("lavender", "#E6E6FA");
-        synonymToHexName.put("lavenderblush", "#FFF0F5");
-        synonymToHexName.put("lavenderblush1", "#FFF0F5");
-        synonymToHexName.put("lavenderblush2", "#EEE0E5");
-        synonymToHexName.put("lavenderblush3", "#CDC1C5");
-        synonymToHexName.put("lavenderblush4", "#8B8386");
-        synonymToHexName.put("lawngreen", "#7CFC00");
-        synonymToHexName.put("lemonchiffon", "#FFFACD");
-        synonymToHexName.put("lemonchiffon1", "#FFFACD");
-        synonymToHexName.put("lemonchiffon2", "#EEE9BF");
-        synonymToHexName.put("lemonchiffon3", "#CDC9A5");
-        synonymToHexName.put("lemonchiffon4", "#8B8970");
-        synonymToHexName.put("lightblue", "#ADD8E6");
-        synonymToHexName.put("lightblue1", "#BFEFFF");
-        synonymToHexName.put("lightblue2", "#B2DFEE");
-        synonymToHexName.put("lightblue3", "#9AC0CD");
-        synonymToHexName.put("lightblue4", "#68838B");
-        synonymToHexName.put("lightcoral", "#F08080");
-        synonymToHexName.put("lightcyan", "#E0FFFF");
-        synonymToHexName.put("lightcyan1", "#E0FFFF");
-        synonymToHexName.put("lightcyan2", "#D1EEEE");
-        synonymToHexName.put("lightcyan3", "#B4CDCD");
-        synonymToHexName.put("lightcyan4", "#7A8B8B");
-        synonymToHexName.put("lightgoldenrod", "#EEDD82");
-        synonymToHexName.put("lightgoldenrod1", "#FFEC8B");
-        synonymToHexName.put("lightgoldenrod2", "#EEDC82");
-        synonymToHexName.put("lightgoldenrod3", "#CDBE70");
-        synonymToHexName.put("lightgoldenrod4", "#8B814C");
-        synonymToHexName.put("lightgoldenrodyellow", "#FAFAD2");
-        synonymToHexName.put("lightgray", "#D3D3D3");
-        synonymToHexName.put("lightgreen", "#90EE90");
-        synonymToHexName.put("lightgrey", "#D3D3D3");
-        synonymToHexName.put("lightpink", "#FFB6C1");
-        synonymToHexName.put("lightpink1", "#FFAEB9");
-        synonymToHexName.put("lightpink2", "#EEA2AD");
-        synonymToHexName.put("lightpink3", "#CD8C95");
-        synonymToHexName.put("lightpink4", "#8B5F65");
-        synonymToHexName.put("lightsalmon", "#FFA07A");
-        synonymToHexName.put("lightsalmon1", "#FFA07A");
-        synonymToHexName.put("lightsalmon2", "#EE9572");
-        synonymToHexName.put("lightsalmon3", "#CD8162");
-        synonymToHexName.put("lightsalmon4", "#8B5742");
-        synonymToHexName.put("lightseagreen", "#20B2AA");
-        synonymToHexName.put("lightskyblue", "#87CEFA");
-        synonymToHexName.put("lightskyblue1", "#B0E2FF");
-        synonymToHexName.put("lightskyblue2", "#A4D3EE");
-        synonymToHexName.put("lightskyblue3", "#8DB6CD");
-        synonymToHexName.put("lightskyblue4", "#607B8B");
-        synonymToHexName.put("lightslateblue", "#8470FF");
-        synonymToHexName.put("lightslategray", "#778899");
-        synonymToHexName.put("lightslategrey", "#778899");
-        synonymToHexName.put("lightsteelblue", "#B0C4DE");
-        synonymToHexName.put("lightsteelblue1", "#CAE1FF");
-        synonymToHexName.put("lightsteelblue2", "#BCD2EE");
-        synonymToHexName.put("lightsteelblue3", "#A2B5CD");
-        synonymToHexName.put("lightsteelblue4", "#6E7B8B");
-        synonymToHexName.put("lightyellow", "#FFFFE0");
-        synonymToHexName.put("lightyellow1", "#FFFFE0");
-        synonymToHexName.put("lightyellow2", "#EEEED1");
-        synonymToHexName.put("lightyellow3", "#CDCDB4");
-        synonymToHexName.put("lightyellow4", "#8B8B7A");
-        synonymToHexName.put("limegreen", "#32CD32");
-        synonymToHexName.put("linen", "#FAF0E6");
-        synonymToHexName.put("magenta", "#FF00FF");
-        synonymToHexName.put("magenta1", "#FF00FF");
-        synonymToHexName.put("magenta2", "#EE00EE");
-        synonymToHexName.put("magenta3", "#CD00CD");
-        synonymToHexName.put("magenta4", "#8B008B");
-        synonymToHexName.put("maroon", "#B03060");
-        synonymToHexName.put("maroon1", "#FF34B3");
-        synonymToHexName.put("maroon2", "#EE30A7");
-        synonymToHexName.put("maroon3", "#CD2990");
-        synonymToHexName.put("maroon4", "#8B1C62");
-        synonymToHexName.put("mediumaquamarine", "#66CDAA");
-        synonymToHexName.put("mediumblue", "#0000CD");
-        synonymToHexName.put("mediumorchid", "#BA55D3");
-        synonymToHexName.put("mediumorchid1", "#E066FF");
-        synonymToHexName.put("mediumorchid2", "#D15FEE");
-        synonymToHexName.put("mediumorchid3", "#B452CD");
-        synonymToHexName.put("mediumorchid4", "#7A378B");
-        synonymToHexName.put("mediumpurple", "#9370DB");
-        synonymToHexName.put("mediumpurple1", "#AB82FF");
-        synonymToHexName.put("mediumpurple2", "#9F79EE");
-        synonymToHexName.put("mediumpurple3", "#8968CD");
-        synonymToHexName.put("mediumpurple4", "#5D478B");
-        synonymToHexName.put("mediumseagreen", "#3CB371");
-        synonymToHexName.put("mediumslateblue", "#7B68EE");
-        synonymToHexName.put("mediumspringgreen", "#00FA9A");
-        synonymToHexName.put("mediumturquoise", "#48D1CC");
-        synonymToHexName.put("mediumvioletred", "#C71585");
-        synonymToHexName.put("midnightblue", "#191970");
-        synonymToHexName.put("mintcream", "#F5FFFA");
-        synonymToHexName.put("mistyrose", "#FFE4E1");
-        synonymToHexName.put("mistyrose1", "#FFE4E1");
-        synonymToHexName.put("mistyrose2", "#EED5D2");
-        synonymToHexName.put("mistyrose3", "#CDB7B5");
-        synonymToHexName.put("mistyrose4", "#8B7D7B");
-        synonymToHexName.put("moccasin", "#FFE4B5");
-        synonymToHexName.put("navajowhite", "#FFDEAD");
-        synonymToHexName.put("navajowhite1", "#FFDEAD");
-        synonymToHexName.put("navajowhite2", "#EECFA1");
-        synonymToHexName.put("navajowhite3", "#CDB38B");
-        synonymToHexName.put("navajowhite4", "#8B795E");
-        synonymToHexName.put("navy", "#000080");
-        synonymToHexName.put("navyblue", "#000080");
-        synonymToHexName.put("oldlace", "#FDF5E6");
-        synonymToHexName.put("olivedrab", "#6B8E23");
-        synonymToHexName.put("olivedrab1", "#C0FF3E");
-        synonymToHexName.put("olivedrab2", "#B3EE3A");
-        synonymToHexName.put("olivedrab3", "#9ACD32");
-        synonymToHexName.put("olivedrab4", "#698B22");
-        synonymToHexName.put("orange", "#FFA500");
-        synonymToHexName.put("orange1", "#FFA500");
-        synonymToHexName.put("orange2", "#EE9A00");
-        synonymToHexName.put("orange3", "#CD8500");
-        synonymToHexName.put("orange4", "#8B5A00");
-        synonymToHexName.put("orangered", "#FF4500");
-        synonymToHexName.put("orangered1", "#FF4500");
-        synonymToHexName.put("orangered2", "#EE4000");
-        synonymToHexName.put("orangered3", "#CD3700");
-        synonymToHexName.put("orangered4", "#8B2500");
-        synonymToHexName.put("orchid", "#DA70D6");
-        synonymToHexName.put("orchid1", "#FF83FA");
-        synonymToHexName.put("orchid2", "#EE7AE9");
-        synonymToHexName.put("orchid3", "#CD69C9");
-        synonymToHexName.put("orchid4", "#8B4789");
-        synonymToHexName.put("palegoldenrod", "#EEE8AA");
-        synonymToHexName.put("palegreen", "#98FB98");
-        synonymToHexName.put("palegreen1", "#9AFF9A");
-        synonymToHexName.put("palegreen2", "#90EE90");
-        synonymToHexName.put("palegreen3", "#7CCD7C");
-        synonymToHexName.put("palegreen4", "#548B54");
-        synonymToHexName.put("paleturquoise", "#AFEEEE");
-        synonymToHexName.put("paleturquoise1", "#BBFFFF");
-        synonymToHexName.put("paleturquoise2", "#AEEEEE");
-        synonymToHexName.put("paleturquoise3", "#96CDCD");
-        synonymToHexName.put("paleturquoise4", "#668B8B");
-        synonymToHexName.put("palevioletred", "#DB7093");
-        synonymToHexName.put("palevioletred1", "#FF82AB");
-        synonymToHexName.put("palevioletred2", "#EE799F");
-        synonymToHexName.put("palevioletred3", "#CD6889");
-        synonymToHexName.put("palevioletred4", "#8B475D");
-        synonymToHexName.put("papayawhip", "#FFEFD5");
-        synonymToHexName.put("peachpuff", "#FFDAB9");
-        synonymToHexName.put("peachpuff1", "#FFDAB9");
-        synonymToHexName.put("peachpuff2", "#EECBAD");
-        synonymToHexName.put("peachpuff3", "#CDAF95");
-        synonymToHexName.put("peachpuff4", "#8B7765");
-        synonymToHexName.put("peru", "#CD853F");
-        synonymToHexName.put("pink", "#FFC0CB");
-        synonymToHexName.put("pink1", "#FFB5C5");
-        synonymToHexName.put("pink2", "#EEA9B8");
-        synonymToHexName.put("pink3", "#CD919E");
-        synonymToHexName.put("pink4", "#8B636C");
-        synonymToHexName.put("plum", "#DDA0DD");
-        synonymToHexName.put("plum1", "#FFBBFF");
-        synonymToHexName.put("plum2", "#EEAEEE");
-        synonymToHexName.put("plum3", "#CD96CD");
-        synonymToHexName.put("plum4", "#8B668B");
-        synonymToHexName.put("powderblue", "#B0E0E6");
-        synonymToHexName.put("purple", "#A020F0");
-        synonymToHexName.put("purple1", "#9B30FF");
-        synonymToHexName.put("purple2", "#912CEE");
-        synonymToHexName.put("purple3", "#7D26CD");
-        synonymToHexName.put("purple4", "#551A8B");
-        synonymToHexName.put("red", "#FF0000");
-        synonymToHexName.put("red1", "#FF0000");
-        synonymToHexName.put("red2", "#EE0000");
-        synonymToHexName.put("red3", "#CD0000");
-        synonymToHexName.put("red4", "#8B0000");
-        synonymToHexName.put("rosybrown", "#BC8F8F");
-        synonymToHexName.put("rosybrown1", "#FFC1C1");
-        synonymToHexName.put("rosybrown2", "#EEB4B4");
-        synonymToHexName.put("rosybrown3", "#CD9B9B");
-        synonymToHexName.put("rosybrown4", "#8B6969");
-        synonymToHexName.put("royalblue", "#4169E1");
-        synonymToHexName.put("royalblue1", "#4876FF");
-        synonymToHexName.put("royalblue2", "#436EEE");
-        synonymToHexName.put("royalblue3", "#3A5FCD");
-        synonymToHexName.put("royalblue4", "#27408B");
-        synonymToHexName.put("snewData.addlebrown", "#8B4513");
-        synonymToHexName.put("salmon", "#FA8072");
-        synonymToHexName.put("salmon1", "#FF8C69");
-        synonymToHexName.put("salmon2", "#EE8262");
-        synonymToHexName.put("salmon3", "#CD7054");
-        synonymToHexName.put("salmon4", "#8B4C39");
-        synonymToHexName.put("sandybrown", "#F4A460");
-        synonymToHexName.put("seagreen", "#2E8B57");
-        synonymToHexName.put("seagreen1", "#54FF9F");
-        synonymToHexName.put("seagreen2", "#4EEE94");
-        synonymToHexName.put("seagreen3", "#43CD80");
-        synonymToHexName.put("seagreen4", "#2E8B57");
-        synonymToHexName.put("seashell", "#FFF5EE");
-        synonymToHexName.put("seashell1", "#FFF5EE");
-        synonymToHexName.put("seashell2", "#EEE5DE");
-        synonymToHexName.put("seashell3", "#CDC5BF");
-        synonymToHexName.put("seashell4", "#8B8682");
-        synonymToHexName.put("sienna", "#A0522D");
-        synonymToHexName.put("sienna1", "#FF8247");
-        synonymToHexName.put("sienna2", "#EE7942");
-        synonymToHexName.put("sienna3", "#CD6839");
-        synonymToHexName.put("sienna4", "#8B4726");
-        synonymToHexName.put("skyblue", "#87CEEB");
-        synonymToHexName.put("skyblue1", "#87CEFF");
-        synonymToHexName.put("skyblue2", "#7EC0EE");
-        synonymToHexName.put("skyblue3", "#6CA6CD");
-        synonymToHexName.put("skyblue4", "#4A708B");
-        synonymToHexName.put("slateblue", "#6A5ACD");
-        synonymToHexName.put("slateblue1", "#836FFF");
-        synonymToHexName.put("slateblue2", "#7A67EE");
-        synonymToHexName.put("slateblue3", "#6959CD");
-        synonymToHexName.put("slateblue4", "#473C8B");
-        synonymToHexName.put("slategray", "#708090");
-        synonymToHexName.put("slategray1", "#C6E2FF");
-        synonymToHexName.put("slategray2", "#B9D3EE");
-        synonymToHexName.put("slategray3", "#9FB6CD");
-        synonymToHexName.put("slategray4", "#6C7B8B");
-        synonymToHexName.put("slategrey", "#708090");
-        synonymToHexName.put("snow", "#FFFAFA");
-        synonymToHexName.put("snow1", "#FFFAFA");
-        synonymToHexName.put("snow2", "#EEE9E9");
-        synonymToHexName.put("snow3", "#CDC9C9");
-        synonymToHexName.put("snow4", "#8B8989");
-        synonymToHexName.put("springgreen", "#00FF7F");
-        synonymToHexName.put("springgreen1", "#00FF7F");
-        synonymToHexName.put("springgreen2", "#00EE76");
-        synonymToHexName.put("springgreen3", "#00CD66");
-        synonymToHexName.put("springgreen4", "#008B45");
-        synonymToHexName.put("steelblue", "#4682B4");
-        synonymToHexName.put("steelblue1", "#63B8FF");
-        synonymToHexName.put("steelblue2", "#5CACEE");
-        synonymToHexName.put("steelblue3", "#4F94CD");
-        synonymToHexName.put("steelblue4", "#36648B");
-        synonymToHexName.put("tan", "#D2B48C");
-        synonymToHexName.put("tan1", "#FFA54F");
-        synonymToHexName.put("tan2", "#EE9A49");
-        synonymToHexName.put("tan3", "#CD853F");
-        synonymToHexName.put("tan4", "#8B5A2B");
-        synonymToHexName.put("thistle", "#D8BFD8");
-        synonymToHexName.put("thistle1", "#FFE1FF");
-        synonymToHexName.put("thistle2", "#EED2EE");
-        synonymToHexName.put("thistle3", "#CDB5CD");
-        synonymToHexName.put("thistle4", "#8B7B8B");
-        synonymToHexName.put("tomato", "#FF6347");
-        synonymToHexName.put("tomato1", "#FF6347");
-        synonymToHexName.put("tomato2", "#EE5C42");
-        synonymToHexName.put("tomato3", "#CD4F39");
-        synonymToHexName.put("tomato4", "#8B3626");
-        synonymToHexName.put("turquoise", "#40E0D0");
-        synonymToHexName.put("turquoise1", "#00F5FF");
-        synonymToHexName.put("turquoise2", "#00E5EE");
-        synonymToHexName.put("turquoise3", "#00C5CD");
-        synonymToHexName.put("turquoise4", "#00868B");
-        synonymToHexName.put("violet", "#EE82EE");
-        synonymToHexName.put("violetred", "#D02090");
-        synonymToHexName.put("violetred1", "#FF3E96");
-        synonymToHexName.put("violetred2", "#EE3A8C");
-        synonymToHexName.put("violetred3", "#CD3278");
-        synonymToHexName.put("violetred4", "#8B2252");
-        synonymToHexName.put("wheat", "#F5DEB3");
-        synonymToHexName.put("wheat1", "#FFE7BA");
-        synonymToHexName.put("wheat2", "#EED8AE");
-        synonymToHexName.put("wheat3", "#CDBA96");
-        synonymToHexName.put("wheat4", "#8B7E66");
-        synonymToHexName.put("whitesmoke", "#F5F5F5");
-        synonymToHexName.put("yellow", "#FFFF00");
-        synonymToHexName.put("yellow1", "#FFFF00");
-        synonymToHexName.put("yellow2", "#EEEE00");
-        synonymToHexName.put("yellow3", "#CDCD00");
-        synonymToHexName.put("yellow4", "#8B8B00");
-        synonymToHexName.put("yellowgreen", "#9ACD32");
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 49d587cf37..33d7761a60 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -16,6 +16,7 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import java.util.Arrays;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -81,7 +82,7 @@ public final class GPar {
     public static RList createNew() {
         Object[] data = new Object[GP_LENGTH];
         Arrays.fill(data, RNull.instance);
-        data[GP_FILL] = "black";
+        data[GP_FILL] = "grey";
         data[GP_COL] = "black";
         data[GP_GAMMA] = newDoubleVec(0);
         data[GP_LTY] = "solid"; // TODO: LineType enum...
@@ -119,13 +120,13 @@ public final class GPar {
         }
 
         @Override
-        public String getColor() {
-            return getHexColor(GP_COL);
+        public GridColor getColor() {
+            return getGridColor(GP_COL);
         }
 
         @Override
-        public void setColor(String hexCode) {
-            data[GP_COL] = hexCode;
+        public void setColor(GridColor color) {
+            data[GP_COL] = GridColorUtils.gridColorToRString(color);
         }
 
         @Override
@@ -139,21 +140,17 @@ public final class GPar {
         }
 
         @Override
-        public String getFillColor() {
-            return getHexColor(GP_FILL);
+        public GridColor getFillColor() {
+            return getGridColor(GP_FILL);
         }
 
         @Override
-        public void setFillColor(String hexCode) {
-            data[GP_FILL] = hexCode;
+        public void setFillColor(GridColor color) {
+            data[GP_FILL] = GridColorUtils.gridColorToRString(color);
         }
 
-        private String getHexColor(int index) {
-            String result = RRuntime.asString(data[index]);
-            if (!result.startsWith("#")) {
-                result = ColorNames.findByName(result);
-            }
-            return result == null ? "#FFFFFF" : result;
+        private GridColor getGridColor(int index) {
+            return GridColorUtils.gridColorFromString(RRuntime.asString(data[index]));
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
new file mode 100644
index 0000000000..1fc036ea84
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
@@ -0,0 +1,745 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1997-2014, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+
+public class GridColorUtils {
+    private static HashMap<String, Object> synonymToColor;
+
+    /**
+     * Converts the representation of color used within R, e.g. as value for
+     * {@code gpar(col='value')}, to our internal representation that grid device should understand.
+     * The acceptable color formats are: name of known color, HTML style hex value, and HTML style
+     * hex value including alpha.
+     */
+    public static GridColor gridColorFromString(String value) {
+        if (value.startsWith("#") && (value.length() == 7 || value.length() == 9)) {
+            return parseHex(value);
+        }
+
+        Object result = findByName(value);
+        if (result == null) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid color '" + value + "'.");
+        }
+        if (result instanceof String) {
+            return parseHex((String) result);
+        }
+        assert result instanceof GridColor : "synonyms map should only contain Strings and GridColors";
+        return (GridColor) result;
+    }
+
+    public static String gridColorToRString(GridColor color) {
+        if (color.getAlpha() == GridColor.OPAQUE_ALPHA) {
+            return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
+        }
+        return String.format("#%02x%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
+    }
+
+    private static GridColor parseHex(String value) {
+        // hex format, e.g. #ffffff
+        int red = Integer.parseInt(value.substring(1, 3), 16);
+        int green = Integer.parseInt(value.substring(3, 5), 16);
+        int blue = Integer.parseInt(value.substring(5, 7), 16);
+        int alpha = GridColor.OPAQUE_ALPHA;
+        if (value.length() == 9) {
+            alpha = Integer.parseInt(value.substring(7, 9), 16);
+        }
+        return new GridColor(red, green, blue, alpha);
+    }
+
+    private static Object findByName(String synonym) {
+        if (synonymToColor == null) {
+            initialize();
+        }
+        return synonymToColor.get(normalizeColorName(synonym));
+    }
+
+    // GnuR compares the user given color name to the dictionary ignoring spaces and case. We remove
+    // the spaces and make it lowercase and then use normal string comparison.
+    private static String normalizeColorName(String synonym) {
+        boolean isNormalized = true;
+        for (int i = 0; i < synonym.length(); i++) {
+            char c = synonym.charAt(i);
+            isNormalized &= (!Character.isAlphabetic(c) || Character.isLowerCase(c)) && c != ' ';
+        }
+        return isNormalized ? synonym : synonym.replace(" ", "").toLowerCase(Locale.ROOT);
+    }
+
+    private static void initialize() {
+        synonymToColor = new HashMap<>(700);
+        synonymToColor.put("transparent", GridColor.TRANSPARENT);
+        synonymToColor.put("NA", GridColor.TRANSPARENT);
+        synonymToColor.put("white", "#FFFFFF");
+        synonymToColor.put("aliceblue", "#F0F8FF");
+        synonymToColor.put("antiquewhite", "#FAEBD7");
+        synonymToColor.put("antiquewhite1", "#FFEFDB");
+        synonymToColor.put("antiquewhite2", "#EEDFCC");
+        synonymToColor.put("antiquewhite3", "#CDC0B0");
+        synonymToColor.put("antiquewhite4", "#8B8378");
+        synonymToColor.put("aquamarine", "#7FFFD4");
+        synonymToColor.put("aquamarine1", "#7FFFD4");
+        synonymToColor.put("aquamarine2", "#76EEC6");
+        synonymToColor.put("aquamarine3", "#66CDAA");
+        synonymToColor.put("aquamarine4", "#458B74");
+        synonymToColor.put("azure", "#F0FFFF");
+        synonymToColor.put("azure1", "#F0FFFF");
+        synonymToColor.put("azure2", "#E0EEEE");
+        synonymToColor.put("azure3", "#C1CDCD");
+        synonymToColor.put("azure4", "#838B8B");
+        synonymToColor.put("beige", "#F5F5DC");
+        synonymToColor.put("bisque", "#FFE4C4");
+        synonymToColor.put("bisque1", "#FFE4C4");
+        synonymToColor.put("bisque2", "#EED5B7");
+        synonymToColor.put("bisque3", "#CDB79E");
+        synonymToColor.put("bisque4", "#8B7D6B");
+        synonymToColor.put("black", "#000000");
+        synonymToColor.put("blanchedalmond", "#FFEBCD");
+        synonymToColor.put("blue", "#0000FF");
+        synonymToColor.put("blue1", "#0000FF");
+        synonymToColor.put("blue2", "#0000EE");
+        synonymToColor.put("blue3", "#0000CD");
+        synonymToColor.put("blue4", "#00008B");
+        synonymToColor.put("blueviolet", "#8A2BE2");
+        synonymToColor.put("brown", "#A52A2A");
+        synonymToColor.put("brown1", "#FF4040");
+        synonymToColor.put("brown2", "#EE3B3B");
+        synonymToColor.put("brown3", "#CD3333");
+        synonymToColor.put("brown4", "#8B2323");
+        synonymToColor.put("burlywood", "#DEB887");
+        synonymToColor.put("burlywood1", "#FFD39B");
+        synonymToColor.put("burlywood2", "#EEC591");
+        synonymToColor.put("burlywood3", "#CDAA7D");
+        synonymToColor.put("burlywood4", "#8B7355");
+        synonymToColor.put("cadetblue", "#5F9EA0");
+        synonymToColor.put("cadetblue1", "#98F5FF");
+        synonymToColor.put("cadetblue2", "#8EE5EE");
+        synonymToColor.put("cadetblue3", "#7AC5CD");
+        synonymToColor.put("cadetblue4", "#53868B");
+        synonymToColor.put("chartreuse", "#7FFF00");
+        synonymToColor.put("chartreuse1", "#7FFF00");
+        synonymToColor.put("chartreuse2", "#76EE00");
+        synonymToColor.put("chartreuse3", "#66CD00");
+        synonymToColor.put("chartreuse4", "#458B00");
+        synonymToColor.put("chocolate", "#D2691E");
+        synonymToColor.put("chocolate1", "#FF7F24");
+        synonymToColor.put("chocolate2", "#EE7621");
+        synonymToColor.put("chocolate3", "#CD661D");
+        synonymToColor.put("chocolate4", "#8B4513");
+        synonymToColor.put("coral", "#FF7F50");
+        synonymToColor.put("coral1", "#FF7256");
+        synonymToColor.put("coral2", "#EE6A50");
+        synonymToColor.put("coral3", "#CD5B45");
+        synonymToColor.put("coral4", "#8B3E2F");
+        synonymToColor.put("cornflowerblue", "#6495ED");
+        synonymToColor.put("cornsilk", "#FFF8DC");
+        synonymToColor.put("cornsilk1", "#FFF8DC");
+        synonymToColor.put("cornsilk2", "#EEE8CD");
+        synonymToColor.put("cornsilk3", "#CDC8B1");
+        synonymToColor.put("cornsilk4", "#8B8878");
+        synonymToColor.put("cyan", "#00FFFF");
+        synonymToColor.put("cyan1", "#00FFFF");
+        synonymToColor.put("cyan2", "#00EEEE");
+        synonymToColor.put("cyan3", "#00CDCD");
+        synonymToColor.put("cyan4", "#008B8B");
+        synonymToColor.put("darkblue", "#00008B");
+        synonymToColor.put("darkcyan", "#008B8B");
+        synonymToColor.put("darkgoldenrod", "#B8860B");
+        synonymToColor.put("darkgoldenrod1", "#FFB90F");
+        synonymToColor.put("darkgoldenrod2", "#EEAD0E");
+        synonymToColor.put("darkgoldenrod3", "#CD950C");
+        synonymToColor.put("darkgoldenrod4", "#8B6508");
+        synonymToColor.put("darkgray", "#A9A9A9");
+        synonymToColor.put("darkgreen", "#006400");
+        synonymToColor.put("darkgrey", "#A9A9A9");
+        synonymToColor.put("darkkhaki", "#BDB76B");
+        synonymToColor.put("darkmagenta", "#8B008B");
+        synonymToColor.put("darkolivegreen", "#556B2F");
+        synonymToColor.put("darkolivegreen1", "#CAFF70");
+        synonymToColor.put("darkolivegreen2", "#BCEE68");
+        synonymToColor.put("darkolivegreen3", "#A2CD5A");
+        synonymToColor.put("darkolivegreen4", "#6E8B3D");
+        synonymToColor.put("darkorange", "#FF8C00");
+        synonymToColor.put("darkorange1", "#FF7F00");
+        synonymToColor.put("darkorange2", "#EE7600");
+        synonymToColor.put("darkorange3", "#CD6600");
+        synonymToColor.put("darkorange4", "#8B4500");
+        synonymToColor.put("darkorchid", "#9932CC");
+        synonymToColor.put("darkorchid1", "#BF3EFF");
+        synonymToColor.put("darkorchid2", "#B23AEE");
+        synonymToColor.put("darkorchid3", "#9A32CD");
+        synonymToColor.put("darkorchid4", "#68228B");
+        synonymToColor.put("darkred", "#8B0000");
+        synonymToColor.put("darksalmon", "#E9967A");
+        synonymToColor.put("darkseagreen", "#8FBC8F");
+        synonymToColor.put("darkseagreen1", "#C1FFC1");
+        synonymToColor.put("darkseagreen2", "#B4EEB4");
+        synonymToColor.put("darkseagreen3", "#9BCD9B");
+        synonymToColor.put("darkseagreen4", "#698B69");
+        synonymToColor.put("darkslateblue", "#483D8B");
+        synonymToColor.put("darkslategray", "#2F4F4F");
+        synonymToColor.put("darkslategray1", "#97FFFF");
+        synonymToColor.put("darkslategray2", "#8DEEEE");
+        synonymToColor.put("darkslategray3", "#79CDCD");
+        synonymToColor.put("darkslategray4", "#528B8B");
+        synonymToColor.put("darkslategrey", "#2F4F4F");
+        synonymToColor.put("darkturquoise", "#00CED1");
+        synonymToColor.put("darkviolet", "#9400D3");
+        synonymToColor.put("deeppink", "#FF1493");
+        synonymToColor.put("deeppink1", "#FF1493");
+        synonymToColor.put("deeppink2", "#EE1289");
+        synonymToColor.put("deeppink3", "#CD1076");
+        synonymToColor.put("deeppink4", "#8B0A50");
+        synonymToColor.put("deepskyblue", "#00BFFF");
+        synonymToColor.put("deepskyblue1", "#00BFFF");
+        synonymToColor.put("deepskyblue2", "#00B2EE");
+        synonymToColor.put("deepskyblue3", "#009ACD");
+        synonymToColor.put("deepskyblue4", "#00688B");
+        synonymToColor.put("dimgray", "#696969");
+        synonymToColor.put("dimgrey", "#696969");
+        synonymToColor.put("dodgerblue", "#1E90FF");
+        synonymToColor.put("dodgerblue1", "#1E90FF");
+        synonymToColor.put("dodgerblue2", "#1C86EE");
+        synonymToColor.put("dodgerblue3", "#1874CD");
+        synonymToColor.put("dodgerblue4", "#104E8B");
+        synonymToColor.put("firebrick", "#B22222");
+        synonymToColor.put("firebrick1", "#FF3030");
+        synonymToColor.put("firebrick2", "#EE2C2C");
+        synonymToColor.put("firebrick3", "#CD2626");
+        synonymToColor.put("firebrick4", "#8B1A1A");
+        synonymToColor.put("floralwhite", "#FFFAF0");
+        synonymToColor.put("forestgreen", "#228B22");
+        synonymToColor.put("gainsboro", "#DCDCDC");
+        synonymToColor.put("ghostwhite", "#F8F8FF");
+        synonymToColor.put("gold", "#FFD700");
+        synonymToColor.put("gold1", "#FFD700");
+        synonymToColor.put("gold2", "#EEC900");
+        synonymToColor.put("gold3", "#CDAD00");
+        synonymToColor.put("gold4", "#8B7500");
+        synonymToColor.put("goldenrod", "#DAA520");
+        synonymToColor.put("goldenrod1", "#FFC125");
+        synonymToColor.put("goldenrod2", "#EEB422");
+        synonymToColor.put("goldenrod3", "#CD9B1D");
+        synonymToColor.put("goldenrod4", "#8B6914");
+        synonymToColor.put("gray", "#BEBEBE");
+        synonymToColor.put("gray0", "#000000");
+        synonymToColor.put("gray1", "#030303");
+        synonymToColor.put("gray2", "#050505");
+        synonymToColor.put("gray3", "#080808");
+        synonymToColor.put("gray4", "#0A0A0A");
+        synonymToColor.put("gray5", "#0D0D0D");
+        synonymToColor.put("gray6", "#0F0F0F");
+        synonymToColor.put("gray7", "#121212");
+        synonymToColor.put("gray8", "#141414");
+        synonymToColor.put("gray9", "#171717");
+        synonymToColor.put("gray10", "#1A1A1A");
+        synonymToColor.put("gray11", "#1C1C1C");
+        synonymToColor.put("gray12", "#1F1F1F");
+        synonymToColor.put("gray13", "#212121");
+        synonymToColor.put("gray14", "#242424");
+        synonymToColor.put("gray15", "#262626");
+        synonymToColor.put("gray16", "#292929");
+        synonymToColor.put("gray17", "#2B2B2B");
+        synonymToColor.put("gray18", "#2E2E2E");
+        synonymToColor.put("gray19", "#303030");
+        synonymToColor.put("gray20", "#333333");
+        synonymToColor.put("gray21", "#363636");
+        synonymToColor.put("gray22", "#383838");
+        synonymToColor.put("gray23", "#3B3B3B");
+        synonymToColor.put("gray24", "#3D3D3D");
+        synonymToColor.put("gray25", "#404040");
+        synonymToColor.put("gray26", "#424242");
+        synonymToColor.put("gray27", "#454545");
+        synonymToColor.put("gray28", "#474747");
+        synonymToColor.put("gray29", "#4A4A4A");
+        synonymToColor.put("gray30", "#4D4D4D");
+        synonymToColor.put("gray31", "#4F4F4F");
+        synonymToColor.put("gray32", "#525252");
+        synonymToColor.put("gray33", "#545454");
+        synonymToColor.put("gray34", "#575757");
+        synonymToColor.put("gray35", "#595959");
+        synonymToColor.put("gray36", "#5C5C5C");
+        synonymToColor.put("gray37", "#5E5E5E");
+        synonymToColor.put("gray38", "#616161");
+        synonymToColor.put("gray39", "#636363");
+        synonymToColor.put("gray40", "#666666");
+        synonymToColor.put("gray41", "#696969");
+        synonymToColor.put("gray42", "#6B6B6B");
+        synonymToColor.put("gray43", "#6E6E6E");
+        synonymToColor.put("gray44", "#707070");
+        synonymToColor.put("gray45", "#737373");
+        synonymToColor.put("gray46", "#757575");
+        synonymToColor.put("gray47", "#787878");
+        synonymToColor.put("gray48", "#7A7A7A");
+        synonymToColor.put("gray49", "#7D7D7D");
+        synonymToColor.put("gray50", "#7F7F7F");
+        synonymToColor.put("gray51", "#828282");
+        synonymToColor.put("gray52", "#858585");
+        synonymToColor.put("gray53", "#878787");
+        synonymToColor.put("gray54", "#8A8A8A");
+        synonymToColor.put("gray55", "#8C8C8C");
+        synonymToColor.put("gray56", "#8F8F8F");
+        synonymToColor.put("gray57", "#919191");
+        synonymToColor.put("gray58", "#949494");
+        synonymToColor.put("gray59", "#969696");
+        synonymToColor.put("gray60", "#999999");
+        synonymToColor.put("gray61", "#9C9C9C");
+        synonymToColor.put("gray62", "#9E9E9E");
+        synonymToColor.put("gray63", "#A1A1A1");
+        synonymToColor.put("gray64", "#A3A3A3");
+        synonymToColor.put("gray65", "#A6A6A6");
+        synonymToColor.put("gray66", "#A8A8A8");
+        synonymToColor.put("gray67", "#ABABAB");
+        synonymToColor.put("gray68", "#ADADAD");
+        synonymToColor.put("gray69", "#B0B0B0");
+        synonymToColor.put("gray70", "#B3B3B3");
+        synonymToColor.put("gray71", "#B5B5B5");
+        synonymToColor.put("gray72", "#B8B8B8");
+        synonymToColor.put("gray73", "#BABABA");
+        synonymToColor.put("gray74", "#BDBDBD");
+        synonymToColor.put("gray75", "#BFBFBF");
+        synonymToColor.put("gray76", "#C2C2C2");
+        synonymToColor.put("gray77", "#C4C4C4");
+        synonymToColor.put("gray78", "#C7C7C7");
+        synonymToColor.put("gray79", "#C9C9C9");
+        synonymToColor.put("gray80", "#CCCCCC");
+        synonymToColor.put("gray81", "#CFCFCF");
+        synonymToColor.put("gray82", "#D1D1D1");
+        synonymToColor.put("gray83", "#D4D4D4");
+        synonymToColor.put("gray84", "#D6D6D6");
+        synonymToColor.put("gray85", "#D9D9D9");
+        synonymToColor.put("gray86", "#DBDBDB");
+        synonymToColor.put("gray87", "#DEDEDE");
+        synonymToColor.put("gray88", "#E0E0E0");
+        synonymToColor.put("gray89", "#E3E3E3");
+        synonymToColor.put("gray90", "#E5E5E5");
+        synonymToColor.put("gray91", "#E8E8E8");
+        synonymToColor.put("gray92", "#EBEBEB");
+        synonymToColor.put("gray93", "#EDEDED");
+        synonymToColor.put("gray94", "#F0F0F0");
+        synonymToColor.put("gray95", "#F2F2F2");
+        synonymToColor.put("gray96", "#F5F5F5");
+        synonymToColor.put("gray97", "#F7F7F7");
+        synonymToColor.put("gray98", "#FAFAFA");
+        synonymToColor.put("gray99", "#FCFCFC");
+        synonymToColor.put("gray100", "#FFFFFF");
+        synonymToColor.put("green", "#00FF00");
+        synonymToColor.put("green1", "#00FF00");
+        synonymToColor.put("green2", "#00EE00");
+        synonymToColor.put("green3", "#00CD00");
+        synonymToColor.put("green4", "#008B00");
+        synonymToColor.put("greenyellow", "#ADFF2F");
+        synonymToColor.put("grey", "#BEBEBE");
+        synonymToColor.put("grey0", "#000000");
+        synonymToColor.put("grey1", "#030303");
+        synonymToColor.put("grey2", "#050505");
+        synonymToColor.put("grey3", "#080808");
+        synonymToColor.put("grey4", "#0A0A0A");
+        synonymToColor.put("grey5", "#0D0D0D");
+        synonymToColor.put("grey6", "#0F0F0F");
+        synonymToColor.put("grey7", "#121212");
+        synonymToColor.put("grey8", "#141414");
+        synonymToColor.put("grey9", "#171717");
+        synonymToColor.put("grey10", "#1A1A1A");
+        synonymToColor.put("grey11", "#1C1C1C");
+        synonymToColor.put("grey12", "#1F1F1F");
+        synonymToColor.put("grey13", "#212121");
+        synonymToColor.put("grey14", "#242424");
+        synonymToColor.put("grey15", "#262626");
+        synonymToColor.put("grey16", "#292929");
+        synonymToColor.put("grey17", "#2B2B2B");
+        synonymToColor.put("grey18", "#2E2E2E");
+        synonymToColor.put("grey19", "#303030");
+        synonymToColor.put("grey20", "#333333");
+        synonymToColor.put("grey21", "#363636");
+        synonymToColor.put("grey22", "#383838");
+        synonymToColor.put("grey23", "#3B3B3B");
+        synonymToColor.put("grey24", "#3D3D3D");
+        synonymToColor.put("grey25", "#404040");
+        synonymToColor.put("grey26", "#424242");
+        synonymToColor.put("grey27", "#454545");
+        synonymToColor.put("grey28", "#474747");
+        synonymToColor.put("grey29", "#4A4A4A");
+        synonymToColor.put("grey30", "#4D4D4D");
+        synonymToColor.put("grey31", "#4F4F4F");
+        synonymToColor.put("grey32", "#525252");
+        synonymToColor.put("grey33", "#545454");
+        synonymToColor.put("grey34", "#575757");
+        synonymToColor.put("grey35", "#595959");
+        synonymToColor.put("grey36", "#5C5C5C");
+        synonymToColor.put("grey37", "#5E5E5E");
+        synonymToColor.put("grey38", "#616161");
+        synonymToColor.put("grey39", "#636363");
+        synonymToColor.put("grey40", "#666666");
+        synonymToColor.put("grey41", "#696969");
+        synonymToColor.put("grey42", "#6B6B6B");
+        synonymToColor.put("grey43", "#6E6E6E");
+        synonymToColor.put("grey44", "#707070");
+        synonymToColor.put("grey45", "#737373");
+        synonymToColor.put("grey46", "#757575");
+        synonymToColor.put("grey47", "#787878");
+        synonymToColor.put("grey48", "#7A7A7A");
+        synonymToColor.put("grey49", "#7D7D7D");
+        synonymToColor.put("grey50", "#7F7F7F");
+        synonymToColor.put("grey51", "#828282");
+        synonymToColor.put("grey52", "#858585");
+        synonymToColor.put("grey53", "#878787");
+        synonymToColor.put("grey54", "#8A8A8A");
+        synonymToColor.put("grey55", "#8C8C8C");
+        synonymToColor.put("grey56", "#8F8F8F");
+        synonymToColor.put("grey57", "#919191");
+        synonymToColor.put("grey58", "#949494");
+        synonymToColor.put("grey59", "#969696");
+        synonymToColor.put("grey60", "#999999");
+        synonymToColor.put("grey61", "#9C9C9C");
+        synonymToColor.put("grey62", "#9E9E9E");
+        synonymToColor.put("grey63", "#A1A1A1");
+        synonymToColor.put("grey64", "#A3A3A3");
+        synonymToColor.put("grey65", "#A6A6A6");
+        synonymToColor.put("grey66", "#A8A8A8");
+        synonymToColor.put("grey67", "#ABABAB");
+        synonymToColor.put("grey68", "#ADADAD");
+        synonymToColor.put("grey69", "#B0B0B0");
+        synonymToColor.put("grey70", "#B3B3B3");
+        synonymToColor.put("grey71", "#B5B5B5");
+        synonymToColor.put("grey72", "#B8B8B8");
+        synonymToColor.put("grey73", "#BABABA");
+        synonymToColor.put("grey74", "#BDBDBD");
+        synonymToColor.put("grey75", "#BFBFBF");
+        synonymToColor.put("grey76", "#C2C2C2");
+        synonymToColor.put("grey77", "#C4C4C4");
+        synonymToColor.put("grey78", "#C7C7C7");
+        synonymToColor.put("grey79", "#C9C9C9");
+        synonymToColor.put("grey80", "#CCCCCC");
+        synonymToColor.put("grey81", "#CFCFCF");
+        synonymToColor.put("grey82", "#D1D1D1");
+        synonymToColor.put("grey83", "#D4D4D4");
+        synonymToColor.put("grey84", "#D6D6D6");
+        synonymToColor.put("grey85", "#D9D9D9");
+        synonymToColor.put("grey86", "#DBDBDB");
+        synonymToColor.put("grey87", "#DEDEDE");
+        synonymToColor.put("grey88", "#E0E0E0");
+        synonymToColor.put("grey89", "#E3E3E3");
+        synonymToColor.put("grey90", "#E5E5E5");
+        synonymToColor.put("grey91", "#E8E8E8");
+        synonymToColor.put("grey92", "#EBEBEB");
+        synonymToColor.put("grey93", "#EDEDED");
+        synonymToColor.put("grey94", "#F0F0F0");
+        synonymToColor.put("grey95", "#F2F2F2");
+        synonymToColor.put("grey96", "#F5F5F5");
+        synonymToColor.put("grey97", "#F7F7F7");
+        synonymToColor.put("grey98", "#FAFAFA");
+        synonymToColor.put("grey99", "#FCFCFC");
+        synonymToColor.put("grey100", "#FFFFFF");
+        synonymToColor.put("honeydew", "#F0FFF0");
+        synonymToColor.put("honeydew1", "#F0FFF0");
+        synonymToColor.put("honeydew2", "#E0EEE0");
+        synonymToColor.put("honeydew3", "#C1CDC1");
+        synonymToColor.put("honeydew4", "#838B83");
+        synonymToColor.put("hotpink", "#FF69B4");
+        synonymToColor.put("hotpink1", "#FF6EB4");
+        synonymToColor.put("hotpink2", "#EE6AA7");
+        synonymToColor.put("hotpink3", "#CD6090");
+        synonymToColor.put("hotpink4", "#8B3A62");
+        synonymToColor.put("indianred", "#CD5C5C");
+        synonymToColor.put("indianred1", "#FF6A6A");
+        synonymToColor.put("indianred2", "#EE6363");
+        synonymToColor.put("indianred3", "#CD5555");
+        synonymToColor.put("indianred4", "#8B3A3A");
+        synonymToColor.put("ivory", "#FFFFF0");
+        synonymToColor.put("ivory1", "#FFFFF0");
+        synonymToColor.put("ivory2", "#EEEEE0");
+        synonymToColor.put("ivory3", "#CDCDC1");
+        synonymToColor.put("ivory4", "#8B8B83");
+        synonymToColor.put("khaki", "#F0E68C");
+        synonymToColor.put("khaki1", "#FFF68F");
+        synonymToColor.put("khaki2", "#EEE685");
+        synonymToColor.put("khaki3", "#CDC673");
+        synonymToColor.put("khaki4", "#8B864E");
+        synonymToColor.put("lavender", "#E6E6FA");
+        synonymToColor.put("lavenderblush", "#FFF0F5");
+        synonymToColor.put("lavenderblush1", "#FFF0F5");
+        synonymToColor.put("lavenderblush2", "#EEE0E5");
+        synonymToColor.put("lavenderblush3", "#CDC1C5");
+        synonymToColor.put("lavenderblush4", "#8B8386");
+        synonymToColor.put("lawngreen", "#7CFC00");
+        synonymToColor.put("lemonchiffon", "#FFFACD");
+        synonymToColor.put("lemonchiffon1", "#FFFACD");
+        synonymToColor.put("lemonchiffon2", "#EEE9BF");
+        synonymToColor.put("lemonchiffon3", "#CDC9A5");
+        synonymToColor.put("lemonchiffon4", "#8B8970");
+        synonymToColor.put("lightblue", "#ADD8E6");
+        synonymToColor.put("lightblue1", "#BFEFFF");
+        synonymToColor.put("lightblue2", "#B2DFEE");
+        synonymToColor.put("lightblue3", "#9AC0CD");
+        synonymToColor.put("lightblue4", "#68838B");
+        synonymToColor.put("lightcoral", "#F08080");
+        synonymToColor.put("lightcyan", "#E0FFFF");
+        synonymToColor.put("lightcyan1", "#E0FFFF");
+        synonymToColor.put("lightcyan2", "#D1EEEE");
+        synonymToColor.put("lightcyan3", "#B4CDCD");
+        synonymToColor.put("lightcyan4", "#7A8B8B");
+        synonymToColor.put("lightgoldenrod", "#EEDD82");
+        synonymToColor.put("lightgoldenrod1", "#FFEC8B");
+        synonymToColor.put("lightgoldenrod2", "#EEDC82");
+        synonymToColor.put("lightgoldenrod3", "#CDBE70");
+        synonymToColor.put("lightgoldenrod4", "#8B814C");
+        synonymToColor.put("lightgoldenrodyellow", "#FAFAD2");
+        synonymToColor.put("lightgray", "#D3D3D3");
+        synonymToColor.put("lightgreen", "#90EE90");
+        synonymToColor.put("lightgrey", "#D3D3D3");
+        synonymToColor.put("lightpink", "#FFB6C1");
+        synonymToColor.put("lightpink1", "#FFAEB9");
+        synonymToColor.put("lightpink2", "#EEA2AD");
+        synonymToColor.put("lightpink3", "#CD8C95");
+        synonymToColor.put("lightpink4", "#8B5F65");
+        synonymToColor.put("lightsalmon", "#FFA07A");
+        synonymToColor.put("lightsalmon1", "#FFA07A");
+        synonymToColor.put("lightsalmon2", "#EE9572");
+        synonymToColor.put("lightsalmon3", "#CD8162");
+        synonymToColor.put("lightsalmon4", "#8B5742");
+        synonymToColor.put("lightseagreen", "#20B2AA");
+        synonymToColor.put("lightskyblue", "#87CEFA");
+        synonymToColor.put("lightskyblue1", "#B0E2FF");
+        synonymToColor.put("lightskyblue2", "#A4D3EE");
+        synonymToColor.put("lightskyblue3", "#8DB6CD");
+        synonymToColor.put("lightskyblue4", "#607B8B");
+        synonymToColor.put("lightslateblue", "#8470FF");
+        synonymToColor.put("lightslategray", "#778899");
+        synonymToColor.put("lightslategrey", "#778899");
+        synonymToColor.put("lightsteelblue", "#B0C4DE");
+        synonymToColor.put("lightsteelblue1", "#CAE1FF");
+        synonymToColor.put("lightsteelblue2", "#BCD2EE");
+        synonymToColor.put("lightsteelblue3", "#A2B5CD");
+        synonymToColor.put("lightsteelblue4", "#6E7B8B");
+        synonymToColor.put("lightyellow", "#FFFFE0");
+        synonymToColor.put("lightyellow1", "#FFFFE0");
+        synonymToColor.put("lightyellow2", "#EEEED1");
+        synonymToColor.put("lightyellow3", "#CDCDB4");
+        synonymToColor.put("lightyellow4", "#8B8B7A");
+        synonymToColor.put("limegreen", "#32CD32");
+        synonymToColor.put("linen", "#FAF0E6");
+        synonymToColor.put("magenta", "#FF00FF");
+        synonymToColor.put("magenta1", "#FF00FF");
+        synonymToColor.put("magenta2", "#EE00EE");
+        synonymToColor.put("magenta3", "#CD00CD");
+        synonymToColor.put("magenta4", "#8B008B");
+        synonymToColor.put("maroon", "#B03060");
+        synonymToColor.put("maroon1", "#FF34B3");
+        synonymToColor.put("maroon2", "#EE30A7");
+        synonymToColor.put("maroon3", "#CD2990");
+        synonymToColor.put("maroon4", "#8B1C62");
+        synonymToColor.put("mediumaquamarine", "#66CDAA");
+        synonymToColor.put("mediumblue", "#0000CD");
+        synonymToColor.put("mediumorchid", "#BA55D3");
+        synonymToColor.put("mediumorchid1", "#E066FF");
+        synonymToColor.put("mediumorchid2", "#D15FEE");
+        synonymToColor.put("mediumorchid3", "#B452CD");
+        synonymToColor.put("mediumorchid4", "#7A378B");
+        synonymToColor.put("mediumpurple", "#9370DB");
+        synonymToColor.put("mediumpurple1", "#AB82FF");
+        synonymToColor.put("mediumpurple2", "#9F79EE");
+        synonymToColor.put("mediumpurple3", "#8968CD");
+        synonymToColor.put("mediumpurple4", "#5D478B");
+        synonymToColor.put("mediumseagreen", "#3CB371");
+        synonymToColor.put("mediumslateblue", "#7B68EE");
+        synonymToColor.put("mediumspringgreen", "#00FA9A");
+        synonymToColor.put("mediumturquoise", "#48D1CC");
+        synonymToColor.put("mediumvioletred", "#C71585");
+        synonymToColor.put("midnightblue", "#191970");
+        synonymToColor.put("mintcream", "#F5FFFA");
+        synonymToColor.put("mistyrose", "#FFE4E1");
+        synonymToColor.put("mistyrose1", "#FFE4E1");
+        synonymToColor.put("mistyrose2", "#EED5D2");
+        synonymToColor.put("mistyrose3", "#CDB7B5");
+        synonymToColor.put("mistyrose4", "#8B7D7B");
+        synonymToColor.put("moccasin", "#FFE4B5");
+        synonymToColor.put("navajowhite", "#FFDEAD");
+        synonymToColor.put("navajowhite1", "#FFDEAD");
+        synonymToColor.put("navajowhite2", "#EECFA1");
+        synonymToColor.put("navajowhite3", "#CDB38B");
+        synonymToColor.put("navajowhite4", "#8B795E");
+        synonymToColor.put("navy", "#000080");
+        synonymToColor.put("navyblue", "#000080");
+        synonymToColor.put("oldlace", "#FDF5E6");
+        synonymToColor.put("olivedrab", "#6B8E23");
+        synonymToColor.put("olivedrab1", "#C0FF3E");
+        synonymToColor.put("olivedrab2", "#B3EE3A");
+        synonymToColor.put("olivedrab3", "#9ACD32");
+        synonymToColor.put("olivedrab4", "#698B22");
+        synonymToColor.put("orange", "#FFA500");
+        synonymToColor.put("orange1", "#FFA500");
+        synonymToColor.put("orange2", "#EE9A00");
+        synonymToColor.put("orange3", "#CD8500");
+        synonymToColor.put("orange4", "#8B5A00");
+        synonymToColor.put("orangered", "#FF4500");
+        synonymToColor.put("orangered1", "#FF4500");
+        synonymToColor.put("orangered2", "#EE4000");
+        synonymToColor.put("orangered3", "#CD3700");
+        synonymToColor.put("orangered4", "#8B2500");
+        synonymToColor.put("orchid", "#DA70D6");
+        synonymToColor.put("orchid1", "#FF83FA");
+        synonymToColor.put("orchid2", "#EE7AE9");
+        synonymToColor.put("orchid3", "#CD69C9");
+        synonymToColor.put("orchid4", "#8B4789");
+        synonymToColor.put("palegoldenrod", "#EEE8AA");
+        synonymToColor.put("palegreen", "#98FB98");
+        synonymToColor.put("palegreen1", "#9AFF9A");
+        synonymToColor.put("palegreen2", "#90EE90");
+        synonymToColor.put("palegreen3", "#7CCD7C");
+        synonymToColor.put("palegreen4", "#548B54");
+        synonymToColor.put("paleturquoise", "#AFEEEE");
+        synonymToColor.put("paleturquoise1", "#BBFFFF");
+        synonymToColor.put("paleturquoise2", "#AEEEEE");
+        synonymToColor.put("paleturquoise3", "#96CDCD");
+        synonymToColor.put("paleturquoise4", "#668B8B");
+        synonymToColor.put("palevioletred", "#DB7093");
+        synonymToColor.put("palevioletred1", "#FF82AB");
+        synonymToColor.put("palevioletred2", "#EE799F");
+        synonymToColor.put("palevioletred3", "#CD6889");
+        synonymToColor.put("palevioletred4", "#8B475D");
+        synonymToColor.put("papayawhip", "#FFEFD5");
+        synonymToColor.put("peachpuff", "#FFDAB9");
+        synonymToColor.put("peachpuff1", "#FFDAB9");
+        synonymToColor.put("peachpuff2", "#EECBAD");
+        synonymToColor.put("peachpuff3", "#CDAF95");
+        synonymToColor.put("peachpuff4", "#8B7765");
+        synonymToColor.put("peru", "#CD853F");
+        synonymToColor.put("pink", "#FFC0CB");
+        synonymToColor.put("pink1", "#FFB5C5");
+        synonymToColor.put("pink2", "#EEA9B8");
+        synonymToColor.put("pink3", "#CD919E");
+        synonymToColor.put("pink4", "#8B636C");
+        synonymToColor.put("plum", "#DDA0DD");
+        synonymToColor.put("plum1", "#FFBBFF");
+        synonymToColor.put("plum2", "#EEAEEE");
+        synonymToColor.put("plum3", "#CD96CD");
+        synonymToColor.put("plum4", "#8B668B");
+        synonymToColor.put("powderblue", "#B0E0E6");
+        synonymToColor.put("purple", "#A020F0");
+        synonymToColor.put("purple1", "#9B30FF");
+        synonymToColor.put("purple2", "#912CEE");
+        synonymToColor.put("purple3", "#7D26CD");
+        synonymToColor.put("purple4", "#551A8B");
+        synonymToColor.put("red", "#FF0000");
+        synonymToColor.put("red1", "#FF0000");
+        synonymToColor.put("red2", "#EE0000");
+        synonymToColor.put("red3", "#CD0000");
+        synonymToColor.put("red4", "#8B0000");
+        synonymToColor.put("rosybrown", "#BC8F8F");
+        synonymToColor.put("rosybrown1", "#FFC1C1");
+        synonymToColor.put("rosybrown2", "#EEB4B4");
+        synonymToColor.put("rosybrown3", "#CD9B9B");
+        synonymToColor.put("rosybrown4", "#8B6969");
+        synonymToColor.put("royalblue", "#4169E1");
+        synonymToColor.put("royalblue1", "#4876FF");
+        synonymToColor.put("royalblue2", "#436EEE");
+        synonymToColor.put("royalblue3", "#3A5FCD");
+        synonymToColor.put("royalblue4", "#27408B");
+        synonymToColor.put("snewData.addlebrown", "#8B4513");
+        synonymToColor.put("salmon", "#FA8072");
+        synonymToColor.put("salmon1", "#FF8C69");
+        synonymToColor.put("salmon2", "#EE8262");
+        synonymToColor.put("salmon3", "#CD7054");
+        synonymToColor.put("salmon4", "#8B4C39");
+        synonymToColor.put("sandybrown", "#F4A460");
+        synonymToColor.put("seagreen", "#2E8B57");
+        synonymToColor.put("seagreen1", "#54FF9F");
+        synonymToColor.put("seagreen2", "#4EEE94");
+        synonymToColor.put("seagreen3", "#43CD80");
+        synonymToColor.put("seagreen4", "#2E8B57");
+        synonymToColor.put("seashell", "#FFF5EE");
+        synonymToColor.put("seashell1", "#FFF5EE");
+        synonymToColor.put("seashell2", "#EEE5DE");
+        synonymToColor.put("seashell3", "#CDC5BF");
+        synonymToColor.put("seashell4", "#8B8682");
+        synonymToColor.put("sienna", "#A0522D");
+        synonymToColor.put("sienna1", "#FF8247");
+        synonymToColor.put("sienna2", "#EE7942");
+        synonymToColor.put("sienna3", "#CD6839");
+        synonymToColor.put("sienna4", "#8B4726");
+        synonymToColor.put("skyblue", "#87CEEB");
+        synonymToColor.put("skyblue1", "#87CEFF");
+        synonymToColor.put("skyblue2", "#7EC0EE");
+        synonymToColor.put("skyblue3", "#6CA6CD");
+        synonymToColor.put("skyblue4", "#4A708B");
+        synonymToColor.put("slateblue", "#6A5ACD");
+        synonymToColor.put("slateblue1", "#836FFF");
+        synonymToColor.put("slateblue2", "#7A67EE");
+        synonymToColor.put("slateblue3", "#6959CD");
+        synonymToColor.put("slateblue4", "#473C8B");
+        synonymToColor.put("slategray", "#708090");
+        synonymToColor.put("slategray1", "#C6E2FF");
+        synonymToColor.put("slategray2", "#B9D3EE");
+        synonymToColor.put("slategray3", "#9FB6CD");
+        synonymToColor.put("slategray4", "#6C7B8B");
+        synonymToColor.put("slategrey", "#708090");
+        synonymToColor.put("snow", "#FFFAFA");
+        synonymToColor.put("snow1", "#FFFAFA");
+        synonymToColor.put("snow2", "#EEE9E9");
+        synonymToColor.put("snow3", "#CDC9C9");
+        synonymToColor.put("snow4", "#8B8989");
+        synonymToColor.put("springgreen", "#00FF7F");
+        synonymToColor.put("springgreen1", "#00FF7F");
+        synonymToColor.put("springgreen2", "#00EE76");
+        synonymToColor.put("springgreen3", "#00CD66");
+        synonymToColor.put("springgreen4", "#008B45");
+        synonymToColor.put("steelblue", "#4682B4");
+        synonymToColor.put("steelblue1", "#63B8FF");
+        synonymToColor.put("steelblue2", "#5CACEE");
+        synonymToColor.put("steelblue3", "#4F94CD");
+        synonymToColor.put("steelblue4", "#36648B");
+        synonymToColor.put("tan", "#D2B48C");
+        synonymToColor.put("tan1", "#FFA54F");
+        synonymToColor.put("tan2", "#EE9A49");
+        synonymToColor.put("tan3", "#CD853F");
+        synonymToColor.put("tan4", "#8B5A2B");
+        synonymToColor.put("thistle", "#D8BFD8");
+        synonymToColor.put("thistle1", "#FFE1FF");
+        synonymToColor.put("thistle2", "#EED2EE");
+        synonymToColor.put("thistle3", "#CDB5CD");
+        synonymToColor.put("thistle4", "#8B7B8B");
+        synonymToColor.put("tomato", "#FF6347");
+        synonymToColor.put("tomato1", "#FF6347");
+        synonymToColor.put("tomato2", "#EE5C42");
+        synonymToColor.put("tomato3", "#CD4F39");
+        synonymToColor.put("tomato4", "#8B3626");
+        synonymToColor.put("turquoise", "#40E0D0");
+        synonymToColor.put("turquoise1", "#00F5FF");
+        synonymToColor.put("turquoise2", "#00E5EE");
+        synonymToColor.put("turquoise3", "#00C5CD");
+        synonymToColor.put("turquoise4", "#00868B");
+        synonymToColor.put("violet", "#EE82EE");
+        synonymToColor.put("violetred", "#D02090");
+        synonymToColor.put("violetred1", "#FF3E96");
+        synonymToColor.put("violetred2", "#EE3A8C");
+        synonymToColor.put("violetred3", "#CD3278");
+        synonymToColor.put("violetred4", "#8B2252");
+        synonymToColor.put("wheat", "#F5DEB3");
+        synonymToColor.put("wheat1", "#FFE7BA");
+        synonymToColor.put("wheat2", "#EED8AE");
+        synonymToColor.put("wheat3", "#CDBA96");
+        synonymToColor.put("wheat4", "#8B7E66");
+        synonymToColor.put("whitesmoke", "#F5F5F5");
+        synonymToColor.put("yellow", "#FFFF00");
+        synonymToColor.put("yellow1", "#FFFF00");
+        synonymToColor.put("yellow2", "#EEEE00");
+        synonymToColor.put("yellow3", "#CDCD00");
+        synonymToColor.put("yellow4", "#8B8B00");
+        synonymToColor.put("yellowgreen", "#9ACD32");
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 5c40420695..040c72660f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -21,6 +21,7 @@ import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -38,7 +39,6 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     private static final double TRC0 = 1.55512030155621416073; /* sqrt(4 * pi/(3 * sqrt(3))) */
     private static final double TRC1 = 1.34677368708859836060; /* TRC0 * sqrt(3) / 2 */
     private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
-    private static final String TRANSPARENT = "white";  // TODO: should be actually transparent
 
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
     @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
@@ -112,9 +112,9 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     private static void drawDot(DrawingContext drawingCtx, GridDevice dev, double cex, double x, double y) {
         // NOTE: we are *filling* a rect with the current colour (we are not drawing the border AND
         // we are not using the current fill colour)
-        String originalFill = drawingCtx.getFillColor();
+        GridColor originalFill = drawingCtx.getFillColor();
         drawingCtx.setFillColor(drawingCtx.getColor());
-        drawingCtx.setColor(TRANSPARENT);
+        drawingCtx.setColor(GridColor.TRANSPARENT);
 
         /*
          * The idea here is to use a 0.01" square, but to be of at least one device unit in each
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index 1cd94bdabf..412f80ebf5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -28,17 +28,12 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 public interface DrawingContext {
     double INCH_TO_POINTS_FACTOR = 72;
 
-    /**
-     * @return Hexadecimal string of the color with leading '#', e.g. '#FFA8B2'. Never returns a
-     *         synonym.
-     */
-    String getColor();
+    GridColor getColor();
 
     /**
-     * Alows to set the color. The parameter may also be a synonym defined in
-     * {@link com.oracle.truffle.r.library.fastrGrid.ColorNames}.
+     * Alows to set the color drawing color of shape borders, lines and text.
      */
-    void setColor(String hexCode);
+    void setColor(GridColor color);
 
     /**
      * Gets the font size in points.
@@ -52,15 +47,10 @@ public interface DrawingContext {
      */
     double getLineHeight();
 
-    /**
-     * @return Hexadecimal string of the color with leading '#', e.g. '#FFA8B2'. Never returns a
-     *         synonym.
-     */
-    String getFillColor();
+    GridColor getFillColor();
 
     /**
-     * Alows to set the fill color. The parameter may also be a synonym defined in
-     * {@link com.oracle.truffle.r.library.fastrGrid.ColorNames}.
+     * Alows to set the fill color of shapes.
      */
-    void setFillColor(String hexCode);
+    void setFillColor(GridColor color);
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
new file mode 100644
index 0000000000..e4cdd7517a
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+/**
+ * Simple color representation, so that the device interface does not have to depend on a specific
+ * GUI framework.
+ */
+public class GridColor {
+    public static final int OPAQUE_ALPHA = 0xff;
+    private static final int TRANSPARENT_ALPHA = 0;
+    public static final GridColor TRANSPARENT = new GridColor(0, 0, 0, TRANSPARENT_ALPHA);
+
+    private final int value;
+
+    public GridColor(int red, int green, int blue, int alpha) {
+        value = ((alpha & 0xFF) << 24) |
+                        ((red & 0xFF) << 16) |
+                        ((green & 0xFF) << 8) |
+                        (blue & 0xFF);
+    }
+
+    public int getRed() {
+        return (value >> 16) & 0xFF;
+    }
+
+    public int getGreen() {
+        return (value >> 8) & 0xFF;
+    }
+
+    public int getBlue() {
+        return value & 0xFF;
+    }
+
+    public int getAlpha() {
+        return (value >> 24) & 0xff;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index cf13bfd232..ff3c882103 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -25,13 +25,17 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics2D;
+import java.awt.Paint;
 import java.awt.RenderingHints;
+import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
 import java.util.function.Supplier;
 
+import javax.swing.UIManager;
+
 import com.oracle.truffle.r.library.graphics.FastRFrame;
 
 public class JFrameDevice implements GridDevice {
@@ -66,7 +70,7 @@ public class JFrameDevice implements GridDevice {
     @Override
     public void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width) {
         setContext(ctx);
-        graphics.draw(new Rectangle2D.Double(leftX, topY, heigh, width));
+        drawShape(ctx, new Rectangle2D.Double(leftX, topY, heigh, width));
     }
 
     @Override
@@ -85,7 +89,7 @@ public class JFrameDevice implements GridDevice {
     @Override
     public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
         setContext(ctx);
-        graphics.draw(new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2d, radius * 2d));
+        drawShape(ctx, new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2d, radius * 2d));
     }
 
     @Override
@@ -127,9 +131,25 @@ public class JFrameDevice implements GridDevice {
         });
     }
 
+    @Override
+    public void initDrawingContext(DrawingContext ctx) {
+        Color color = UIManager.getColor("Panel.background");
+        if (color != null) {
+            ctx.setFillColor(toGridColor(color));
+        }
+    }
+
+    private void drawShape(DrawingContext drawingCtx, Shape shape) {
+        Paint paint = graphics.getPaint();
+        graphics.setPaint(fromGridColor(drawingCtx.getFillColor()));
+        graphics.fill(shape);
+        graphics.setPaint(paint);
+        graphics.draw(shape);
+    }
+
     private void setContext(DrawingContext ctx) {
         graphics.setFont(graphics.getFont().deriveFont((float) ctx.getFontSize()));
-        graphics.setColor(Color.decode(ctx.getColor()));
+        graphics.setColor(fromGridColor(ctx.getColor()));
     }
 
     private <T> T noTranform(Supplier<T> action) {
@@ -139,4 +159,12 @@ public class JFrameDevice implements GridDevice {
         graphics.setTransform(transform);
         return result;
     }
+
+    private static Color fromGridColor(GridColor color) {
+        return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
+    }
+
+    private static GridColor toGridColor(Color color) {
+        return new GridColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java
new file mode 100644
index 0000000000..8e43a26774
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastrGrid/GridColorUtilsTests.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.library.fastrGrid;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.library.fastrGrid.GridColorUtils;
+import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
+import com.oracle.truffle.r.test.TestBase;
+
+public class GridColorUtilsTests extends TestBase {
+    @Test
+    public void convertFromHex() {
+        GridColor color = GridColorUtils.gridColorFromString("#FF01FE");
+        assertEquals(255, color.getRed());
+        assertEquals(1, color.getGreen());
+        assertEquals(254, color.getBlue());
+        assertEquals(255, color.getAlpha());
+    }
+
+    @Test
+    public void convertFromHexWithAlpha() {
+        GridColor color = GridColorUtils.gridColorFromString("#FF00FE02");
+        assertEquals(255, color.getRed());
+        assertEquals(0, color.getGreen());
+        assertEquals(254, color.getBlue());
+        assertEquals(02, color.getAlpha());
+    }
+
+    @Test
+    public void convertSynonymBlack() {
+        GridColor black = GridColorUtils.gridColorFromString("black");
+        assertEquals(0, black.getRed());
+        assertEquals(0, black.getGreen());
+        assertEquals(0, black.getBlue());
+        assertEquals(255, black.getAlpha());
+    }
+
+    @Test
+    public void convertSynonymUpercaseRed() {
+        GridColor black = GridColorUtils.gridColorFromString("RED");
+        assertEquals(255, black.getRed());
+        assertEquals(0, black.getGreen());
+        assertEquals(0, black.getBlue());
+        assertEquals(255, black.getAlpha());
+    }
+
+    @Test
+    public void convertSynonymLightGreenWithSpace() {
+        GridColor black = GridColorUtils.gridColorFromString("light green");
+        assertEquals(0x90, black.getRed());
+        assertEquals(0xee, black.getGreen());
+        assertEquals(0x90, black.getBlue());
+        assertEquals(255, black.getAlpha());
+    }
+
+    @Test
+    public void convertSynonymLightGreen() {
+        GridColor black = GridColorUtils.gridColorFromString("light green");
+        assertEquals(0x90, black.getRed());
+        assertEquals(0xee, black.getGreen());
+        assertEquals(0x90, black.getBlue());
+        assertEquals(255, black.getAlpha());
+    }
+
+    @Test
+    public void convertSynonymTransparent() {
+        GridColor transparent = GridColorUtils.gridColorFromString("transparent");
+        assertEquals(0, transparent.getAlpha());
+    }
+}
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 2ed282f563..8cef96974b 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -786,7 +786,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ColorNames.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 782257b532..259351b416 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -404,7 +404,7 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.grid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data', 'S4']))
+    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.fastrGrid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data', 'S4']))
 
 def _simple_unit_tests():
     return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
-- 
GitLab


From f4c1cec6a3e2210602d02203bbe570771afdc50e Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 17 Mar 2017 10:07:40 +0100
Subject: [PATCH 160/402] FastR Grid: fixes in text rendering

---
 .../r/library/fastrGrid/GridTextNode.java     |  2 +-
 .../fastrGrid/device/DrawingContext.java      |  2 +-
 .../library/fastrGrid/device/GridDevice.java  |  8 +++--
 .../fastrGrid/device/JFrameDevice.java        | 34 +++++++++++++------
 4 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 8d390d72e4..8fbbe300af 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -247,7 +247,7 @@ public final class GridTextNode extends RBaseNode {
                 ybottom = yoff - (xadj) * width * sinRot - yadj * height * cosRot;
             }
 
-            device.drawString(drawingCtx, xleft, ybottom, rotation, lines[lineIdx]);
+            device.drawString(drawingCtx, xleft, ybottom, radRotation, lines[lineIdx]);
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index 412f80ebf5..ca1e987c1b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -26,7 +26,7 @@ package com.oracle.truffle.r.library.fastrGrid.device;
  * Defines parameters for drawing, like color, line style etc.
  */
 public interface DrawingContext {
-    double INCH_TO_POINTS_FACTOR = 72;
+    double INCH_TO_POINTS_FACTOR = 72.27;
 
     GridColor getColor();
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 16299f7a2e..1f0a0d8f03 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -26,7 +26,7 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 
 /**
  * Abstract device that can draw primitive shapes and text. All sizes and coordinates are specified
- * in inches.
+ * in inches and angles in radians unless stated otherwise.
  */
 public interface GridDevice {
     void openNewPage();
@@ -41,7 +41,11 @@ public interface GridDevice {
 
     void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius);
 
-    void drawString(DrawingContext ctx, double leftX, double bottomY, double rotation, String text);
+    /**
+     * Prints a string with left bottom corner at given position rotates by given angle anti clock
+     * wise, the centre of the rotation should be the bottom left corer.
+     */
+    void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text);
 
     /**
      * @return The width of the device in inches.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index ff3c882103..758ae81683 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.device;
 
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+
 import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics2D;
@@ -44,6 +46,7 @@ public class JFrameDevice implements GridDevice {
     // coordinate system to the grid one. However, in the case of text rendering, we cannot simply
     // turn upside down the y-axis, because the text would be upside down too, so for text rendering
     // only, we reset the transformation completely and transform the coordinates ourselves
+    private static final double POINTS_IN_INCH = 72.;
 
     private FastRFrame currentFrame;
     private Graphics2D graphics;
@@ -55,8 +58,8 @@ public class JFrameDevice implements GridDevice {
             currentFrame.setVisible(true);
             graphics = (Graphics2D) currentFrame.getGraphics();
             graphics.translate(0, currentFrame.getHeight());
-            graphics.scale(72, -72); // doc: 72 points ~ 1 inch
-            graphics.setStroke(new BasicStroke(1f / 72f));
+            graphics.scale(POINTS_IN_INCH, -POINTS_IN_INCH);
+            graphics.setStroke(new BasicStroke((float) (1d / POINTS_IN_INCH)));
             graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
             graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
         } else {
@@ -93,31 +96,36 @@ public class JFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotation, String text) {
+    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
         setContext(ctx);
         noTranform(() -> {
-            graphics.rotate(rotation);
-            graphics.drawString(text, (float) leftX * 72f, (float) (currentFrame.getContentPane().getHeight() - bottomY * 72f));
+            AffineTransform tr = graphics.getTransform();
+            tr.translate((float) (leftX * POINTS_IN_INCH), (float) (currentFrame.getContentPane().getHeight() - bottomY * POINTS_IN_INCH));
+            tr.rotate(-rotationAnticlockWise);
+            graphics.setTransform(tr);
+            setFontSize(ctx);
+            graphics.drawString(text, 0, 0);
             return null;
         });
     }
 
     @Override
     public double getWidth() {
-        return currentFrame.getContentPane().getWidth() / 72.0;
+        return currentFrame.getContentPane().getWidth() / POINTS_IN_INCH;
     }
 
     @Override
     public double getHeight() {
-        return currentFrame.getContentPane().getHeight() / 72.0;
+        return currentFrame.getContentPane().getHeight() / POINTS_IN_INCH;
     }
 
     @Override
     public double getStringWidth(DrawingContext ctx, String text) {
         setContext(ctx);
         return noTranform(() -> {
+            setFontSize(ctx);
             int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
-            return swingUnits / 72.;
+            return swingUnits / POINTS_IN_INCH;
         });
     }
 
@@ -125,9 +133,9 @@ public class JFrameDevice implements GridDevice {
     public double getStringHeight(DrawingContext ctx, String text) {
         setContext(ctx);
         return noTranform(() -> {
-            // int swingUnits = graphics.getFontMetrics(graphics.getFont()).getHeight();
+            setFontSize(ctx);
             int swingUnits = graphics.getFont().getSize();
-            return swingUnits / 72.;
+            return swingUnits / POINTS_IN_INCH;
         });
     }
 
@@ -148,10 +156,14 @@ public class JFrameDevice implements GridDevice {
     }
 
     private void setContext(DrawingContext ctx) {
-        graphics.setFont(graphics.getFont().deriveFont((float) ctx.getFontSize()));
         graphics.setColor(fromGridColor(ctx.getColor()));
     }
 
+    private void setFontSize(DrawingContext ctx) {
+        float fontSize = (float) ((ctx.getFontSize() / INCH_TO_POINTS_FACTOR) * POINTS_IN_INCH);
+        graphics.setFont(graphics.getFont().deriveFont(fontSize));
+    }
+
     private <T> T noTranform(Supplier<T> action) {
         AffineTransform transform = graphics.getTransform();
         graphics.setTransform(new AffineTransform());
-- 
GitLab


From 657f38f4d69a696d85005ee5ba920a3ac4bfab6a Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 17 Mar 2017 12:50:58 +0100
Subject: [PATCH 161/402] FastR Grid: LPolygon + support for 'stringwidth'
 units

---
 .../r/library/fastrGrid/DoSetViewPort.java    |  25 ++--
 .../r/library/fastrGrid/GridLinesNode.java    | 119 +++++++++++++++++
 .../r/library/fastrGrid/GridTextNode.java     |   2 +-
 .../r/library/fastrGrid/GridUtils.java        |  11 ++
 .../truffle/r/library/fastrGrid/LCircle.java  |   2 +-
 .../truffle/r/library/fastrGrid/LConvert.java |  50 +++----
 .../truffle/r/library/fastrGrid/LLines.java   |  97 ++++----------
 .../truffle/r/library/fastrGrid/LPoints.java  |   2 +-
 .../truffle/r/library/fastrGrid/LPolygon.java |  52 ++++++++
 .../truffle/r/library/fastrGrid/LRect.java    |   2 +-
 .../r/library/fastrGrid/LSegments.java        |   2 +-
 .../truffle/r/library/fastrGrid/Unit.java     | 123 ++++++++++++------
 .../foreign/CallAndExternalFunctions.java     |   3 +
 mx.fastr/copyrights/overrides                 |   2 +-
 14 files changed, 331 insertions(+), 161 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 7134c501c4..ec20b0d423 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -107,7 +107,7 @@ class DoSetViewPort extends RBaseNode {
             }
         }
 
-        UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, drawingContext);
+        UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, device, drawingContext);
         double xInches = unitsToInches.convertX(vpl.x, 0, conversionCtx);
         double yInches = unitsToInches.convertY(vpl.y, 0, conversionCtx);
         double width = unitsToInches.convertWidth(vpl.width, 0, conversionCtx);
@@ -141,7 +141,7 @@ class DoSetViewPort extends RBaseNode {
         if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) {
             ViewPortContext vpCtx = vpContextFromVP.execute(viewPort);
             DrawingContext drawingCtx = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)));
-            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, drawingCtx);
+            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, drawingCtx);
         }
 
         Object[] viewPortData = viewPort.getDataWithoutCopying();
@@ -151,13 +151,13 @@ class DoSetViewPort extends RBaseNode {
         viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
     }
 
-    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, DrawingContext drawingCtx) {
+    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx) {
         LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort);
         double[] npcWidths = new double[layoutSize.ncol];
         double[] npcHeights = new double[layoutSize.nrow];
         boolean[] relativeWidths = new boolean[layoutSize.ncol];
         boolean[] relativeHeights = new boolean[layoutSize.nrow];
-        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, device, drawingCtx);
 
         // For both dimensions we find out which units are other than "null" for those we can
         // immediately calculate the physical size in npcWidth/npcHeights. The reducedWidth/Height
@@ -178,8 +178,8 @@ class DoSetViewPort extends RBaseNode {
         int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT));
         int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying();
         if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) {
-            double sumRelWidth = sumRelativeDimension(layoutSize, layoutWidths, relativeWidths, parentVPCtx, drawingCtx, true);
-            double sumRelHeight = sumRelativeDimension(layoutSize, layoutHeights, relativeHeights, parentVPCtx, drawingCtx, false);
+            double sumRelWidth = sumRelativeDimension(layoutSize, layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
+            double sumRelHeight = sumRelativeDimension(layoutSize, layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
             double tempWidth = reducedWidth;
             double tempHeight = reducedHeight;
             double denom;
@@ -233,8 +233,8 @@ class DoSetViewPort extends RBaseNode {
         }
 
         // Secondly, allocate remaining relative widths and heights in the remaining space
-        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, drawingCtx, parentVPCtx, true);
-        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, drawingCtx, parentVPCtx, false);
+        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, device, drawingCtx, parentVPCtx, true);
+        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, device, drawingCtx, parentVPCtx, false);
 
         // Create the result
         Object[] vpData = viewPort.getDataWithoutCopying();
@@ -243,8 +243,8 @@ class DoSetViewPort extends RBaseNode {
     }
 
     private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
-                    DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, drawingCtx, 1, 0);
+                    GridDevice device, DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
         double totalUnrespectedSize = 0;
         if (reducedDim > 0) {
             for (int i = 0; i < layoutSize.ncol; i++) {
@@ -293,8 +293,9 @@ class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(LayoutSize layoutSize, RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, DrawingContext drawingCtx, boolean isWidth) {
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, drawingCtx, 0, 1);
+    private double sumRelativeDimension(LayoutSize layoutSize, RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
+                    boolean isWidth) {
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 0, 1);
         double totalWidth = 0;
         for (int i = 0; i < layoutSize.ncol; i++) {
             if (relativeItems[i]) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
new file mode 100644
index 0000000000..695175e7c2
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -0,0 +1,119 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Common code shared between {@code L_lines} and {@code L_polygon} externals. Both draw a series of
+ * lines, but only the later connects the last point with the first point and only the former draws
+ * arrows (which is not implemented yet). Note: the third parameter contains sequences
+ * {@code 1:max(length(x),length(y))}, where the 'length' dispatches to S3 method giving us unit
+ * length like {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode}. This means that
+ * we do not have to use the {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode} to
+ * get the length.
+ */
+public abstract class GridLinesNode extends Node {
+    public static GridLinesNode createLines() {
+        return new GridLinesImpl();
+    }
+
+    public static GridLinesNode createPolygon() {
+        return new GridLinesPolygon();
+    }
+
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
+    void execute(RAbstractVector x, RAbstractVector y, RList lengths) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
+        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+
+        // Convert the list of vectors of indexes to type-safe array and calculate the max length of
+        // the vectors.
+        RAbstractIntVector[] unitIndexesList = new RAbstractIntVector[lengths.getLength()];
+        int maxIndexesLen = 0;
+        for (int i = 0; i < lengths.getLength(); i++) {
+            unitIndexesList[i] = asIntVector(lengths.getDataAt(i));
+            maxIndexesLen = Math.max(maxIndexesLen, unitIndexesList[i].getLength());
+        }
+
+        double[] xx = new double[maxIndexesLen + 1];    // plus one for polygons
+        double[] yy = new double[maxIndexesLen + 1];
+        for (RAbstractIntVector unitIndexes : unitIndexesList) {
+            boolean oldIsFinite = false;
+            int start = 0;
+            int unitIndexesLen = unitIndexes.getLength();
+            // following loop finds series of valid points (finite x and y values) and draws each
+            // such series as a polyline
+            for (int i = 0; i < unitIndexesLen; i++) {
+                int unitIndex = unitIndexes.getDataAt(i) - 1;   // coverting R's 1-based index
+                Point origLoc = Point.fromUnits(unitToInches, x, y, unitIndex, conversionCtx);
+                Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
+                xx[i] = loc.x;
+                yy[i] = loc.y;
+                boolean currIsFinite = loc.isFinite();
+                boolean lastIter = i == (unitIndexesLen - 1);
+                if (currIsFinite && !oldIsFinite) {
+                    start = i; // start a new series
+                } else if (oldIsFinite && (!currIsFinite || lastIter)) {
+                    // draw the previous points series because
+                    // (1) current is invalid point. Note: in (one of) the next iteration(s), the
+                    // oldIsFinite will be false and we will update the start and start a new series
+                    // (2) we are in the last iteration
+                    if (lastIter || i - start > 1) {
+                        // we draw only if the previous series of points was at least of length 3 or
+                        // it's last iteration. This seems slightly weird, but that's how GnuR seems
+                        // to work
+                        drawPolylines(dev, drawingCtx, yy, xx, start, (i - start) + 1);
+                    }
+                }
+                oldIsFinite = currIsFinite;
+            }
+        }
+    }
+
+    abstract void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length);
+
+    private static final class GridLinesImpl extends GridLinesNode {
+        @Override
+        void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length) {
+            dev.drawPolyLines(drawingCtx, xx, yy, start, length);
+        }
+    }
+
+    private static final class GridLinesPolygon extends GridLinesNode {
+        @Override
+        void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length) {
+            xx[start + length] = xx[start];
+            yy[start + length] = yy[start];
+            dev.drawPolyLines(drawingCtx, xx, yy, start, length + 1);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 8fbbe300af..13e52dfc66 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -97,7 +97,7 @@ public final class GridTextNode extends RBaseNode {
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
         ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, x, y);
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 0de2442c7b..1b7ff9197a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -21,6 +21,7 @@ import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -89,6 +90,16 @@ final class GridUtils {
         return false;
     }
 
+    static RList asListOrNull(Object value) {
+        if (value == null || value == RNull.instance) {
+            return null;
+        }
+        if (!(value instanceof RList)) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Expected list");
+        }
+        return (RList) value;
+    }
+
     static RList asList(Object value) {
         if (!(value instanceof RList)) {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "Expected list");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 60448d3fa7..c5262bd3ff 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -51,7 +51,7 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
         ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 04f325f485..3703c83baa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -19,6 +19,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
@@ -59,7 +60,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
         ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = unitLength.execute(units);
         double[] result = new double[length];
@@ -69,15 +70,11 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
 
         for (int i = 0; i < length; i++) {
             // scalar values used in current iteration
-            int axisFrom = axisFromVec.getDataAt(i % axisFromVec.getLength());
-            int axisTo = axisToVec.getDataAt(i % axisToVec.getLength());
-            boolean compatibleAxes = axisFrom == axisTo ||
-                            (axisFrom == 0 && axisTo == 2) ||
-                            (axisFrom == 2 && axisTo == 0) ||
-                            (axisFrom == 1 && axisTo == 3) ||
-                            (axisFrom == 3 && axisTo == 1);
-            double vpToSize = isXAxis(axisTo) ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
-            double vpFromSize = isXAxis(axisFrom) ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
+            AxisOrDimension axisFrom = AxisOrDimension.fromInt(axisFromVec.getDataAt(i % axisFromVec.getLength()));
+            AxisOrDimension axisTo = AxisOrDimension.fromInt(axisToVec.getDataAt(i % axisToVec.getLength()));
+            boolean compatibleAxes = axisFrom.isHorizontal() == axisTo.isHorizontal();
+            double vpToSize = axisTo.isHorizontal() ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
+            double vpFromSize = axisFrom.isHorizontal() ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
             int unitTo = unitToVec.getDataAt(i % unitToVec.getLength());
             int fromUnitId = unitIds.getDataAt(i % unitIds.getLength());
 
@@ -94,26 +91,26 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
                 result[i] = transformFromNPC(tranfromToNPC(fromValue, fromUnitId, axisFrom, vpContext), unitTo, axisTo, vpContext);
             } else {
                 double inches = toInches(units, i, axisFrom, conversionCtx);
-                boolean isX = isXAxis(axisTo);
+                boolean isX = axisTo.isHorizontal();
                 double scalemin = isX ? vpContext.xscalemin : vpContext.yscalemin;
                 double scalemax = isX ? vpContext.xscalemax : vpContext.yscalemax;
-                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, isDimension(axisTo), drawingCtx);
+                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, axisTo.isDimension(), drawingCtx);
             }
         }
 
         return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
     }
 
-    private double toInches(RAbstractVector units, int index, int axisFrom, UnitConversionContext conversionCtx) {
+    private double toInches(RAbstractVector units, int index, AxisOrDimension axisFrom, UnitConversionContext conversionCtx) {
         double inches;
-        if (isXAxis(axisFrom)) {
-            if (isDimension(axisFrom)) {
+        if (axisFrom.isHorizontal()) {
+            if (axisFrom.isDimension()) {
                 inches = unitToInches.convertWidth(units, index, conversionCtx);
             } else {
                 inches = unitToInches.convertX(units, index, conversionCtx);
             }
         } else {
-            if (isDimension(axisFrom)) {
+            if (axisFrom.isDimension()) {
                 inches = unitToInches.convertHeight(units, index, conversionCtx);
             } else {
                 inches = unitToInches.convertY(units, index, conversionCtx);
@@ -122,30 +119,30 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         return inches;
     }
 
-    private static double tranfromToNPC(double value, int fromUnitId, int axisFrom, ViewPortContext vpContext) {
+    private static double tranfromToNPC(double value, int fromUnitId, AxisOrDimension axisFrom, ViewPortContext vpContext) {
         if (fromUnitId == Unit.NPC) {
             return value;
         }
         assert fromUnitId == Unit.NATIVE : "relative conversion should only happen when units are NPC or NATIVE";
-        boolean isX = isXAxis(axisFrom);
+        boolean isX = axisFrom.isHorizontal();
         double min = isX ? vpContext.xscalemin : vpContext.yscalemin;
         double max = isX ? vpContext.xscalemax : vpContext.yscalemax;
-        if (isDimension(axisFrom)) {
+        if (axisFrom.isDimension()) {
             return value / (max - min);
         } else {
             return (value - min) / (max - min);
         }
     }
 
-    private static double transformFromNPC(double value, int unitTo, int axisTo, ViewPortContext vpContext) {
+    private static double transformFromNPC(double value, int unitTo, AxisOrDimension axisTo, ViewPortContext vpContext) {
         if (unitTo == Unit.NPC) {
             return value;
         }
         assert unitTo == Unit.NATIVE : "relative conversion should only happen when units are NPC or NATIVE";
-        boolean isX = isXAxis(axisTo);
+        boolean isX = axisTo.isHorizontal();
         double min = isX ? vpContext.xscalemin : vpContext.yscalemin;
         double max = isX ? vpContext.xscalemax : vpContext.yscalemax;
-        if (isDimension(axisTo)) {
+        if (axisTo.isDimension()) {
             return value * (max - min);
         } else {
             return min + value * (max - min);
@@ -157,13 +154,4 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     private static boolean isRelative(int unitId) {
         return unitId == NPC || unitId == NATIVE;
     }
-
-    // what = 0 means x, 1 means y, 2 means width, 3 means height
-    private static boolean isXAxis(int what) {
-        return what % 2 == 0;
-    }
-
-    private static boolean isDimension(int what) {
-        return what >= 2;
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
index 0f429081b6..de27073452 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -1,40 +1,37 @@
 /*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- * Copyright (C) 2001-3 Paul Murrell
- * Copyright (c) 1998-2013, The R Core Team
- * Copyright (c) 2017, Oracle and/or its affiliates
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
  *
- * All rights reserved.
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
-import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-/**
- * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the
- * 'length' dispatches to S3 method giving us unit length like
- * {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode}.
- */
 public abstract class LLines extends RExternalBuiltinNode.Arg4 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+    @Child private GridLinesNode gridLinesNode = GridLinesNode.createLines();
 
     static {
         Casts casts = new Casts(LLines.class);
@@ -48,59 +45,9 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, Object arrowIgnored) {
-        GridContext ctx = GridContext.getContext();
-        GridDevice dev = ctx.getCurrentDevice();
-
-        RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
-
-        // Convert the list of vectors of indexes to type-safe array and calculate the max length of
-        // the vectors.
-        RAbstractIntVector[] unitIndexesList = new RAbstractIntVector[lengths.getLength()];
-        int maxIndexesLen = 0;
-        for (int i = 0; i < lengths.getLength(); i++) {
-            unitIndexesList[i] = asIntVector(lengths.getDataAt(i));
-            maxIndexesLen = Math.max(maxIndexesLen, unitIndexesList[i].getLength());
-        }
-
-        double[] xx = new double[maxIndexesLen];
-        double[] yy = new double[maxIndexesLen];
-        for (RAbstractIntVector unitIndexes : unitIndexesList) {
-            boolean oldIsFinite = false;
-            int start = 0;
-            int unitIndexesLen = unitIndexes.getLength();
-            // following loop finds series of valid points (finite x and y values) and draws each
-            // such series as a polyline
-            for (int i = 0; i < unitIndexesLen; i++) {
-                int unitIndex = unitIndexes.getDataAt(i) - 1;   // coverting R's 1-based index
-                Point origLoc = Point.fromUnits(unitToInches, x, y, unitIndex, conversionCtx);
-                Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
-                xx[i] = loc.x;
-                yy[i] = loc.y;
-                boolean currIsFinite = loc.isFinite();
-                boolean lastIter = i == (unitIndexesLen - 1);
-                if (currIsFinite && !oldIsFinite) {
-                    start = i; // start a new series
-                } else if (oldIsFinite && (!currIsFinite || lastIter)) {
-                    // draw the previous points series because
-                    // (1) current is invalid point. Note: in (one of) the next iteration(s), the
-                    // oldIsFinite will be false and we will update the start and start a new series
-                    // (2) we are in the last iteration
-                    if (lastIter || i - start > 1) {
-                        // we draw only if the previous series of points was at least of length 3 or
-                        // it's last iteration. This seems slightly weird, but that's how GnuR seems
-                        // to work
-                        dev.drawPolyLines(drawingCtx, xx, yy, start, (i - start) + 1);
-                    }
-                }
-                oldIsFinite = currIsFinite;
-            }
-        }
-
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") Object arrowIgnored) {
+        // TODO: implement arrows
+        gridLinesNode.execute(x, y, lengths);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 040c72660f..67604044ec 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -68,7 +68,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         double cex = GPar.getCex(gpar);
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
         ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         // Note: unlike in other drawing primitives, we only consider length of x
         int length = unitLength.execute(xVec);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
new file mode 100644
index 0000000000..8d4343e9ab
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LPolygon extends RExternalBuiltinNode.Arg3 {
+    @Child private GridLinesNode gridLinesNode = GridLinesNode.createPolygon();
+
+    static {
+        Casts casts = new Casts(LPolygon.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(RList.class);
+    }
+
+    public static LPolygon create() {
+        return LPolygonNodeGen.create();
+    }
+
+    @Specialization
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths) {
+        gridLinesNode.execute(x, y, lengths);
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index a7557972f3..e79c9dcd67 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -56,7 +56,7 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
         ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 3aca3f3afc..426234d0fb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -55,7 +55,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
         ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
         double[] xx = new double[2];
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 06952fdba7..a9dd76013c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -15,6 +15,7 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContain
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.hasRClass;
@@ -34,6 +35,7 @@ import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -177,13 +179,14 @@ public class Unit {
         }
     }
 
-    private static double convertToInches(double value, int unitId, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx) {
+    private static double convertToInches(double value, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+        double vpSize = ctx.getViewPortSize(axisOrDim);
         switch (unitId) {
             case INCHES:
                 return value;
             case NATIVE:
-                double tmp = isDimension ? value : (value - scalemin);
-                return (tmp / (scalemax - scalemin)) * vpSize;
+                double tmp = axisOrDim.isDimension() ? value : (value - ctx.getScaleMin(axisOrDim));
+                return (tmp / (ctx.getScaleMax(axisOrDim) - ctx.getScaleMin(axisOrDim))) * vpSize;
             case NPC:
                 return value * vpSize;
             case POINTS:
@@ -194,12 +197,18 @@ public class Unit {
                 return value / (CM_IN_INCH * 10);
             case CHAR:
             case MYCHAR:
-                return (value * drawingCtx.getFontSize()) / INCH_TO_POINTS_FACTOR;
+                return (value * ctx.drawingContext.getFontSize()) / INCH_TO_POINTS_FACTOR;
             case LINES:
             case MYLINES:
-                return (value * drawingCtx.getFontSize() * drawingCtx.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+                return (value * ctx.drawingContext.getFontSize() * ctx.drawingContext.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+            case STRINGWIDTH:
+            case MYSTRINGWIDTH:
+                return ctx.device.getStringWidth(ctx.drawingContext, RRuntime.asString(data.getDataAt(0)));
+            case STRINGHEIGHT:
+            case MYSTRINGHEIGHT:
+                return ctx.device.getStringHeight(ctx.drawingContext, RRuntime.asString(data.getDataAt(0)));
             case NULL:
-                return evaluateNullUnit(value, vpSize, nullLMode, nullAMode);
+                return evaluateNullUnit(value, vpSize, ctx.nullLayoutMode, ctx.nullArithmeticMode);
             default:
                 throw RInternalError.unimplemented("unit type " + unitId + " in convertToInches");
         }
@@ -387,6 +396,33 @@ public class Unit {
         }
     }
 
+    /**
+     * Used to discriminate between x axis, y axis, width, and height when doing unit conversions.
+     * The order should be the same as used in e.g. {@code L_convert}, which is 0 means x, 1 means
+     * y, 2 means width, 3 means height.
+     */
+    public enum AxisOrDimension {
+        X,
+        Y,
+        WIDTH,
+        HEIGHT;
+
+        private static final AxisOrDimension[] enumValues = values();
+
+        static AxisOrDimension fromInt(int value) {
+            assert value >= 0 && value < 4;
+            return enumValues[value];
+        }
+
+        public boolean isHorizontal() {
+            return this == X || this == WIDTH;
+        }
+
+        public boolean isDimension() {
+            return this == WIDTH || this == HEIGHT;
+        }
+    }
+
     /**
      * Wraps the data necessary for converting a unit to another unit. Note: {@code nullLMode} and
      * {@code nullAMode} is only used for converting 'NULL' units and is only explicitly set when
@@ -397,20 +433,34 @@ public class Unit {
         public final Size viewPortSize;
         public final ViewPortContext viewPortContext;
         public final DrawingContext drawingContext;
+        public final GridDevice device;
         public final int nullLayoutMode;
         public final int nullArithmeticMode;
 
-        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, DrawingContext drawingContext) {
-            this(viewPortSize, viewPortContext, drawingContext, 0, 0);
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, DrawingContext drawingContext) {
+            this(viewPortSize, viewPortContext, device, drawingContext, 0, 0);
         }
 
-        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, DrawingContext drawingContext, int nullLMode, int nullAMode) {
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, DrawingContext drawingContext, int nullLMode, int nullAMode) {
             this.viewPortSize = viewPortSize;
             this.viewPortContext = viewPortContext;
+            this.device = device;
             this.drawingContext = drawingContext;
             this.nullLayoutMode = nullLMode;
             this.nullArithmeticMode = nullAMode;
         }
+
+        public double getViewPortSize(AxisOrDimension forAxisOrDim) {
+            return forAxisOrDim.isHorizontal() ? viewPortSize.getWidth() : viewPortSize.getHeight();
+        }
+
+        public double getScaleMin(AxisOrDimension forAxisOrDim) {
+            return forAxisOrDim.isHorizontal() ? viewPortContext.xscalemin : viewPortContext.yscalemin;
+        }
+
+        public double getScaleMax(AxisOrDimension forAxisOrDim) {
+            return forAxisOrDim.isHorizontal() ? viewPortContext.xscalemax : viewPortContext.yscalemax;
+        }
     }
 
     /**
@@ -425,34 +475,29 @@ public class Unit {
         }
 
         public double convertX(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx.viewPortSize.getWidth(), ctx.viewPortContext.xscalemin, ctx.viewPortContext.xscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, false,
-                            ctx.drawingContext);
+            return execute(vector, index, ctx, AxisOrDimension.X);
         }
 
         public double convertY(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx.viewPortSize.getHeight(), ctx.viewPortContext.yscalemin, ctx.viewPortContext.yscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, false,
-                            ctx.drawingContext);
+            return execute(vector, index, ctx, AxisOrDimension.Y);
         }
 
         public double convertWidth(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx.viewPortSize.getWidth(), ctx.viewPortContext.xscalemin, ctx.viewPortContext.xscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, true,
-                            ctx.drawingContext);
+            return execute(vector, index, ctx, AxisOrDimension.WIDTH);
         }
 
         public double convertHeight(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx.viewPortSize.getHeight(), ctx.viewPortContext.yscalemin, ctx.viewPortContext.yscalemax, ctx.nullLayoutMode, ctx.nullArithmeticMode, true,
-                            ctx.drawingContext);
+            return execute(vector, index, ctx, AxisOrDimension.HEIGHT);
         }
 
         public double convertDimension(RAbstractContainer vector, int index, UnitConversionContext ctx, boolean isWidth) {
             return isWidth ? convertWidth(vector, index, ctx) : convertHeight(vector, index, ctx);
         }
 
-        public abstract double execute(RAbstractContainer vector, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension,
-                        DrawingContext drawingCtx);
+        public abstract double execute(RAbstractContainer vector, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim);
 
         @Specialization(guards = "isSimple(value)")
-        double doNormal(RAbstractContainer value, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx,
+        double doNormal(RAbstractContainer value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
                         @Cached("createAsDoubleCast()") CastNode asDoubleCast,
                         @Cached("create()") UnitUnitIdNode unitUnitId) {
             int unitId = unitUnitId.execute(value, index);
@@ -460,29 +505,27 @@ public class Unit {
             double scalarValue = vector.getDataAt(index % vector.getLength());
             if (isGrobUnit(unitId)) {
                 RList grobList = asList(vector.getAttr("data"));
-                return grobUnitToInches.execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), nullLMode, nullAMode);
+                return grobUnitToInches.execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
             }
-            return convertToInches(scalarValue, unitId, vpSize, scalemin, scalemax, nullLMode, nullAMode, isDimension, drawingCtx);
+            return convertToInches(scalarValue, unitId, asListOrNull(vector.getAttr("data")), ctx, axisOrDim);
         }
 
         @Specialization(guards = "isUnitList(value)")
-        double doList(RList value, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx,
+        double doList(RList value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
                         @Cached("create()") UnitToInchesNode recursiveNode) {
             Object unwrapped = value.getDataAt(index % value.getLength());
             if (unwrapped instanceof RAbstractVector) {
-                return recursiveNode.execute((RAbstractContainer) unwrapped, 0, vpSize, scalemin, scalemax, nullLMode, nullAMode, isDimension, drawingCtx);
+                return recursiveNode.execute((RAbstractContainer) unwrapped, 0, ctx, axisOrDim);
             }
             throw error(Message.GENERIC, "Unexpected unit list with non-vector like element at index " + index);
         }
 
         @Specialization(guards = "isArithmetic(list)")
-        double doArithmetic(RList list, int index, double vpSize, double scalemin, double scalemax, int nullLMode, int nullAMode, boolean isDimension, DrawingContext drawingCtx,
+        double doArithmetic(RList list, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
                         @Cached("create()") UnitLengthNode unitLengthNode,
                         @Cached("create()") UnitToInchesNode recursiveNode) {
             ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit(list);
-            // Note the catch: newNullAMode is applied only if isDimension == true
-            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> recursiveNode.execute(x, index, vpSize, scalemin, scalemax, nullLMode,
-                            isDimension ? newNullAMode : nullAMode, isDimension, drawingCtx);
+            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> recursiveNode.execute(x, index, getNewCtx(ctx, axisOrDim, newNullAMode), axisOrDim);
             switch (expr.op) {
                 case "+":
                     return recursive.apply(expr.arg1, L_adding) + recursive.apply(expr.arg2, L_adding);
@@ -496,11 +539,11 @@ public class Unit {
             }
 
             // must be aggregate operation
-            int newNullAMode = isDimension ? getNullAMode(expr.op) : nullAMode;
+            UnitConversionContext newCtx = getNewCtx(ctx, axisOrDim, getNullAMode(expr.op));
             int len = unitLengthNode.execute(expr.arg1);
             double[] values = new double[len];
             for (int i = 0; i < len; i++) {
-                values[i] = recursiveNode.execute(expr.arg1, i, vpSize, scalemin, scalemax, nullLMode, newNullAMode, isDimension, drawingCtx);
+                values[i] = recursiveNode.execute(expr.arg1, i, newCtx, axisOrDim);
             }
 
             switch (expr.op) {
@@ -515,6 +558,12 @@ public class Unit {
             }
         }
 
+        // Note the catch: newNullAMode is applied only if the axisOrDim is dimension
+        private static UnitConversionContext getNewCtx(UnitConversionContext ctx, AxisOrDimension axisOrDim, int newNullAMode) {
+            return new UnitConversionContext(ctx.viewPortSize, ctx.viewPortContext, ctx.device, ctx.drawingContext, ctx.nullLayoutMode,
+                            axisOrDim.isDimension() ? newNullAMode : ctx.nullArithmeticMode);
+        }
+
         private static int getNullAMode(String op) {
             switch (op) {
                 case "min":
@@ -543,7 +592,7 @@ public class Unit {
 
         // transcribed from unit.c function evaluateGrobUnit
 
-        public double execute(double value, int unitId, Object grob, int nullLMode, int nullAMode) {
+        public double execute(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
             GridContext ctx = GridContext.getContext();
             RList currentVP = ctx.getGridState().getViewPort();
             getViewPortTransform.execute(currentVP);
@@ -571,10 +620,10 @@ public class Unit {
                 case GROBY:
                     if (unitId == GROBY && isRelativeUnit.execute(unitxy.getDataAt(1), 0)) {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), nullLMode, nullAMode);
+                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else if (isRelativeUnit.execute(unitxy.getDataAt(0), 0)) {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), nullLMode, nullAMode);
+                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else {
                         throw RInternalError.unimplemented("GrobUnitToInches from unit.c: 610");
                     }
@@ -585,16 +634,16 @@ public class Unit {
                         // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
                         // GROBHEIGHT, bug?
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), nullLMode, nullAMode);
+                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else {
-                        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, GPar.asDrawingContext(currentGP));
+                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.asDrawingContext(currentGP));
                         initUnitToInchesNode();
                         if (unitId == GROBWIDTH) {
-                            result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, conversionCtx);
+                            result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                         } else {
                             // Note: GnuR uses height transform for both grobascent, grobdescent and
                             // for height
-                            result = unitToInchesNode.convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, conversionCtx);
+                            result = unitToInchesNode.convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                         }
                     }
                     break;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index 6b0b5d88be..ba396e0f39 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
 import com.oracle.truffle.r.library.fastrGrid.LLines;
 import com.oracle.truffle.r.library.fastrGrid.LNewPage;
 import com.oracle.truffle.r.library.fastrGrid.LPoints;
+import com.oracle.truffle.r.library.fastrGrid.LPolygon;
 import com.oracle.truffle.r.library.fastrGrid.LRect;
 import com.oracle.truffle.r.library.fastrGrid.LSegments;
 import com.oracle.truffle.r.library.fastrGrid.LText;
@@ -702,6 +703,8 @@ public class CallAndExternalFunctions {
                     return LRect.create();
                 case "L_lines":
                     return LLines.create();
+                case "L_polygon":
+                    return LPolygon.create();
                 case "L_text":
                     return LText.create();
                 case "L_textBounds":
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 8cef96974b..0095ec54be 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -783,7 +783,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtil
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java,gnu_r.copyright
-- 
GitLab


From 3dd52c8ccedf9f1a38f27420ea6a001087cc0e5b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 17 Mar 2017 17:56:25 +0100
Subject: [PATCH 162/402] FastR Grid: more view-port features implemented

---
 .../r/library/fastrGrid/DoSetViewPort.java    | 67 ++++++++------
 .../truffle/r/library/fastrGrid/GPar.java     |  6 +-
 .../r/library/fastrGrid/GridLinesNode.java    |  6 +-
 .../r/library/fastrGrid/GridTextNode.java     |  7 +-
 .../truffle/r/library/fastrGrid/LCircle.java  |  6 +-
 .../truffle/r/library/fastrGrid/LConvert.java |  6 +-
 .../truffle/r/library/fastrGrid/LPoints.java  |  7 +-
 .../truffle/r/library/fastrGrid/LRect.java    |  6 +-
 .../r/library/fastrGrid/LSegments.java        |  6 +-
 .../r/library/fastrGrid/LUnsetViewPort.java   | 88 +++++++++++++++++++
 .../truffle/r/library/fastrGrid/Unit.java     |  9 +-
 .../truffle/r/library/fastrGrid/ViewPort.java | 19 ++++
 .../r/library/fastrGrid/ViewPortContext.java  | 35 ++++----
 .../r/library/fastrGrid/ViewPortLocation.java | 48 +++++-----
 .../library/fastrGrid/ViewPortTransform.java  | 20 ++++-
 .../library/fastrGrid/device/GridDevice.java  |  2 +-
 .../fastrGrid/device/JFrameDevice.java        | 18 +---
 .../truffle/r/library/fastrGrid/fastrGrid.R   | 16 +++-
 .../foreign/CallAndExternalFunctions.java     |  3 +
 mx.fastr/copyrights/overrides                 |  1 +
 20 files changed, 247 insertions(+), 129 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index ec20b0d423..f15ca369fd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -12,12 +12,14 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.flatten;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.fromFlat;
-import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.identity;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
+import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.rotation;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
@@ -26,8 +28,6 @@ import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortLocation.VPLocationFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -50,8 +50,6 @@ class DoSetViewPort extends RBaseNode {
     @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
     @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
     @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
-    @Child private VPLocationFromVPNode vpLocationFromVP = new VPLocationFromVPNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
     @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
 
     public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
@@ -66,7 +64,10 @@ class DoSetViewPort extends RBaseNode {
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
         DrawingContext deviceDrawingContext = GridState.getInitialGPar(currentDevice);
-        calcViewportTransform(pushedViewPort, pushedViewPort.getDataAt(ViewPort.PVP_PARENT), !hasParent, currentDevice, deviceDrawingContext);
+
+        RList parent = asListOrNull(pushedViewPort.getDataAt(ViewPort.PVP_PARENT));
+        boolean doNotRecalculateParent = hasParent && !ViewPort.updateDeviceSizeInVP(parent, currentDevice);
+        calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, deviceDrawingContext);
 
         // TODO: clipping
         pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
@@ -75,18 +76,32 @@ class DoSetViewPort extends RBaseNode {
         return pushedViewPort;
     }
 
-    private void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
+    /**
+     * Calculates and sets the view-port width and height in inches, and transformation matrix and
+     * rotation angle.
+     *
+     * @param viewPort The view-port to be updated.
+     * @param parent The parent of the view-port, null if the view-port is top level.
+     * @param incremental If {@code true} it is assumed that we can just take the transformation
+     *            matrix and other values from the parent without re-calculating them recursively.
+     * @param device This method needs the device in order to convert units
+     * @param deviceDrawingContext This method needs to know the device default drawing context in
+     *            order to convert units for the top level view port
+     */
+    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
         Size parentSize;
         DrawingContext drawingContext;
+        double parentAngle;
         if (parent == null || parent == RNull.instance) {
             parentTransform = TransformMatrix.identity();
             parentContext = ViewPortContext.createDefault();
             parentSize = new Size(device.getWidth(), device.getHeight());
-            vpl = vpLocationFromVP.execute(viewPort);
+            vpl = ViewPortLocation.fromViewPort(viewPort);
             drawingContext = deviceDrawingContext;
+            parentAngle = 0;
         } else {
             assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list";
             RList parentVPList = (RList) parent;
@@ -96,12 +111,13 @@ class DoSetViewPort extends RBaseNode {
             }
             parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
             parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
-            parentContext = vpContextFromVP.execute(parentVPList);
+            parentContext = ViewPortContext.fromViewPort(parentVPList);
+            parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]);
 
             drawingContext = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
             boolean noLayout = (isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSROW)) && isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSCOL))) || isNull(parentData[ViewPort.VP_LAYOUT]);
             if (noLayout) {
-                vpl = vpLocationFromVP.execute(viewPort);
+                vpl = ViewPortLocation.fromViewPort(viewPort);
             } else {
                 vpl = calcViewportLocationFromLayout(getLayoutPos(viewPort, parentVPList), parentVPList, parentSize);
             }
@@ -122,11 +138,10 @@ class DoSetViewPort extends RBaseNode {
 
         // Produce transform for this viewport
         double[][] thisLocation = translation(xInches, yInches);
-        double[][] thisRotation = identity();
-        // TODO: if (viewportAngle(vp) != 0) rotation(viewportAngle(vp), thisRotation);
-
         double[][] thisJustification = translation(xadj, yadj);
         // Position relative to origin of rotation THEN rotate.
+        double viewPortAngle = asDouble(viewPort.getDataAt(ViewPort.VP_ANGLE));
+        double[][] thisRotation = rotation(viewPortAngle);
         double[][] tempTransform = multiply(thisJustification, thisRotation);
         // Translate to bottom-left corner.
         double[][] thisTransform = multiply(tempTransform, thisLocation);
@@ -134,12 +149,11 @@ class DoSetViewPort extends RBaseNode {
         double[][] transform = multiply(thisTransform, parentTransform);
 
         // Sum up the rotation angles
-        // TODO: rotationAngle = parentAngle + viewportAngle(vp);
-        double rotationAngle = 0;
+        double rotationAngle = parentAngle + viewPortAngle;
 
         // Finally, allocate the rows and columns for this viewport's layout if it has one
         if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) {
-            ViewPortContext vpCtx = vpContextFromVP.execute(viewPort);
+            ViewPortContext vpCtx = ViewPortContext.fromViewPort(viewPort);
             DrawingContext drawingCtx = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)));
             calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, drawingCtx);
         }
@@ -178,8 +192,8 @@ class DoSetViewPort extends RBaseNode {
         int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT));
         int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying();
         if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) {
-            double sumRelWidth = sumRelativeDimension(layoutSize, layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
-            double sumRelHeight = sumRelativeDimension(layoutSize, layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
+            double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
+            double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
             double tempWidth = reducedWidth;
             double tempHeight = reducedHeight;
             double denom;
@@ -244,17 +258,18 @@ class DoSetViewPort extends RBaseNode {
 
     private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
                     GridDevice device, DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
+        assert relativeItems.length == npcItems.length;
         UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
         double totalUnrespectedSize = 0;
         if (reducedDim > 0) {
-            for (int i = 0; i < layoutSize.ncol; i++) {
+            for (int i = 0; i < relativeItems.length; i++) {
                 if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
                     totalUnrespectedSize += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
                 }
             }
         }
         // set the remaining width/height to zero or to proportion of totalUnrespectedSize
-        for (int i = 0; i < layoutSize.ncol; i++) {
+        for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
                 npcItems[i] = 0;
                 if (totalUnrespectedSize > 0) {
@@ -265,8 +280,8 @@ class DoSetViewPort extends RBaseNode {
         }
     }
 
-    private boolean rowColRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
-        return isColumn ? colRespected(respected, respected, layoutRespectMat, layoutSize) : rowRespected(respected, row, layoutRespectMat, layoutSize);
+    private boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
+        return isColumn ? colRespected(respected, rowOrCol, layoutRespectMat, layoutSize) : rowRespected(respected, rowOrCol, layoutRespectMat, layoutSize);
     }
 
     private boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
@@ -293,11 +308,11 @@ class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(LayoutSize layoutSize, RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
+    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
                     boolean isWidth) {
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 0, 1);
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
         double totalWidth = 0;
-        for (int i = 0; i < layoutSize.ncol; i++) {
+        for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i]) {
                 totalWidth += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
             }
@@ -349,7 +364,7 @@ class DoSetViewPort extends RBaseNode {
         double totalHeight = sum(heights, 0, pos.layoutSize.nrow);
         double width = sum(widths, pos.colMin, pos.colMax - pos.colMin + 1);
         double height = sum(heights, pos.rowMin, pos.rowMax - pos.rowMin + 1);
-        double left = parentSize.getWidth() * pos.layoutSize.hjust - totalWidth * pos.layoutSize.hjust + sum(widths, 0, pos.colMin - 1);
+        double left = parentSize.getWidth() * pos.layoutSize.hjust - totalWidth * pos.layoutSize.hjust + sum(widths, 0, pos.colMin);
         double bottom = parentSize.getHeight() * pos.layoutSize.vjust + (1 - pos.layoutSize.vjust) * totalHeight - sum(heights, 0, pos.rowMax + 1);
         ViewPortLocation result = new ViewPortLocation();
         result.width = newUnit(width, Unit.INCHES);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 33d7761a60..322ce43195 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -82,14 +82,14 @@ public final class GPar {
     public static RList createNew() {
         Object[] data = new Object[GP_LENGTH];
         Arrays.fill(data, RNull.instance);
-        data[GP_FILL] = "grey";
+        data[GP_FILL] = "transparent";
         data[GP_COL] = "black";
         data[GP_GAMMA] = newDoubleVec(0);
         data[GP_LTY] = "solid"; // TODO: LineType enum...
         data[GP_LWD] = newDoubleVec(1);
         data[GP_CEX] = newDoubleVec(1);
-        data[GP_FONTSIZE] = newDoubleVec(12);
-        data[GP_LINEHEIGHT] = newDoubleVec(1.0);
+        data[GP_FONTSIZE] = newDoubleVec(16);
+        data[GP_LINEHEIGHT] = newDoubleVec(1.2);
         data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);  // TODO: font constants?
         data[GP_FONTFAMILY] = ""; // means default font (probably)
         data[GP_ALPHA] = newDoubleVec(1);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 695175e7c2..24cb71abc5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -43,7 +42,6 @@ public abstract class GridLinesNode extends Node {
 
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     void execute(RAbstractVector x, RAbstractVector y, RList lengths) {
         GridContext ctx = GridContext.getContext();
@@ -51,8 +49,8 @@ public abstract class GridLinesNode extends Node {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         // Convert the list of vectors of indexes to type-safe array and calculate the max length of
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 13e52dfc66..2c6dc5a516 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -34,7 +34,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -58,7 +57,7 @@ public final class GridTextNode extends RBaseNode {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
     private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile();
     private final boolean draw;
 
@@ -95,8 +94,8 @@ public final class GridTextNode extends RBaseNode {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, x, y);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index c5262bd3ff..4fc29b79f7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -29,7 +28,6 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LCircle.class);
@@ -49,8 +47,8 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 3703c83baa..96792070cc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -21,7 +21,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -36,7 +35,6 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LConvert.class);
@@ -58,8 +56,8 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = unitLength.execute(units);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 67604044ec..0c457f1bed 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -18,7 +18,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
@@ -41,7 +40,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
 
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
     @Child private UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
 
@@ -66,8 +65,8 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         RList gpar = ctx.getGridState().getGpar();
         DrawingContext drawingCtx = GPar.asDrawingContext(gpar);
         double cex = GPar.getCex(gpar);
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         // Note: unlike in other drawing primitives, we only consider length of x
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index e79c9dcd67..062d23c46d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -31,7 +30,6 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LRect.class);
@@ -54,8 +52,8 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 426234d0fb..33e8f7d514 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -32,7 +31,6 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
 
     static {
         Casts casts = new Casts(LSegments.class);
@@ -53,8 +51,8 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-        ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
 
         int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
new file mode 100644
index 0000000000..153358e5ef
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -0,0 +1,88 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
+
+public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
+    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
+
+    static {
+        Casts casts = new Casts(LUnsetViewPort.class);
+        casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst();
+    }
+
+    public static LUnsetViewPort create() {
+        return LUnsetViewPortNodeGen.create();
+    }
+
+    @Specialization
+    Object unsetViewPort(int n) {
+        GridContext ctx = GridContext.getContext();
+        GridState gridState = ctx.getGridState();
+
+        // go n-steps up the view-port tree
+        RList gvp = gridState.getViewPort();
+        RList newVp = gvp;
+        for (int i = 0; i < n; i++) {
+            gvp = newVp;
+            newVp = asListOrNull(gvp.getDataAt(ViewPort.PVP_PARENT));
+            if (newVp == null) {
+                throw error(Message.GENERIC, "cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)");
+            }
+        }
+
+        // gvp will be removed, newVp will be the new view-port
+        // first update children of newVp -> remove gvp
+        REnvironment children = (REnvironment) newVp.getDataAt(ViewPort.PVP_CHILDREN);
+        String gvpName = RRuntime.asString(gvp.getDataAt(ViewPort.VP_NAME));
+        safeRemoveFromEnv(children, gvpName);
+
+        // update newVp transform etc. because it will be the current vp, it has to be up to date
+        GridDevice device = ctx.getCurrentDevice();
+        if (ViewPort.updateDeviceSizeInVP(newVp, device)) {
+            // Note: like in other places calling this, why incremental == true, given that the
+            // device has changed? Don't we want to recalculate the whole tree?
+            doSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
+        }
+
+        gridState.setGpar(asList(newVp.getDataAt(ViewPort.PVP_GPAR)));
+
+        // TODO: clipping
+        gridState.setViewPort(newVp);
+
+        // remove the parent link from the old viewport
+        gvp.setDataAt(gvp.getInternalStore(), ViewPort.PVP_PARENT, null);
+        return RNull.instance;
+    }
+
+    private void safeRemoveFromEnv(REnvironment children, String gvpName) {
+        try {
+            children.rm(gvpName);
+        } catch (PutException e) {
+            throw RInternalError.shouldNotReachHere("Cannot update view-port children environment");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index a9dd76013c..fb8112cb3e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitLengthNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortContext.VPContextFromVPNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -586,7 +585,7 @@ public class Unit {
         @Child private RGridCodeCall getUnitXY = new RGridCodeCall("grobConversionGetUnitXY");
         @Child private RGridCodeCall postDrawCode = new RGridCodeCall("grobConversionPostDraw");
         @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-        @Child private VPContextFromVPNode vpContextFromVP = new VPContextFromVPNode();
+
         @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
         @Child private UnitToInchesNode unitToInchesNode;
 
@@ -595,7 +594,7 @@ public class Unit {
         public double execute(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
             GridContext ctx = GridContext.getContext();
             RList currentVP = ctx.getGridState().getViewPort();
-            getViewPortTransform.execute(currentVP);
+            getViewPortTransform.execute(currentVP, conversionCtx.device);
 
             RList savedGPar = ctx.getGridState().getGpar();
             Object savedGrob = ctx.getGridState().getCurrentGrob();
@@ -609,8 +608,8 @@ public class Unit {
              */
             currentVP = ctx.getGridState().getViewPort();
             RList currentGP = ctx.getGridState().getGpar();
-            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP);
-            ViewPortContext vpContext = vpContextFromVP.execute(currentVP);
+            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, conversionCtx.device);
+            ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
 
             // getUnitXY returns a list with either one or two items
             RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId}, ArgumentsSignature.empty(2)));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 7bf24ec0aa..99fdd428d3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -11,7 +11,9 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.inchesToCm;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
@@ -80,6 +82,23 @@ class ViewPort {
     public static final int LAYOUT_JUST = 7;
     private static final int LAYOUT_VJUST = 8;
 
+    /**
+     * Updates the device size in the viewport and returns {@code true} if the size has changed.
+     */
+    public static boolean updateDeviceSizeInVP(RList viewPort, GridDevice device) {
+        double devWidthCm = inchesToCm(device.getWidth());
+        boolean result = false;
+        if (Math.abs(devWidthCm - asDouble(viewPort.getDataAt(PVP_DEVWIDTHCM))) >= 1e-6) {
+            viewPort.setDataAt(viewPort.getInternalStore(), PVP_DEVWIDTHCM, devWidthCm);
+            result = true;
+        }
+        double devHeightCm = inchesToCm(device.getHeight());
+        if (Math.abs(devHeightCm - asDouble(viewPort.getDataAt(PVP_DEVHEIGHTCM))) >= 1e-6) {
+            viewPort.setDataAt(viewPort.getInternalStore(), PVP_DEVHEIGHTCM, devHeightCm);
+        }
+        return result;
+    }
+
     /**
      * Represents the integer values extracted from {@link #LAYOUT_NCOL} and {@link #LAYOUT_NROW}.
      * In the R world, RNulls are valid values for those, we convert them to -1 to keep type safety.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
index e07043ce1c..0eb93b84f9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java
@@ -11,11 +11,10 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector;
 
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
-import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
@@ -37,22 +36,20 @@ public final class ViewPortContext {
         return result;
     }
 
-    public static final class VPContextFromVPNode extends Node {
-        @Child private CastNode castVector = newCastBuilder().asDoubleVector().mustBe(Predef.size(2)).buildCastNode();
-
-        public ViewPortContext execute(RList viewPort) {
-            ViewPortContext result = new ViewPortContext();
-            RAbstractDoubleVector x = castVec(viewPort.getDataAt(ViewPort.VP_XSCALE));
-            result.xscalemin = x.getDataAt(0);
-            result.xscalemax = x.getDataAt(1);
-            RAbstractDoubleVector y = castVec(viewPort.getDataAt(ViewPort.VP_YSCALE));
-            result.yscalemin = y.getDataAt(0);
-            result.yscalemax = y.getDataAt(1);
-            return result;
+    public static ViewPortContext fromViewPort(RList viewPort) {
+        ViewPortContext result = new ViewPortContext();
+        RAbstractDoubleVector x = asDoubleVector(viewPort.getDataAt(ViewPort.VP_XSCALE));
+        if (x.getLength() != 2) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "view-port xscale must be vector of size 2");
         }
-
-        private RAbstractDoubleVector castVec(Object val) {
-            return (RAbstractDoubleVector) castVector.execute(val);
+        result.xscalemin = x.getDataAt(0);
+        result.xscalemax = x.getDataAt(1);
+        RAbstractDoubleVector y = asDoubleVector(viewPort.getDataAt(ViewPort.VP_YSCALE));
+        if (y.getLength() != 2) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "view-port yscale must be vector of size 2");
         }
+        result.yscalemin = y.getDataAt(0);
+        result.yscalemax = y.getDataAt(1);
+        return result;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
index 894d8d90e1..2ea1a4d776 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
@@ -11,13 +11,13 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector;
 
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 /**
@@ -25,31 +25,25 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
  * for them. However, the unit object should contain only single value.
  */
 public class ViewPortLocation {
-    public RAbstractDoubleVector x;
-    public RAbstractDoubleVector y;
-    public RAbstractDoubleVector width;
-    public RAbstractDoubleVector height;
+    public RAbstractContainer x;
+    public RAbstractContainer y;
+    public RAbstractContainer width;
+    public RAbstractContainer height;
     public double hjust;
     public double vjust;
 
-    public static final class VPLocationFromVPNode extends Node {
-        @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
-        @Child private CastNode castJustVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().mustBe(size(2)).buildCastNode();
-
-        public ViewPortLocation execute(RList viewPort) {
-            ViewPortLocation r = new ViewPortLocation();
-            r.x = vec(viewPort.getDataAt(ViewPort.VP_X));
-            r.y = vec(viewPort.getDataAt(ViewPort.VP_Y));
-            r.width = vec(viewPort.getDataAt(ViewPort.VP_WIDTH));
-            r.height = vec(viewPort.getDataAt(ViewPort.VP_HEIGHT));
-            RAbstractDoubleVector just = (RAbstractDoubleVector) castJustVector.execute(viewPort.getDataAt(ViewPort.VP_VALIDJUST));
-            r.hjust = just.getDataAt(0);
-            r.vjust = just.getDataAt(1);
-            return r;
-        }
-
-        private RAbstractDoubleVector vec(Object val) {
-            return (RAbstractDoubleVector) castDoubleVector.execute(val);
+    public static ViewPortLocation fromViewPort(RList viewPort) {
+        ViewPortLocation r = new ViewPortLocation();
+        r.x = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_X));
+        r.y = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_Y));
+        r.width = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_WIDTH));
+        r.height = asAbstractContainer(viewPort.getDataAt(ViewPort.VP_HEIGHT));
+        RAbstractDoubleVector just = asDoubleVector(viewPort.getDataAt(ViewPort.VP_VALIDJUST));
+        if (just.getLength() != 2) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected size of layout justification vector.");
         }
+        r.hjust = just.getDataAt(0);
+        r.vjust = just.getDataAt(1);
+        return r;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
index cc7656af20..0e8ea8aa08 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -14,7 +14,9 @@ package com.oracle.truffle.r.library.fastrGrid;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -36,10 +38,15 @@ public final class ViewPortTransform {
     public static final class GetViewPortTransformNode extends Node {
         @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
         @Child private CastNode castScalarDouble = newCastBuilder().mustBe(numericValue()).asDoubleVector().findFirst().buildCastNode();
+        @Child private DoSetViewPort doSetViewPort;
 
-        public ViewPortTransform execute(RList viewPort) {
-            // TODO: if device has changed, recalculate the VP transform!!! Some code, e.g.
-            // GrobUnitToInches relies on that
+        public ViewPortTransform execute(RList viewPort, GridDevice device) {
+            if (ViewPort.updateDeviceSizeInVP(viewPort, device)) {
+                // Note: GnuR sets incremental parameter to true, but don't we need to recalculate
+                // the parent(s) as well?
+                initDoSetViewportNode();
+                doSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
+            }
             double width = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
             double height = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
             double rotationAngle = getScalar(viewPort.getDataAt(ViewPort.VP_ANGLE));
@@ -48,6 +55,13 @@ public final class ViewPortTransform {
             return new ViewPortTransform(width, height, rotationAngle, transform);
         }
 
+        private void initDoSetViewportNode() {
+            if (doSetViewPort == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                doSetViewPort = new DoSetViewPort();
+            }
+        }
+
         private double getScalar(Object value) {
             return (double) castScalarDouble.execute(value);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 1f0a0d8f03..9e37a873bb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -31,7 +31,7 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 public interface GridDevice {
     void openNewPage();
 
-    void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width);
+    void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height);
 
     /**
      * Connects given points with a line, there has to be at least two points in order to actually
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 758ae81683..8fea72124b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -36,8 +36,6 @@ import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
 import java.util.function.Supplier;
 
-import javax.swing.UIManager;
-
 import com.oracle.truffle.r.library.graphics.FastRFrame;
 
 public class JFrameDevice implements GridDevice {
@@ -71,9 +69,9 @@ public class JFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double topY, double heigh, double width) {
+    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height) {
         setContext(ctx);
-        drawShape(ctx, new Rectangle2D.Double(leftX, topY, heigh, width));
+        drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height));
     }
 
     @Override
@@ -139,14 +137,6 @@ public class JFrameDevice implements GridDevice {
         });
     }
 
-    @Override
-    public void initDrawingContext(DrawingContext ctx) {
-        Color color = UIManager.getColor("Panel.background");
-        if (color != null) {
-            ctx.setFillColor(toGridColor(color));
-        }
-    }
-
     private void drawShape(DrawingContext drawingCtx, Shape shape) {
         Paint paint = graphics.getPaint();
         graphics.setPaint(fromGridColor(drawingCtx.getFillColor()));
@@ -175,8 +165,4 @@ public class JFrameDevice implements GridDevice {
     private static Color fromGridColor(GridColor color) {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
-
-    private static GridColor toGridColor(Color color) {
-        return new GridColor(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index 84f733bb59..30a16598ea 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -45,6 +45,19 @@ L_setviewport <- function(vp, hasParent) {
     .Internal(.fastr.grid.doSetViewPort(pushedVP, hasParent, TRUE));
 }
 
+L_unsetviewport <- function(n) {
+    gvp <- .Call(grid:::L_currentViewport)
+    newVp <- gvp;
+    for (i in 1:n) {
+        gvp <- newVp;
+        newVp <- gvp$parent;
+        if (is.null(newVp)) {
+            error("cannot pop the top-level viewport ('grid' and 'graphics' output mixed?)")
+        }
+    }
+    # remove
+}
+
 ###################################################
 # Helper functions to deal with null and grob units
 # these functions are invoked from Java directly
@@ -80,7 +93,8 @@ isPureNullUnit <- function(unit, index) {
     } else if (inherits(unit, "unit.list")) {
         return(isPureNullUnit(unit[[indexMod(index, length(unit))]], 1))
     }
-    unitId <- attr(unit, "valid.unit")
+    unitIdVec <- attr(unit, "valid.unit")
+    unitId <- unitIdVec[[indexMod(index, length(unitIdVec))]]
     if (unitId == L_GROBWIDTH) {
         return(isPureNullUnitGrobDim(unit, index, grid:::width))
     } else if (unitId == L_GROBHEIGHT) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index ba396e0f39..cbb9714312 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.library.fastrGrid.LRect;
 import com.oracle.truffle.r.library.fastrGrid.LSegments;
 import com.oracle.truffle.r.library.fastrGrid.LText;
 import com.oracle.truffle.r.library.fastrGrid.LTextBounds;
+import com.oracle.truffle.r.library.fastrGrid.LUnsetViewPort;
 import com.oracle.truffle.r.library.fastrGrid.LUpViewPort;
 import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
 import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
@@ -694,6 +695,8 @@ public class CallAndExternalFunctions {
                     return LUpViewPort.create();
                 case "L_initViewportStack":
                     return new LInitViewPortStack();
+                case "L_unsetviewport":
+                    return LUnsetViewPort.create();
                 case "L_setviewport":
                 case "L_downviewport":
                     return getExternalFastRGridBuiltinNode(name);
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 0095ec54be..7c18b674af 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -778,6 +778,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.jav
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
-- 
GitLab


From 193fbef0ee90885f02dcee860895b04da1628955 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 21 Mar 2017 16:24:20 +0100
Subject: [PATCH 163/402] FastR Grid: support arrows

---
 .../r/library/fastrGrid/DrawArrowsNode.java   | 99 +++++++++++++++++++
 .../r/library/fastrGrid/GridLinesNode.java    |  8 +-
 .../r/library/fastrGrid/GridUtils.java        | 24 +++++
 .../truffle/r/library/fastrGrid/LLines.java   | 12 ++-
 .../truffle/r/library/fastrGrid/LPolygon.java |  2 +-
 .../r/library/fastrGrid/LSegments.java        | 12 ++-
 mx.fastr/copyrights/overrides                 |  1 +
 7 files changed, 152 insertions(+), 6 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
new file mode 100644
index 0000000000..21a2208f16
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
@@ -0,0 +1,99 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asInt;
+
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+
+public class DrawArrowsNode extends Node {
+    // Structure of an arrow description
+    public static final int ARROWANGLE = 0;
+    public static final int ARROWLENGTH = 1;
+    public static final int ARROWENDS = 2;
+    public static final int ARROWTYPE = 3;
+    // known values of ARROWTYPE
+    public static final int ARROWTYPE_LINES = 1;
+    public static final int ARROWTYPE_POLYGON = 2;
+
+    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
+
+    /**
+     * Draws arrows at the start and end of given lines.
+     *
+     * @param x x-positions of the line(s)
+     * @param y y-positions of the line(s)
+     * @param startIndex consider arrays x,y to start from this index
+     * @param length consider arrays x,y to have this length
+     * @param parentIndex the index of the line we are drawing, this is used for choosing the right
+     *            index into vectors extracted from arrow
+     * @param arrow list with various attributes of the arrow
+     * @param start should we draw start arrow if the arrow list says so. Otherwise never draw it.
+     * @param end should we draw end arrow if the arrow list says so. Otherwise never draw it.
+     * @param conversionCtx needed for unit conversions.
+     */
+    public void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) {
+        assert x.length == y.length;
+        int endsVal = asInt(arrow.getDataAt(ARROWENDS), parentIndex);
+        boolean first = endsVal != 2;
+        boolean last = endsVal != 1;
+        if ((!first || !start) && (!last || !end)) {
+            // if we are not going to draw any arrow anyway, just finish
+            return;
+        }
+        // extract angle, length in inches and arrow type from 'arrow'
+        double angle = asDouble(arrow.getDataAt(ARROWANGLE), parentIndex);
+        int arrowType = asInt(arrow.getDataAt(ARROWTYPE), parentIndex);
+        RAbstractContainer lengthVec = asAbstractContainer(arrow.getDataAt(ARROWLENGTH));
+        double arrowLength = unitToInches.convertHeight(lengthVec, parentIndex, conversionCtx);
+        arrowLength = Math.max(arrowLength, unitToInches.convertWidth(lengthVec, parentIndex, conversionCtx));
+        // draw the arrows
+        GridDevice device = conversionCtx.device;
+        DrawingContext drawingCtx = conversionCtx.drawingContext;
+        if (first && start) {
+            drawArrow(drawingCtx, device, arrowType, x[startIndex], y[startIndex], x[startIndex + 1], y[startIndex + 1], angle, arrowLength);
+        }
+        if (last && end) {
+            int n = startIndex + length;
+            drawArrow(drawingCtx, device, arrowType, x[n - 1], y[n - 1], x[n - 2], y[n - 2], angle, arrowLength);
+        }
+    }
+
+    private void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) {
+        double a = Math.toRadians(angle);
+        double xc = x1 - x0;
+        double yc = y1 - y0;
+        double rot = Math.atan2(yc, xc);
+        double[] vertx = new double[3];
+        double[] verty = new double[3];
+        vertx[0] = x0 + length * Math.cos(rot + a);
+        verty[0] = y0 + length * Math.sin(rot + a);
+        vertx[1] = x0;
+        verty[1] = y0;
+        vertx[2] = x0 + length * Math.cos(rot - a);
+        verty[2] = y0 + length * Math.sin(rot - a);
+        if (arrowType == ARROWTYPE_LINES) {
+            device.drawPolyLines(drawingCtx, vertx, verty, 0, 3);
+        } else if (arrowType == ARROWTYPE_POLYGON) {
+            device.drawPolyLines(drawingCtx, vertx, verty, 0, 3);
+            // TODO: real polygon
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 24cb71abc5..11946cb521 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -42,8 +42,9 @@ public abstract class GridLinesNode extends Node {
 
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
 
-    void execute(RAbstractVector x, RAbstractVector y, RList lengths) {
+    void execute(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
 
@@ -90,6 +91,11 @@ public abstract class GridLinesNode extends Node {
                         // it's last iteration. This seems slightly weird, but that's how GnuR seems
                         // to work
                         drawPolylines(dev, drawingCtx, yy, xx, start, (i - start) + 1);
+                        if (arrow != null) {
+                            // Can draw an arrow at the start if the points include the first point.
+                            // Draw an arrow at the end only if this is the last series
+                            drawArrowsNode.drawArrows(xx, yy, start, (i - start) + 1, unitIndex, arrow, start == 0, lastIter, conversionCtx);
+                        }
                     }
                 }
                 oldIsFinite = currIsFinite;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 1b7ff9197a..c7680a918f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -124,6 +124,30 @@ final class GridUtils {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value " + val.getClass().getSimpleName());
     }
 
+    static double asDouble(Object val, int cyclicIndex) {
+        if (val instanceof Double) {
+            return (int) val;
+        } else if (val instanceof RAbstractDoubleVector) {
+            RAbstractDoubleVector vec = (RAbstractDoubleVector) val;
+            if (vec.getLength() > 0) {
+                return vec.getDataAt(cyclicIndex % vec.getLength());
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double value " + val.getClass().getSimpleName());
+    }
+
+    static int asInt(Object val, int cyclicIndex) {
+        if (val instanceof Integer) {
+            return (int) val;
+        } else if (val instanceof RAbstractIntVector) {
+            RAbstractIntVector vec = (RAbstractIntVector) val;
+            if (vec.getLength() > 0) {
+                return vec.getDataAt(cyclicIndex % vec.getLength());
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + val.getClass().getSimpleName());
+    }
+
     static RAbstractIntVector asIntVector(Object value) {
         if (value instanceof Integer) {
             return RDataFactory.createIntVectorFromScalar((Integer) value);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
index de27073452..e38149b8f1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -38,6 +38,7 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
         casts.arg(0).mustBe(abstractVectorValue());
         casts.arg(1).mustBe(abstractVectorValue());
         casts.arg(2).mustBe(RList.class);
+        casts.arg(2).allowNull().mustBe(RList.class);
     }
 
     public static LLines create() {
@@ -45,9 +46,14 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") Object arrowIgnored) {
-        // TODO: implement arrows
-        gridLinesNode.execute(x, y, lengths);
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, RNull arrowIgnored) {
+        gridLinesNode.execute(x, y, lengths, null);
+        return RNull.instance;
+    }
+
+    @Specialization
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") RList arrow) {
+        gridLinesNode.execute(x, y, lengths, arrow);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
index 8d4343e9ab..a4d8a917bd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPolygon.java
@@ -46,7 +46,7 @@ public abstract class LPolygon extends RExternalBuiltinNode.Arg3 {
 
     @Specialization
     Object doLines(RAbstractVector x, RAbstractVector y, RList lengths) {
-        gridLinesNode.execute(x, y, lengths);
+        gridLinesNode.execute(x, y, lengths, null);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 33e8f7d514..6ec185aef1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -31,6 +31,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
 
     static {
         Casts casts = new Casts(LSegments.class);
@@ -38,6 +39,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         casts.arg(1).mustBe(abstractVectorValue());
         casts.arg(2).mustBe(abstractVectorValue());
         casts.arg(3).mustBe(abstractVectorValue());
+        casts.arg(4).allowNull().mustBe(RList.class);
     }
 
     public static LSegments create() {
@@ -45,7 +47,12 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     }
 
     @Specialization
-    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, Object arrowIgnored) {
+    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RNull arrow) {
+        return doSegments(x0, y0, x1, y1, (RList) null);
+    }
+
+    @Specialization
+    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RList arrow) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
 
@@ -69,6 +76,9 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
             yy[0] = loc1.y;
             yy[1] = loc2.y;
             dev.drawPolyLines(drawingCtx, xx, yy, 0, 2);
+            if (arrow != null) {
+                drawArrowsNode.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
+            }
         }
         return RNull.instance;
     }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 7c18b674af..8dc2bf1018 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -767,6 +767,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
-- 
GitLab


From ab0e94a1722fe48337b940651ff8c206a27fc1d5 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 21 Mar 2017 17:53:16 +0100
Subject: [PATCH 164/402] FastR Grid: implement line styles

---
 .../truffle/r/library/fastrGrid/GPar.java     | 58 ++++++++++++++++++-
 .../fastrGrid/device/DrawingContext.java      | 24 ++++++++
 .../fastrGrid/device/JFrameDevice.java        | 49 ++++++++++++++++
 3 files changed, 130 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 322ce43195..41d785ee1f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -11,18 +11,23 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 
 import java.util.Arrays;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 /**
  * In the context of grid package, GPar is a list that contains the parameters for the drawing, like
@@ -85,7 +90,7 @@ public final class GPar {
         data[GP_FILL] = "transparent";
         data[GP_COL] = "black";
         data[GP_GAMMA] = newDoubleVec(0);
-        data[GP_LTY] = "solid"; // TODO: LineType enum...
+        data[GP_LTY] = "solid";
         data[GP_LWD] = newDoubleVec(1);
         data[GP_CEX] = newDoubleVec(1);
         data[GP_FONTSIZE] = newDoubleVec(16);
@@ -119,6 +124,35 @@ public final class GPar {
             data = list.getDataWithoutCopying();
         }
 
+        @Override
+        public GridLineType getLineType() {
+            Object lty = data[GP_LTY];
+            if (lty == null || lty == RNull.instance) {
+                return GridLineType.SOLID;
+            }
+            String name = RRuntime.asString(lty);
+            if (name != null) {
+                return lineTypeFromName(name);
+            }
+            RAbstractContainer ltyVec = asAbstractContainer(lty);
+            int num;
+            if (ltyVec.getLength() == 0) {
+                num = RRuntime.INT_NA;
+            } else if (ltyVec instanceof RAbstractDoubleVector) {
+                double realVal = ((RAbstractDoubleVector) ltyVec).getDataAt(0);
+                num = RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal;
+            } else if (ltyVec instanceof RAbstractIntVector) {
+                num = ((RAbstractIntVector) ltyVec).getDataAt(0);
+            } else {
+                num = RRuntime.INT_NA;
+            }
+
+            if (RRuntime.isNA(num)) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line type.");
+            }
+            return GridLineType.fromInt(num);
+        }
+
         @Override
         public GridColor getColor() {
             return getGridColor(GP_COL);
@@ -152,5 +186,27 @@ public final class GPar {
         private GridColor getGridColor(int index) {
             return GridColorUtils.gridColorFromString(RRuntime.asString(data[index]));
         }
+
+        private GridLineType lineTypeFromName(String name) {
+            switch (name) {
+                case "solid":
+                    return GridLineType.SOLID;
+                case "dashed":
+                    return GridLineType.DASHED;
+                case "dotted":
+                    return GridLineType.DOTTED;
+                case "dotdashed":
+                    return GridLineType.DOTDASHED;
+                case "longdash":
+                    return GridLineType.LONGDASH;
+                case "twodash":
+                    return GridLineType.TWODASH;
+                case "blank":
+                    return GridLineType.BLANK;
+                default:
+                    // TODO: implement hex digits as line style
+                    throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected line type '" + name + "'.");
+            }
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index ca1e987c1b..f3d42fa703 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -28,6 +28,30 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 public interface DrawingContext {
     double INCH_TO_POINTS_FACTOR = 72.27;
 
+    enum GridLineType {
+        // The order is important!
+        BLANK,
+        SOLID,
+        DASHED,
+        DOTTED,
+        DOTDASHED,
+        LONGDASH,
+        TWODASH;
+
+        private static final int LINE_TYPES_COUNT = 7;
+        private static final GridLineType[] allValues = values();
+
+        public static GridLineType fromInt(int num) {
+            if (num == -1) {
+                return BLANK;
+            }
+            assert num >= 1;
+            return allValues[(num - 1) % LINE_TYPES_COUNT + 1];
+        }
+    }
+
+    GridLineType getLineType();
+
     GridColor getColor();
 
     /**
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 8fea72124b..ea216ae304 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -36,7 +36,9 @@ import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
 import java.util.function.Supplier;
 
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineType;
 import com.oracle.truffle.r.library.graphics.FastRFrame;
+import com.oracle.truffle.r.runtime.RInternalError;
 
 public class JFrameDevice implements GridDevice {
     // Grid's coordinate system has origin in left bottom corner and y axis grows from bottom to
@@ -46,11 +48,20 @@ public class JFrameDevice implements GridDevice {
     // only, we reset the transformation completely and transform the coordinates ourselves
     private static final double POINTS_IN_INCH = 72.;
 
+    private static BasicStroke solidStroke;
+    private static BasicStroke blankStroke;
+    private static BasicStroke dashedStroke;
+    private static BasicStroke longdashedStroke;
+    private static BasicStroke twodashedStroke;
+    private static BasicStroke dotdashedStroke;
+    private static BasicStroke dottedStroke;
+
     private FastRFrame currentFrame;
     private Graphics2D graphics;
 
     @Override
     public void openNewPage() {
+        initStrokes();
         if (currentFrame == null) {
             currentFrame = new FastRFrame();
             currentFrame.setVisible(true);
@@ -147,6 +158,7 @@ public class JFrameDevice implements GridDevice {
 
     private void setContext(DrawingContext ctx) {
         graphics.setColor(fromGridColor(ctx.getColor()));
+        graphics.setStroke(fromGridLineType(ctx.getLineType()));
     }
 
     private void setFontSize(DrawingContext ctx) {
@@ -165,4 +177,41 @@ public class JFrameDevice implements GridDevice {
     private static Color fromGridColor(GridColor color) {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
+
+    private static BasicStroke fromGridLineType(GridLineType type) {
+        switch (type) {
+            case SOLID:
+                return solidStroke;
+            case BLANK:
+                return blankStroke;
+            case DASHED:
+                return dashedStroke;
+            case DOTDASHED:
+                return dotdashedStroke;
+            case DOTTED:
+                return dottedStroke;
+            case TWODASH:
+                return twodashedStroke;
+            case LONGDASH:
+                return longdashedStroke;
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected value of GridLineType enum");
+        }
+    }
+
+    private static void initStrokes() {
+        if (solidStroke != null) {
+            return;
+        }
+        float defaultWidth = (float) (1. / POINTS_IN_INCH);
+        float dashSize = (float) (10. / POINTS_IN_INCH);
+        float dotSize = (float) (2. / POINTS_IN_INCH);
+        solidStroke = new BasicStroke((float) (1f / POINTS_IN_INCH));
+        blankStroke = new BasicStroke(0f);
+        dashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize}, 0f);
+        dottedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dotSize}, 0f);
+        dotdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dotSize, dashSize}, 0f);
+        twodashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize / 2f, dashSize}, 0f);
+        longdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{2f * dashSize}, 0f);
+    }
 }
-- 
GitLab


From e5b2c92648108fd2a669a0fd4c06e7221b11f8cc Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 22 Mar 2017 14:50:03 +0100
Subject: [PATCH 165/402] Remove old FastR java graphics & provide grDevices
 and graphics simulation layer for FastR grid.

---
 .../r/library/fastrGrid/DrawArrowsNode.java   |  14 +-
 .../fastrGrid/FastRGridExternalLookup.java    | 151 +++++++++
 .../r/library/fastrGrid/GridStateGetNode.java |   4 +-
 .../fastrGrid/IgnoredGridExternal.java        |   4 +-
 .../r/library/fastrGrid/LGridDirty.java       |   2 +-
 .../r/library/fastrGrid/LInitGPar.java        |   2 +-
 .../library/fastrGrid/LInitViewPortStack.java |   2 +-
 .../truffle/r/library/fastrGrid/LNewPage.java |   2 +-
 .../fastrGrid/device/JFrameDevice.java        |  47 ++-
 .../grDevices/InitWindowedDevice.java         |  52 +++
 .../fastrGrid/grDevices/R/fastrGridDevices.R  |  30 ++
 .../fastrGrid/grDevices/package-info.java     |  31 ++
 .../graphics/RGridGraphicsAdapter.java        |  73 ++++
 .../r/library/grDevices/DevicesCCalls.java    | 125 -------
 .../library/grDevices/NullGraphicsDevice.java |  71 ----
 .../fastrgd/FastRGraphicsDevice.java          | 137 --------
 .../grDevices/pdf/PdfGraphicsDevice.java      |  91 -----
 .../library/graphics/BaseGraphicsSystem.java  |  30 --
 .../r/library/graphics/FastRComponent.java    |  84 -----
 .../r/library/graphics/FastRFrame.java        |  75 -----
 .../r/library/graphics/GraphicsCCalls.java    | 137 --------
 .../truffle/r/library/graphics/RGraphics.java |  54 +--
 .../graphics/core/AbstractGraphicsSystem.java |  34 --
 .../graphics/core/DrawingParameters.java      |  19 --
 .../library/graphics/core/GraphicsDevice.java |  40 ---
 .../library/graphics/core/GraphicsEngine.java |  63 ----
 .../graphics/core/GraphicsEngineImpl.java     | 316 ------------------
 .../library/graphics/core/GraphicsEvent.java  |  20 --
 .../library/graphics/core/GraphicsSystem.java |  27 --
 .../core/GraphicsSystemParameters.java        |  41 ---
 .../drawables/CoordinatesDrawableObject.java  |  44 ---
 .../core/drawables/DrawableObject.java        |  43 ---
 .../drawables/PolylineDrawableObject.java     |  36 --
 .../core/drawables/StringDrawableObject.java  |  41 ---
 .../library/graphics/core/geometry/Axis.java  |  43 ---
 .../graphics/core/geometry/AxisDirection.java |  22 --
 .../core/geometry/CoordinateSystem.java       |  81 -----
 .../graphics/core/geometry/Coordinates.java   |  28 --
 .../core/geometry/CoordinatesFactory.java     |  70 ----
 .../core/geometry/DoubleCoordinates.java      |  52 ---
 .../core/geometry/IntCoordinates.java         |  51 ---
 .../foreign/CallAndExternalFunctions.java     | 153 +--------
 .../builtin/base/foreign/LookupAdapter.java   |   5 -
 .../truffle/r/nodes/test/ExtBuiltinsList.java |   6 -
 .../truffle/r/runtime/FastROptions.java       |   1 -
 .../truffle/r/runtime/data/RPairList.java     |  11 +
 mx.fastr/copyrights/overrides                 |  27 +-
 47 files changed, 426 insertions(+), 2066 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
index 21a2208f16..e177c722b1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
@@ -23,15 +23,15 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
-public class DrawArrowsNode extends Node {
+class DrawArrowsNode extends Node {
     // Structure of an arrow description
-    public static final int ARROWANGLE = 0;
-    public static final int ARROWLENGTH = 1;
-    public static final int ARROWENDS = 2;
-    public static final int ARROWTYPE = 3;
+    private static final int ARROWANGLE = 0;
+    private static final int ARROWLENGTH = 1;
+    private static final int ARROWENDS = 2;
+    private static final int ARROWTYPE = 3;
     // known values of ARROWTYPE
-    public static final int ARROWTYPE_LINES = 1;
-    public static final int ARROWTYPE_POLYGON = 2;
+    private static final int ARROWTYPE_LINES = 1;
+    private static final int ARROWTYPE_POLYGON = 2;
 
     @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
new file mode 100644
index 0000000000..5863de72a4
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice;
+import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
+import com.oracle.truffle.r.runtime.RInternalCode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+/**
+ * Implements the lookup for externals replaced by the FastR grid package.
+ */
+public class FastRGridExternalLookup {
+
+    public static RExternalBuiltinNode lookupDotExternal(String name) {
+        switch (name) {
+            case "devholdflush":
+                return new IgnoredGridExternal(RNull.instance);
+            case "PDF":
+                return new IgnoredGridExternal(RNull.instance);
+            default:
+                return null;
+        }
+    }
+
+    public static RExternalBuiltinNode lookupDotExternal2(String name) {
+        switch (name) {
+            case "C_par":
+                return new CPar();
+            case "X11":
+                return new InitWindowedDevice();
+            default:
+                return null;
+        }
+    }
+
+    public static RExternalBuiltinNode lookupDotCall(String name) {
+        switch (name) {
+            case "L_gridDirty":
+                return new LGridDirty();
+            case "L_initGrid":
+                return LInitGrid.create();
+            case "L_newpage":
+                return new LNewPage();
+            case "L_convert":
+                return LConvert.create();
+
+            // Viewport management
+            case "L_upviewport":
+                return LUpViewPort.create();
+            case "L_initViewportStack":
+                return new LInitViewPortStack();
+            case "L_unsetviewport":
+                return LUnsetViewPort.create();
+            case "L_setviewport":
+            case "L_downviewport":
+                return getExternalFastRGridBuiltinNode(name);
+
+            // Drawing primitives
+            case "L_rect":
+                return LRect.create();
+            case "L_lines":
+                return LLines.create();
+            case "L_polygon":
+                return LPolygon.create();
+            case "L_text":
+                return LText.create();
+            case "L_textBounds":
+                return LTextBounds.create();
+            case "L_segments":
+                return LSegments.create();
+            case "L_circle":
+                return LCircle.create();
+            case "L_points":
+                return LPoints.create();
+
+            // Simple grid state access
+            case "L_getGPar":
+                return new GridStateGetNode(GridState::getGpar);
+            case "L_setGPar":
+                return GridStateSetNode.create((state, val) -> state.setGpar((RList) val));
+            case "L_getCurrentGrob":
+                return new GridStateGetNode(GridState::getCurrentGrob);
+            case "L_setCurrentGrob":
+                return GridStateSetNode.create(GridState::setCurrentGrob);
+            case "L_currentViewport":
+                return new GridStateGetNode(GridState::getViewPort);
+            case "L_initGPar":
+                return new LInitGPar();
+
+            // Display list stuff: not implemented atm
+            case "L_getDisplayList":
+                return new IgnoredGridExternal(RDataFactory.createList());
+            case "L_getDLindex":
+                return new IgnoredGridExternal(0);
+            case "L_getDLon":
+            case "L_getEngineDLon":
+                return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE);
+            case "L_initDisplayList":
+            case "L_newpagerecording":
+            case "L_setDisplayList":
+            case "L_setDLelt":
+            case "L_setDLindex":
+            case "L_setDLon":
+                return new IgnoredGridExternal(RNull.instance);
+
+            // These methods do not use graphics system or any global state. For now,
+            // we can re-use the native implementation, which in the future should be rewritten
+            // to managed code.
+            case "L_validUnits":
+                return null;
+            default:
+                if (name.startsWith("L_")) {
+                    throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
+                } else {
+                    return null;
+                }
+        }
+    }
+
+    private static RExternalBuiltinNode getExternalFastRGridBuiltinNode(String name) {
+        return new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
index 1da60efecf..9006431d60 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
@@ -29,14 +29,14 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 /**
  * Gets a specified attribute of current {@link GridState}.
  */
-public class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
+class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
     private final Function<GridState, Object> getter;
 
     static {
         Casts.noCasts(GridStateGetNode.class);
     }
 
-    public GridStateGetNode(Function<GridState, Object> getter) {
+    GridStateGetNode(Function<GridState, Object> getter) {
         this.getter = getter;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
index 067193cf08..9166dac774 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
@@ -29,14 +29,14 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
  * A node for externals that we ignore, becuase we do not need to implement them or because they
  * support functionallity we do not implement yet, especially record/replay.
  */
-public class IgnoredGridExternal extends RExternalBuiltinNode {
+class IgnoredGridExternal extends RExternalBuiltinNode {
     private final Object result;
 
     static {
         Casts.noCasts(IgnoredGridExternal.class);
     }
 
-    public IgnoredGridExternal(Object result) {
+    IgnoredGridExternal(Object result) {
         this.result = result;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index ec70939be0..b187d6bc7d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -19,7 +19,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-public class LGridDirty extends RExternalBuiltinNode {
+class LGridDirty extends RExternalBuiltinNode {
     @Child private InitViewPortNode initViewPort = new InitViewPortNode();
     private final ConditionProfile initViewPortProfile = ConditionProfile.createCountingProfile();
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
index 38388451db..5bca2d1b31 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-public class LInitGPar extends RExternalBuiltinNode {
+class LInitGPar extends RExternalBuiltinNode {
     static {
         Casts.noCasts(LInitGPar.class);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
index 83a82b0a47..8a28365fc7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -18,7 +18,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-public class LInitViewPortStack extends RExternalBuiltinNode {
+class LInitViewPortStack extends RExternalBuiltinNode {
     @Child private InitViewPortNode initViewPortNode = new InitViewPortNode();
     static {
         Casts.noCasts(LInitViewPortStack.class);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 727e10ed91..7e03f9b840 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -14,7 +14,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-public class LNewPage extends RExternalBuiltinNode.Arg0 {
+class LNewPage extends RExternalBuiltinNode.Arg0 {
     static {
         Casts.noCasts(LNewPage.class);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index ea216ae304..8821b8dd0f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -25,19 +25,27 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
 
 import java.awt.BasicStroke;
+import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.Graphics2D;
+import java.awt.HeadlessException;
 import java.awt.Paint;
 import java.awt.RenderingHints;
 import java.awt.Shape;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
 import java.util.function.Supplier;
 
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineType;
-import com.oracle.truffle.r.library.graphics.FastRFrame;
 import com.oracle.truffle.r.runtime.RInternalError;
 
 public class JFrameDevice implements GridDevice {
@@ -214,4 +222,41 @@ public class JFrameDevice implements GridDevice {
         twodashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize / 2f, dashSize}, 0f);
         longdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{2f * dashSize}, 0f);
     }
+
+    private static class FastRFrame extends JFrame {
+        private static final long serialVersionUID = 1L;
+        private final Dimension framePreferredSize = new Dimension(720, 720);
+        private final JPanel fastRComponent = new JPanel();
+
+        FastRFrame() throws HeadlessException {
+            super("FastR");
+            addCloseListener();
+            createUI();
+            center();
+        }
+
+        private void createUI() {
+            setLayout(new BorderLayout());
+            setSize(framePreferredSize);
+            add(fastRComponent, BorderLayout.CENTER);
+            fastRComponent.setPreferredSize(getSize());
+        }
+
+        private void addCloseListener() {
+            addWindowFocusListener(new WindowAdapter() {
+                @Override
+                public void windowClosing(WindowEvent e) {
+                    dispose();
+                }
+            });
+        }
+
+        private void center() {
+            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+            Dimension frameSize = getSize();
+            int x = (screenSize.width - frameSize.width) / 2;
+            int y = (screenSize.height - frameSize.height) / 2;
+            setLocation(x, y);
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
new file mode 100644
index 0000000000..4e9f77c712
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.GridState;
+import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+/**
+ * Node that handles the {@code C_X11} external calls. Those calls may be initiated from either the
+ * {@code X11} function or FastR specific {@code awt} function. In either case the result is that
+ * the AWT window is opened and ready for drawing.
+ */
+public final class InitWindowedDevice extends RExternalBuiltinNode {
+    static {
+        Casts.noCasts(InitWindowedDevice.class);
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        GridState gridState = GridContext.getContext().getGridState();
+        if (!gridState.isDeviceInitialized()) {
+            GridContext.getContext().getCurrentDevice().openNewPage();
+            gridState.setDeviceInitialized();
+        }
+        RGridGraphicsAdapter.setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo");
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
new file mode 100644
index 0000000000..16a15ce9b2
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
@@ -0,0 +1,30 @@
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+eval(expression({
+    # This should be preffered way of starting the FastR java device.
+    # For compatibility reasons, both X11 and awt end up calling C_X11.
+    # In the future, this function may support extra parameters like a
+    # reference to java 2D graphics object, which will be used for the drawing.
+    awt <- function(...) {
+        .External2(grDevices:::C_X11)
+    }
+}), asNamespace("grDevices"))
\ No newline at end of file
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java
new file mode 100644
index 0000000000..f8363aacb3
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/**
+ * Compatibility layer for grDevices packages.
+ *
+ * With FastR grid we use {@link com.oracle.truffle.r.library.fastrGrid.device.GridDevice} instead
+ * of the abstraction used by GnuR. This is compatibility layer that provides implementation of some
+ * of the externals that manipulate the device and forwards them to corresponding methods on FastR
+ * grid side.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
new file mode 100644
index 0000000000..4d4629bc7f
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
@@ -0,0 +1,73 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (C) 1998 Ross Ihaka
+ * Copyright (c) 1998--2014, The R Core Team
+ * Copyright (c) 2002--2010, The R Foundation
+ * Copyright (C) 2005--2006, Morten Welinder
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid.graphics;
+
+import com.oracle.truffle.r.library.fastrGrid.FastRGridExternalLookup;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.ROptions;
+import com.oracle.truffle.r.runtime.ROptions.OptionsException;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+
+/**
+ * Initialization of graphics package emulation for the purposes of FastR grid package
+ * implementation.
+ *
+ * FastR exposes two devices: the null device and 'awt' device, and adds function 'awt' to the
+ * grDevices package. The 'awt' function ends up calling 'C_X11' (the same as the 'X11' function
+ * from grDevices), we capture that call in {@link FastRGridExternalLookup} and replace it with our
+ * own logic. This way we also "implement" 'X11' device with java awt should anyone try to activate
+ * it.
+ *
+ * Moreover, we change the value of option "device" to our "awt" function so that when e.g. lattice
+ * tries to open the default device it uses 'awt'. If the future this should be either 'awt' for
+ * interactive sessions, or some image format device for batch sessions. We should also honor the
+ * R_INTERACTIVE_DEVICE and R_DEFAULT_DEVICE environment variables.
+ */
+public class RGridGraphicsAdapter {
+    private static final String NULL_DEVICE = "null device";
+    /**
+     * The graphics devices system maintains two variables .Device and .Devices in the base
+     * environment both are always set: .Devices gives a list of character vectors of the names of
+     * open devices, .Device is the element corresponding to the currently active device. The null
+     * device will always be open.
+     */
+    private static final String DOT_DEVICE = ".Device";
+    private static final String DOT_DEVICES = ".Devices";
+
+    public static void initialize() {
+        setCurrentDevice(NULL_DEVICE);
+        ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
+        try {
+            options.setValue("device", "awt");
+        } catch (OptionsException e) {
+            RError.warning(RError.NO_CALLER, Message.GENERIC, "FastR could not set the 'device' options to awt.");
+        }
+    }
+
+    public static void setCurrentDevice(String name) {
+        REnvironment baseEnv = REnvironment.baseEnv();
+        baseEnv.safePut(DOT_DEVICE, name);
+        Object devices = baseEnv.get(DOT_DEVICES);
+        if (devices instanceof RPairList) {
+            ((RPairList) devices).appendToEnd(RDataFactory.createPairList(name));
+        } else {
+            baseEnv.safePut(DOT_DEVICES, RDataFactory.createPairList(name));
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
deleted file mode 100644
index d7ba80d07c..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.grDevices;
-
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen;
-import com.oracle.truffle.r.library.grDevices.pdf.PdfGraphicsDevice;
-import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-public class DevicesCCalls {
-    public abstract static class C_DevOff extends RExternalBuiltinNode.Arg1 {
-        public static C_DevOff create() {
-            return C_DevOffNodeGen.create();
-        }
-
-        static {
-            Casts casts = new Casts(C_DevOff.class);
-            casts.arg(0).asIntegerVector().findFirst();
-        }
-
-        @Specialization
-        public Object doCall(int deviceIndex) {
-            GraphicsEngineImpl.getInstance().killGraphicsDeviceByIndex(deviceIndex);
-            return RNull.instance;
-        }
-    }
-
-    public static final class C_DevCur extends RExternalBuiltinNode.Arg0 {
-
-        @Override
-        @TruffleBoundary
-        public Object execute() {
-            return GraphicsEngineImpl.getInstance().getCurrentGraphicsDeviceIndex();
-        }
-    }
-
-    public static final class C_PDF extends RExternalBuiltinNode {
-
-        @Child private CastNode extractFontsNode = newCastBuilder().mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector().buildCastNode();
-        @Child private CastNode asStringNode = newCastBuilder().asStringVector().findFirst().buildCastNode();
-        @Child private CastNode asDoubleNode = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
-        @Child private CastNode asLogicalNode = newCastBuilder().asLogicalVector().findFirst().buildCastNode();
-        @Child private CastNode asIntNode = newCastBuilder().asIntegerVector().findFirst().buildCastNode();
-
-        static {
-            Casts.noCasts(C_PDF.class);
-        }
-
-        @SuppressWarnings("unused")
-        @Override
-        @TruffleBoundary
-        public Object call(RArgsValuesAndNames args) {
-            new PdfGraphicsDevice(extractParametersFrom(args));
-            // todo implement devices addition
-            return RNull.instance;
-        }
-
-        private PdfGraphicsDevice.Parameters extractParametersFrom(RArgsValuesAndNames args) {
-            PdfGraphicsDevice.Parameters result = new PdfGraphicsDevice.Parameters();
-            result.filePath = asString(args.getArgument(0));
-            result.paperSize = asString(args.getArgument(1));
-            result.fontFamily = asString(args.getArgument(2));
-            result.encoding = asString(args.getArgument(3));
-            result.bg = asString(args.getArgument(4));
-            result.fg = asString(args.getArgument(5));
-            result.width = asDouble(castVector(args.getArgument(6)));
-            result.height = asDouble(castVector(args.getArgument(7)));
-            result.pointSize = asDouble(castVector(args.getArgument(8)));
-            result.oneFile = asLogical(castVector(args.getArgument(9)));
-            result.pageCenter = asLogical(castVector(args.getArgument(10)));
-            result.title = asString(args.getArgument(11));
-            result.fonts = extractFontsFrom(args.getArgument(12));
-
-            result.majorVersion = asInt(castVector(args.getArgument(13)));
-            result.minorVersion = asInt(castVector(args.getArgument(14)));
-            result.colormodel = asString(args.getArgument(15));
-            result.useDingbats = asLogical(castVector(args.getArgument(16)));
-            result.useKerning = asLogical(castVector(args.getArgument(17)));
-            result.fillOddEven = asLogical(castVector(args.getArgument(18)));
-            result.compress = asLogical(castVector(args.getArgument(19)));
-            return result;
-        }
-
-        private String asString(Object value) {
-            return (String) asStringNode.execute(value);
-        }
-
-        private int asInt(Object value) {
-            return (Integer) asIntNode.execute(value);
-        }
-
-        private double asDouble(Object value) {
-            return (Double) asDoubleNode.execute(value);
-        }
-
-        private byte asLogical(Object value) {
-            return (Byte) asLogicalNode.execute(value);
-        }
-
-        private String[] extractFontsFrom(Object inputArgument) {
-            return ((RAbstractStringVector) extractFontsNode.execute(inputArgument)).materialize().getDataCopy();
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java
deleted file mode 100644
index 0ec439c902..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.grDevices;
-
-import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
-import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-
-public final class NullGraphicsDevice implements GraphicsDevice {
-    private static final NullGraphicsDevice instance = new NullGraphicsDevice();
-
-    public static NullGraphicsDevice getInstance() {
-        return instance;
-    }
-
-    @Override
-    public void deactivate() {
-        throw createExceptionForMethod("deactivate");
-    }
-
-    @Override
-    public void activate() {
-        throw createExceptionForMethod("activate");
-    }
-
-    @Override
-    public void close() {
-        throw createExceptionForMethod("close");
-    }
-
-    @Override
-    public DrawingParameters getDrawingParameters() {
-        throw createExceptionForMethod("getDrawingParameters");
-    }
-
-    @Override
-    public void setMode(Mode newMode) {
-        throw createExceptionForMethod("setMode");
-    }
-
-    @Override
-    public Mode getMode() {
-        throw createExceptionForMethod("getMode");
-    }
-
-    @Override
-    public void setClipRect(double x1, double y1, double x2, double y2) {
-        throw createExceptionForMethod("setClipRect");
-    }
-
-    @Override
-    public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
-        throw createExceptionForMethod("drawPolyline");
-    }
-
-    private static RuntimeException createExceptionForMethod(String methodName) {
-        return new IllegalStateException("Call to " + methodName + " of Null-device");
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java
deleted file mode 100644
index ca8976b790..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.grDevices.fastrgd;
-
-import static com.oracle.truffle.r.library.graphics.core.geometry.AxisDirection.EAST;
-import static com.oracle.truffle.r.library.graphics.core.geometry.AxisDirection.NORTH;
-
-import java.util.Arrays;
-import java.util.function.Function;
-
-import com.oracle.truffle.r.library.graphics.FastRFrame;
-import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
-import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
-import com.oracle.truffle.r.library.graphics.core.drawables.DrawableObject;
-import com.oracle.truffle.r.library.graphics.core.drawables.PolylineDrawableObject;
-import com.oracle.truffle.r.library.graphics.core.drawables.StringDrawableObject;
-import com.oracle.truffle.r.library.graphics.core.geometry.Axis;
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinatesFactory;
-import com.oracle.truffle.r.library.graphics.core.geometry.DoubleCoordinates;
-
-/**
- * Default interactive FastR graphics device.
- */
-public class FastRGraphicsDevice implements GraphicsDevice {
-    private static final double GNUR_DEFAULT_MAX_X = 1;
-    private static final Axis GNUR_DEFAULT_X_AXIS = new Axis(0, GNUR_DEFAULT_MAX_X, EAST);
-    private static final Axis GNUR_DEFAULT_Y_AXIS = new Axis(0, 1, NORTH);
-    private static final double MARGIN = GNUR_DEFAULT_MAX_X * 0.1; // the margin for each side of
-    // 10% of a screen
-    // compress resulting image to have a small margin on all sides
-    private static final double COMPRESS_RATION = 1. - MARGIN * 1.8;
-
-    private Mode mode = Mode.GRAPHICS_OFF;
-    private FastRFrame fastRFrame;
-    private CoordinateSystem currentCoordinateSystem = new CoordinateSystem(GNUR_DEFAULT_X_AXIS, GNUR_DEFAULT_Y_AXIS);
-
-    @Override
-    public void deactivate() {
-        // todo impl
-    }
-
-    @Override
-    public void activate() {
-        // todo impl
-    }
-
-    @Override
-    public void close() {
-        // todo impl
-    }
-
-    @Override
-    public DrawingParameters getDrawingParameters() {
-        return null;
-    }
-
-    @Override
-    public void setMode(Mode newMode) {
-        mode = newMode;
-    }
-
-    @Override
-    public Mode getMode() {
-        return mode;
-    }
-
-    @Override
-    public void setClipRect(double x1, double y1, double x2, double y2) {
-        // todo impl
-    }
-
-    @Override
-    public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
-        // todo continue from GEPolyline() of engine.c
-        Coordinates convertedCoords = CoordinatesFactory.withRatioAndShift(coordinates, COMPRESS_RATION, MARGIN);
-        addDrawableObject(new PolylineDrawableObject(currentCoordinateSystem, convertedCoords));
-        drawBounds();
-        drawXYLabelsFor(coordinates);
-    }
-
-    private void drawBounds() {
-        // x,y in range [0,1]
-        double[] boundsXYPairs = {0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0};
-        Coordinates bounds = CoordinatesFactory.createByXYPairs(boundsXYPairs);
-        Coordinates compressedBounds = CoordinatesFactory.withRatioAndShift(bounds, COMPRESS_RATION, MARGIN);
-        addDrawableObject(new PolylineDrawableObject(currentCoordinateSystem, compressedBounds));
-    }
-
-    private void drawXYLabelsFor(Coordinates coordinates) {
-        drawLabelsForCoordinates(coordinates.getXCoordinatesAsDoubles(), MARGIN, 0.01, // just small
-                        // shift
-                        d -> CoordinatesFactory.createWithSameY(d, 0));
-        drawLabelsForCoordinates(coordinates.getYCoordinatesAsDoubles(), 0, MARGIN, d -> CoordinatesFactory.createWithSameX(0, d));
-    }
-
-    private void drawLabelsForCoordinates(double[] coordinates, double xShift, double yShift, Function<double[], DoubleCoordinates> xYConverter) {
-        int length = coordinates.length;
-        double[] sortedCoords = new double[length];
-        // copy to avoid side-effects on a caller side
-        System.arraycopy(coordinates, 0, sortedCoords, 0, length);
-        Arrays.sort(sortedCoords);
-        String[] labels = composeLabelsFor(sortedCoords);
-        DoubleCoordinates xYCoords = xYConverter.apply(sortedCoords);
-        Coordinates shiftedCoords = CoordinatesFactory.withRatioAndShift(xYCoords, COMPRESS_RATION, xShift, yShift);
-        addDrawableObject(new StringDrawableObject(currentCoordinateSystem, shiftedCoords, labels));
-    }
-
-    private static String[] composeLabelsFor(double[] doubles) {
-        return Arrays.stream(doubles).mapToObj(String::valueOf).toArray(String[]::new);
-    }
-
-    private FastRFrame getFastRFrame() {
-        if (fastRFrame == null || !fastRFrame.isVisible()) {
-            fastRFrame = new FastRFrame();
-            fastRFrame.setVisible(true);
-        }
-        return fastRFrame;
-    }
-
-    private void addDrawableObject(DrawableObject drawableObject) {
-        getFastRFrame().getFastRComponent().addDrawableObject(drawableObject);
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java
deleted file mode 100644
index 9b7302823d..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.grDevices.pdf;
-
-import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
-import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-import com.oracle.truffle.r.runtime.RRuntime;
-
-public class PdfGraphicsDevice implements GraphicsDevice {
-    @SuppressWarnings("unused") private final Parameters deviceParameters;
-
-    public PdfGraphicsDevice(Parameters deviceParameters) {
-        this.deviceParameters = deviceParameters;
-    }
-
-    @Override
-    public void deactivate() {
-
-    }
-
-    @Override
-    public void activate() {
-
-    }
-
-    @Override
-    public void close() {
-
-    }
-
-    @Override
-    public DrawingParameters getDrawingParameters() {
-        return null;
-    }
-
-    @Override
-    public void setMode(Mode newMode) {
-
-    }
-
-    @Override
-    public Mode getMode() {
-        return null;
-    }
-
-    @Override
-    public void setClipRect(double x1, double y1, double x2, double y2) {
-
-    }
-
-    @Override
-    public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
-
-    }
-
-    public static class Parameters {
-        public String filePath;
-        public String paperSize = "special";
-        public String fontFamily = "Helvetica";
-        public String encoding = "default";
-        public String bg = "transparent";
-        public String fg = "black";
-        public double width = 7.;
-        public double height = 7.;
-        public double pointSize = 12.;
-        public byte oneFile = RRuntime.LOGICAL_TRUE;
-        public byte pageCenter = RRuntime.LOGICAL_TRUE;
-        public String title = "R Graphics Output";
-        public String[] fonts;
-        public int majorVersion = 1;
-        public int minorVersion = 4;
-        public String colormodel = "srgb";
-        public byte useDingbats = RRuntime.LOGICAL_TRUE;
-        public byte useKerning = RRuntime.LOGICAL_TRUE;
-        public byte fillOddEven = RRuntime.LOGICAL_FALSE;
-        public byte compress = RRuntime.LOGICAL_TRUE;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java
deleted file mode 100644
index 77d572f534..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics;
-
-import com.oracle.truffle.r.library.graphics.core.AbstractGraphicsSystem;
-
-/**
- * Denotes to the 'base' in GNUR terms graphics system.
- */
-public class BaseGraphicsSystem extends AbstractGraphicsSystem {
-    private final GraphicsEventsListener graphicsEventsListener = (graphicsEvent, graphicsDevice) -> {
-    };
-
-    @Override
-    public GraphicsEventsListener getGraphicsEventsListener() {
-        return graphicsEventsListener;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java
deleted file mode 100644
index 5f395fecd1..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics;
-
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.swing.JComponent;
-
-import com.oracle.truffle.r.library.graphics.core.drawables.DrawableObject;
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
-
-public class FastRComponent extends JComponent {
-
-    private static final long serialVersionUID = 1L;
-
-    private final List<DrawableObject> displayList = Collections.synchronizedList(new ArrayList<>());
-
-    private boolean shouldDraw;
-    private CoordinateSystem coordinateSystem;
-
-    /**
-     * Note! Called from ED thread.
-     */
-    @Override
-    public void doLayout() {
-        super.doLayout();
-        Dimension size = getSize();
-        coordinateSystem = new CoordinateSystem(0, size.getWidth(), 0, size.getHeight());
-        shouldDraw = true;
-        recalculateDisplayList();
-    }
-
-    private void recalculateDisplayList() {
-        synchronized (displayList) {
-            displayList.stream().forEach(drawableObject -> drawableObject.recalculateForDrawingIn(coordinateSystem));
-        }
-    }
-
-    /**
-     * Note! Called from ED thread.
-     */
-    @Override
-    protected void paintComponent(Graphics g) {
-        super.paintComponent(g);
-        Graphics2D g2 = (Graphics2D) g;
-        if (shouldDraw) {
-            drawDisplayListOn(g2);
-        }
-    }
-
-    private void drawDisplayListOn(Graphics2D g2) {
-        synchronized (displayList) {
-            displayList.stream().forEach(drawableObject -> drawableObject.drawOn(g2));
-        }
-    }
-
-    public void addDrawableObject(DrawableObject drawableObject) {
-        synchronized (displayList) {
-            displayList.add(drawableObject);
-        }
-        shouldDraw = true;
-        if (coordinateSystem != null) {
-            drawableObject.recalculateForDrawingIn(coordinateSystem);
-            repaint();
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java
deleted file mode 100644
index 7446c48d59..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRFrame.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.library.graphics;
-
-import java.awt.BorderLayout;
-import java.awt.Dimension;
-import java.awt.HeadlessException;
-import java.awt.Toolkit;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-
-import javax.swing.JFrame;
-
-public class FastRFrame extends JFrame {
-
-    private static final long serialVersionUID = 1L;
-
-    private final Dimension framePreferredSize = new Dimension(720, 720);
-    private final FastRComponent fastRComponent = new FastRComponent();
-
-    public FastRFrame() throws HeadlessException {
-        super("FastR");
-        addCloseListener();
-        createUI();
-        center();
-    }
-
-    private void createUI() {
-        setLayout(new BorderLayout());
-        setSize(framePreferredSize);
-        add(fastRComponent, BorderLayout.CENTER);
-        fastRComponent.setPreferredSize(getSize());
-    }
-
-    private void addCloseListener() {
-        addWindowFocusListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                dispose();
-            }
-        });
-    }
-
-    private void center() {
-        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
-        Dimension frameSize = getSize();
-        int x = (screenSize.width - frameSize.width) / 2;
-        int y = (screenSize.height - frameSize.height) / 2;
-        setLocation(x, y);
-    }
-
-    public FastRComponent getFastRComponent() {
-        return fastRComponent;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
deleted file mode 100644
index adee6f49ea..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics;
-
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.library.graphics.core.DrawingParameters;
-import com.oracle.truffle.r.library.graphics.core.GraphicsDevice;
-import com.oracle.truffle.r.library.graphics.core.GraphicsEngine;
-import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinatesFactory;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.RNull;
-
-public class GraphicsCCalls {
-    public static final class C_PlotXY extends RExternalBuiltinNode {
-
-        @Child private CastNode castXYNode = newCastBuilder().mustBe(doubleValue().and(size(2))).asDoubleVector().buildCastNode();
-
-        static {
-            Casts.noCasts(C_PlotXY.class);
-        }
-
-        @Override
-        @TruffleBoundary
-        public RNull call(RArgsValuesAndNames args) {
-            RDoubleVector xyVector = (RDoubleVector) castXYNode.execute(args.getArgument(0));
-            getGraphicsEngine().setCurrentGraphicsDeviceMode(GraphicsDevice.Mode.GRAPHICS_ON);
-            drawWithLines(xyVector);
-            return RNull.instance;
-        }
-
-        private static void drawWithLines(RDoubleVector xyVector) {
-            // todo implement coordinate systems units conversion like in GConvert (graphics.c)
-            setClipRect();
-            DrawingParameters adoptedParameters = adoptCurrentDeviceDrawingParameters();
-            Coordinates coordinates = CoordinatesFactory.createByXYVector(xyVector);
-            getGraphicsEngine().drawPolyline(coordinates, adoptedParameters);
-        }
-
-        private static DrawingParameters adoptCurrentDeviceDrawingParameters() {
-            // todo Now adoption as for today. Transcribe from gcontextFromGM() (graphics.c)
-            return getCurrentGraphicsDevice().getDrawingParameters();
-        }
-
-        private static void setClipRect() {
-            // todo Transcrive from Gclip() (graphics.c)
-            getGraphicsEngine().setCurrentGraphicsDeviceClipRect(0, 0, 0, 0);
-        }
-
-        private static GraphicsDevice getCurrentGraphicsDevice() {
-            return getGraphicsEngine().getCurrentGraphicsDevice();
-        }
-
-        private static GraphicsEngine getGraphicsEngine() {
-            return GraphicsEngineImpl.getInstance();
-        }
-    }
-
-    public static final class C_Par extends RExternalBuiltinNode {
-
-        static {
-            Casts.noCasts(C_Par.class);
-        }
-
-        @Override
-        @TruffleBoundary
-        public Object call(RArgsValuesAndNames args) {
-            // pch
-            return RDataFactory.createIntVectorFromScalar(1);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public static final class C_mtext extends RExternalBuiltinNode {
-        private Object text;
-        private double side = 3.;
-        private double line = 0.;
-        private boolean outer = true;
-        private double adj = RRuntime.DOUBLE_NA;
-        private double at = RRuntime.DOUBLE_NA;
-        private double padj = RRuntime.DOUBLE_NA;
-        private double cex = RRuntime.DOUBLE_NA;
-        private double col = RRuntime.DOUBLE_NA;
-        private double font = RRuntime.DOUBLE_NA;
-
-        @Child private CastNode firstDoubleCast = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
-
-        static {
-            Casts.noCasts(C_mtext.class);
-        }
-
-        @Override
-        @TruffleBoundary
-        public Object call(RArgsValuesAndNames args) {
-            extractArgumentsFrom(args);
-            return RNull.instance;
-        }
-
-        private void extractArgumentsFrom(RArgsValuesAndNames args) {
-            // text = args.getArgument(0); // postpone for now
-            side = extractFirstDoubleValueFrom(args.getArgument(1));
-            line = extractFirstDoubleValueFrom(args.getArgument(2));
-            // outer = extractFirstDoubleValueFrom(args.getArgument(3));
-            at = extractFirstDoubleValueFrom(args.getArgument(4));
-            adj = extractFirstDoubleValueFrom(args.getArgument(5));
-            padj = extractFirstDoubleValueFrom(args.getArgument(6));
-            cex = extractFirstDoubleValueFrom(args.getArgument(7));
-            // col = extractFirstDoubleValueFrom(args.getArgument(8));
-            font = extractFirstDoubleValueFrom(args.getArgument(9));
-        }
-
-        private double extractFirstDoubleValueFrom(Object arg) {
-            return (Double) firstDoubleCast.execute(arg);
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
index 11c4a71ce6..7e9d763981 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
@@ -16,50 +16,24 @@ package com.oracle.truffle.r.library.graphics;
 
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import com.oracle.truffle.r.library.graphics.core.GraphicsEngine;
-import com.oracle.truffle.r.library.graphics.core.GraphicsEngineImpl;
+import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
 import com.oracle.truffle.r.runtime.FastROptions;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RPairList;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
 
 /**
- * A placeholder to keep {@code REngine} limited to calling the {@link #initialize} method. Two
- * possible implementations are available:
- * <ul>
- * <li>Native graphics from GnuR</li>
- * <li>Internal (Java) graphics, very incomplete implementation</li>
- * </ul>
- * The default is native graphics, selected by a startup option. Graphics is not virtualized, so
- * multiple contexts all share the same underlying implementation which is initialized exactly once.
- *
+ * A placeholder to keep {@code REngine} limited to calling the {@link #initialize} method. The code
+ * in R has a hard-coded invocation to InitGraphics in it. This initialization either invokes it
+ * too, or it runs a Java version of it if the internal grid package implementation is to be used.
  */
 public class RGraphics {
-    private static final RStringVector NULL_DEVICE = RDataFactory.createStringVectorFromScalar("null device");
-    /**
-     * The graphics devices system maintains two variables .Device and .Devices in the base
-     * environment both are always set: .Devices gives a list of character vectors of the names of
-     * open devices, .Device is the element corresponding to the currently active device. The null
-     * device will always be open.
-     */
-    private static final String DOT_DEVICE = ".Device";
-    private static final String DOT_DEVICES = ".Devices";
     private static final AtomicBoolean initialized = new AtomicBoolean();
 
     public static void initialize() {
         if (initialized.compareAndSet(false, true)) {
-            if (FastROptions.UseInternalGraphics.getBooleanValue()) {
-                REnvironment baseEnv = REnvironment.baseEnv();
-                baseEnv.safePut(DOT_DEVICE, NULL_DEVICE);
-                RPairList devices = RDataFactory.createPairList(NULL_DEVICE);
-                baseEnv.safePut(DOT_DEVICES, devices);
-                registerBaseGraphicsSystem();
+            if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
+                RGridGraphicsAdapter.initialize();
             } else {
                 DLL.DLLInfo dllInfo = DLL.findLibrary("graphics");
                 DLL.SymbolHandle symbolHandle = DLL.findSymbol("InitGraphics", dllInfo);
@@ -68,18 +42,4 @@ public class RGraphics {
             }
         }
     }
-
-    private static void registerBaseGraphicsSystem() {
-        try {
-            getGraphicsEngine().registerGraphicsSystem(new BaseGraphicsSystem());
-        } catch (Exception e) {
-            e.printStackTrace();
-            ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
-            consoleHandler.println("Unable to register base graphics system");
-        }
-    }
-
-    private static GraphicsEngine getGraphicsEngine() {
-        return GraphicsEngineImpl.getInstance();
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java
deleted file mode 100644
index b401568ffa..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-public abstract class AbstractGraphicsSystem implements GraphicsSystem {
-    private final GraphicsSystemParameters graphicsSystemParameters = new GraphicsSystemParameters();
-    private int id;
-
-    protected GraphicsSystemParameters getGraphicsSystemParameters() {
-        return graphicsSystemParameters;
-    }
-
-    @Override
-    public void setId(int id) {
-        this.id = id;
-    }
-
-    @Override
-    public int getId() {
-        return id;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java
deleted file mode 100644
index 69a1d70752..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-// todo implement GEContext data structure (GraphicsEngine.h)
-public final class DrawingParameters {
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java
deleted file mode 100644
index 91e07584d7..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-
-public interface GraphicsDevice {
-    void deactivate();
-
-    void activate();
-
-    void close();
-
-    DrawingParameters getDrawingParameters();
-
-    void setMode(Mode newMode);
-
-    Mode getMode();
-
-    void setClipRect(double x1, double y1, double x2, double y2);
-
-    void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters);
-
-    enum Mode {
-        GRAPHICS_ON,    // allow graphics output
-        GRAPHICS_OFF    // disable graphics output
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java
deleted file mode 100644
index 57a70b07e2..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-
-public interface GraphicsEngine {
-    void registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception;
-
-    void unRegisterGraphicsSystem(GraphicsSystem graphicsSystem);
-
-    void registerGraphicsDevice(GraphicsDevice newGraphicsDevice) throws Exception;
-
-    void unRegisterGraphicsDevice(GraphicsDevice deviceToUnregister);
-
-    int getGraphicsDevicesAmount();
-
-    /**
-     * @return true if there is only Null graphics device registered
-     */
-    boolean noGraphicsDevices();
-
-    /**
-     * Tries to install one if there is no current device.
-     *
-     * @return current {@link GraphicsDevice}
-     */
-    GraphicsDevice getCurrentGraphicsDevice();
-
-    /**
-     * @return {@link com.oracle.truffle.r.library.grDevices.NullGraphicsDevice} if unable to find
-     *         other
-     */
-    GraphicsDevice getGraphicsDeviceNextTo(GraphicsDevice graphicsDevice);
-
-    /**
-     * @return {@link com.oracle.truffle.r.library.grDevices.NullGraphicsDevice} if unable to find
-     *         other
-     */
-    GraphicsDevice getGraphicsDevicePrevTo(GraphicsDevice graphicsDevice);
-
-    void setCurrentGraphicsDeviceMode(GraphicsDevice.Mode mode);
-
-    void setCurrentGraphicsDeviceClipRect(double x1, double y1, double x2, double y2);
-
-    void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters);
-
-    void killGraphicsDeviceByIndex(int graphicsDeviceIndex);
-
-    int getCurrentGraphicsDeviceIndex();
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java
deleted file mode 100644
index 5efaee6e67..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-import static com.oracle.truffle.r.library.graphics.core.GraphicsEvent.GE_FINAL_STATE;
-import static com.oracle.truffle.r.library.graphics.core.GraphicsEvent.GE_INIT_STATE;
-
-import com.oracle.truffle.r.library.grDevices.NullGraphicsDevice;
-import com.oracle.truffle.r.library.grDevices.fastrgd.FastRGraphicsDevice;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-import com.oracle.truffle.r.runtime.Utils;
-
-// todo implement 'active' devices array from devices.c
-public final class GraphicsEngineImpl implements GraphicsEngine {
-    // GNUR: GraphicsEngine.h (original value: 24)
-    private static final int MAX_GRAPHICS_SYSTEMS_AMOUNT = 48;
-    private static final int MAX_GRAPHICS_DEVICES_AMOUNT = 64;
-    private static final int NULL_GRAPHICS_DEVICE_INDEX = 0;
-    private static final int LAST_GRAPHICS_DEVICE_INDEX = MAX_GRAPHICS_DEVICES_AMOUNT - 1;
-    private static final int NOT_FOUND = -1;
-    private static final GraphicsEngine instance = new GraphicsEngineImpl();
-
-    /**
-     * According to GNUR devices.c: 0 - null device, 63 - empty.
-     */
-    private final GraphicsDevice[] graphicsDevices = new GraphicsDevice[MAX_GRAPHICS_DEVICES_AMOUNT];
-    private final GraphicsSystem[] graphicsSystems = new AbstractGraphicsSystem[MAX_GRAPHICS_SYSTEMS_AMOUNT];
-
-    private int graphicsSystemsAmount = 0;
-    private int devicesAmountWithoutNullDevice = 0;
-    private CurrentGraphicsDevice currentGraphicsDevice = new CurrentGraphicsDevice(NullGraphicsDevice.getInstance(), NULL_GRAPHICS_DEVICE_INDEX);
-
-    public static GraphicsEngine getInstance() {
-        return instance;
-    }
-
-    private GraphicsEngineImpl() {
-        initNullGraphicsDevice();
-    }
-
-    /**
-     * According to GNUR 0 index is for the Null graphics device.
-     */
-    private void initNullGraphicsDevice() {
-        graphicsDevices[NULL_GRAPHICS_DEVICE_INDEX] = NullGraphicsDevice.getInstance();
-    }
-
-    @Override
-    public void registerGraphicsSystem(GraphicsSystem newGraphicsSystem) throws Exception {
-        if (newGraphicsSystem == null) {
-            throw new NullPointerException("Graphics system to register is null");
-        }
-        int index = findElementIndexInArray(null, graphicsSystems); // find null in the
-        // graphicsSystems
-        if (NOT_FOUND == index) {
-            throw handleErrorAndMakeException("too many graphics systems registered");
-        }
-        newGraphicsSystem.setId(index);
-        graphicsSystems[index] = newGraphicsSystem;
-        callListenerForEachDevice(newGraphicsSystem.getGraphicsEventsListener(), GE_INIT_STATE);
-        graphicsSystemsAmount++;
-    }
-
-    private void callListenerForEachDevice(AbstractGraphicsSystem.GraphicsEventsListener listener, GraphicsEvent event) {
-        if (noGraphicsDevices()) {
-            return;
-        }
-        for (int i = NULL_GRAPHICS_DEVICE_INDEX + 1; i < LAST_GRAPHICS_DEVICE_INDEX; i++) {
-            GraphicsDevice graphicsDevice = graphicsDevices[i];
-            if (graphicsDevice != null) {
-                listener.onEvent(event, graphicsDevice);
-            }
-        }
-    }
-
-    // todo transcribe error(_(msg)) from errors.c
-    private static Exception handleErrorAndMakeException(String message) {
-        return new Exception(message);
-    }
-
-    // todo implement in GNUR way
-    private static void issueWarning(String warningMessage) {
-        Utils.warn(warningMessage);
-    }
-
-    @Override
-    public void unRegisterGraphicsSystem(GraphicsSystem graphicsSystem) {
-        int graphicsSystemId = graphicsSystem.getId();
-        checkGraphicsSystemIndex(graphicsSystemId);
-        if (graphicsSystemsAmount == 0) {
-            issueWarning("no graphics system to unregister");
-            return;
-        }
-        callListenerForEachDevice(graphicsSystem.getGraphicsEventsListener(), GE_FINAL_STATE);
-        graphicsSystems[graphicsSystemId] = null;
-        graphicsSystemsAmount--;
-    }
-
-    private void checkGraphicsSystemIndex(int graphicsSystemIndex) {
-        if (graphicsSystemIndex < 0 || graphicsSystemIndex >= graphicsSystems.length) {
-            throw new IllegalArgumentException("Wrong graphics system index: " + graphicsSystemIndex);
-        }
-    }
-
-    // todo implement '.Devices' list related logic from GEaddDevices (devices.c)
-    @Override
-    public void registerGraphicsDevice(GraphicsDevice newGraphicsDevice) throws Exception {
-        if (newGraphicsDevice == null) {
-            throw new NullPointerException("Graphics device to register is null");
-        }
-        if (!noGraphicsDevices()) {
-            getCurrentGraphicsDevice().deactivate();
-        }
-        int index = findElementIndexInArray(NULL_GRAPHICS_DEVICE_INDEX + 1, LAST_GRAPHICS_DEVICE_INDEX, null, graphicsDevices);
-        if (index == NOT_FOUND) {
-            throw handleErrorAndMakeException("too many open devices");
-        }
-        graphicsDevices[index] = newGraphicsDevice;
-        devicesAmountWithoutNullDevice++;
-        currentGraphicsDevice = new CurrentGraphicsDevice(newGraphicsDevice, index);
-        notifyEachGraphicsSystem(newGraphicsDevice, GE_INIT_STATE);
-        newGraphicsDevice.activate();
-    }
-
-    private void notifyEachGraphicsSystem(GraphicsDevice graphicsDevice, GraphicsEvent event) {
-        for (int i = 0; i < MAX_GRAPHICS_SYSTEMS_AMOUNT; i++) {
-            GraphicsSystem graphicsSystem = graphicsSystems[i];
-            if (graphicsSystem != null) {
-                graphicsSystem.getGraphicsEventsListener().onEvent(event, graphicsDevice);
-            }
-        }
-    }
-
-    @Override
-    public void unRegisterGraphicsDevice(GraphicsDevice deviceToUnregister) {
-        if (deviceToUnregister == null) {
-            throw new NullPointerException("Graphics device to unregister is null");
-        }
-        doUnregisterGraphicsDevice(deviceToUnregister);
-        GraphicsDevice nextGraphicsDevice = getGraphicsDeviceNextTo(deviceToUnregister);
-        int index = findElementIndexInArray(nextGraphicsDevice, graphicsDevices);
-        currentGraphicsDevice = new CurrentGraphicsDevice(nextGraphicsDevice, index);
-        nextGraphicsDevice.activate();
-        // todo Interesting that in GNUR a GraphicsSystem is not notified when a GraphicsDevice is
-        // killed
-    }
-
-    private void doUnregisterGraphicsDevice(GraphicsDevice deviceToUnregister) {
-        int index = findElementIndexInArray(deviceToUnregister, graphicsDevices);
-        if (index == NOT_FOUND) {
-            issueWarning("no graphics device to unregister");
-            return;
-        }
-        graphicsDevices[index] = null;
-        devicesAmountWithoutNullDevice--;
-        currentGraphicsDevice = new CurrentGraphicsDevice(getNullGraphicsDevice(), NULL_GRAPHICS_DEVICE_INDEX);
-        deviceToUnregister.close();
-    }
-
-    @Override
-    public int getGraphicsDevicesAmount() {
-        return devicesAmountWithoutNullDevice;
-    }
-
-    @Override
-    public boolean noGraphicsDevices() {
-        return devicesAmountWithoutNullDevice == 0;
-    }
-
-    @Override
-    public int getCurrentGraphicsDeviceIndex() {
-        return currentGraphicsDevice.graphicsDeviceIndex;
-    }
-
-    @Override
-    public GraphicsDevice getCurrentGraphicsDevice() {
-        if (isNullDeviceIsCurrent()) {
-            try {
-                // todo transcribe device installation from GNUR GEcurrentDevice (devices.c)
-                installCurrentGraphicsDevice();
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-        return currentGraphicsDevice.graphicsDevice;
-    }
-
-    private boolean isNullDeviceIsCurrent() {
-        return currentGraphicsDevice.graphicsDevice == getNullGraphicsDevice();
-    }
-
-    private void installCurrentGraphicsDevice() throws Exception {
-        registerGraphicsDevice(new FastRGraphicsDevice());
-    }
-
-    @Override
-    public GraphicsDevice getGraphicsDeviceNextTo(GraphicsDevice graphicsDevice) {
-        if (graphicsDevice == null) {
-            throw new NullPointerException("Graphics device is null");
-        }
-        int startIndex = findElementIndexInArray(graphicsDevice, graphicsDevices);
-        if (startIndex == NOT_FOUND) {
-            return getNullGraphicsDevice();
-        }
-        GraphicsDevice foundDevice = findNotNullGraphicsDevice(startIndex + 1, graphicsDevices.length, SearchDirection.FORWARD);
-        if (foundDevice == null) {
-            foundDevice = findNotNullGraphicsDevice(startIndex - 1, NULL_GRAPHICS_DEVICE_INDEX, SearchDirection.BACKWARD);
-        }
-        return foundDevice == null ? getNullGraphicsDevice() : foundDevice;
-    }
-
-    @Override
-    public void setCurrentGraphicsDeviceMode(GraphicsDevice.Mode newMode) {
-        GraphicsDevice currentDevice = getCurrentGraphicsDevice();
-        if (currentDevice.getMode() != newMode) {
-            currentDevice.setMode(newMode);
-        }
-    }
-
-    @Override
-    public GraphicsDevice getGraphicsDevicePrevTo(GraphicsDevice graphicsDevice) {
-        if (graphicsDevice == null) {
-            throw new NullPointerException("Graphics device is null");
-        }
-        int startIndex = findElementIndexInArray(graphicsDevice, graphicsDevices);
-        if (startIndex == NOT_FOUND) {
-            return getNullGraphicsDevice();
-        }
-        GraphicsDevice foundDevice = findNotNullGraphicsDevice(startIndex - 1, NULL_GRAPHICS_DEVICE_INDEX, SearchDirection.BACKWARD);
-        if (foundDevice == null) {
-            foundDevice = findNotNullGraphicsDevice(startIndex + 1, graphicsDevices.length, SearchDirection.FORWARD);
-        }
-        return foundDevice == null ? getNullGraphicsDevice() : foundDevice;
-    }
-
-    private static <T> int findElementIndexInArray(T element, T[] array) {
-        return findElementIndexInArray(0, array.length, element, array);
-    }
-
-    private static <T> int findElementIndexInArray(int startIndexInclusive, int endIndexNotInclusive, T element, T[] array) {
-        for (int i = startIndexInclusive; i < endIndexNotInclusive; i++) {
-            if (array[i] == element) {
-                return i;
-            }
-        }
-        return NOT_FOUND;
-    }
-
-    private GraphicsDevice findNotNullGraphicsDevice(int startIndexInclusive, int endIndexNotInclusive, SearchDirection direction) {
-        switch (direction) {
-            case FORWARD:
-                for (int i = startIndexInclusive; i < endIndexNotInclusive; i++) {
-                    GraphicsDevice graphicsDevice = graphicsDevices[i];
-                    if (graphicsDevice != null) {
-                        return graphicsDevice;
-                    }
-                }
-                break;
-            case BACKWARD:
-                for (int i = startIndexInclusive; i > endIndexNotInclusive; i--) {
-                    GraphicsDevice graphicsDevice = graphicsDevices[i];
-                    if (graphicsDevice != null) {
-                        return graphicsDevice;
-                    }
-                }
-        }
-        return getNullGraphicsDevice();
-    }
-
-    private GraphicsDevice getNullGraphicsDevice() {
-        return graphicsDevices[NULL_GRAPHICS_DEVICE_INDEX];
-    }
-
-    @Override
-    public void setCurrentGraphicsDeviceClipRect(double x1, double y1, double x2, double y2) {
-        // todo transcribe from GESetClip() (engine.c)
-        getCurrentGraphicsDevice().setClipRect(0, 0, 0, 0);
-    }
-
-    @Override
-    public void drawPolyline(Coordinates coordinates, DrawingParameters drawingParameters) {
-        getCurrentGraphicsDevice().drawPolyline(coordinates, drawingParameters);
-    }
-
-    @Override
-    public void killGraphicsDeviceByIndex(int graphicsDeviceIndex) {
-        // todo TBD
-    }
-
-    private final class CurrentGraphicsDevice {
-        private final GraphicsDevice graphicsDevice;
-        private final int graphicsDeviceIndex;
-
-        private CurrentGraphicsDevice(GraphicsDevice graphicsDevice, int graphicsDeviceIndex) {
-            this.graphicsDevice = graphicsDevice;
-            this.graphicsDeviceIndex = graphicsDeviceIndex;
-        }
-    }
-
-    private enum SearchDirection {
-        FORWARD,
-        BACKWARD
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java
deleted file mode 100644
index 5ff9cf1c50..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-public enum GraphicsEvent {
-    GE_INIT_STATE,
-    GE_FINAL_STATE
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java
deleted file mode 100644
index d0011a8c9a..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-public interface GraphicsSystem {
-    GraphicsEventsListener getGraphicsEventsListener();
-
-    void setId(int id);
-
-    int getId();
-
-    public interface GraphicsEventsListener {
-        void onEvent(GraphicsEvent graphicsEvent, GraphicsDevice graphicsDevice);
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java
deleted file mode 100644
index 4d3ead19ca..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core;
-
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.Map;
-
-class GraphicsSystemParameters {
-    private final Map<GraphicsDevice, HashMap<String, Object>> parametersByDevices = new IdentityHashMap<>();
-
-    void addParameterForDevice(GraphicsDevice graphicsDevice, String parameterName, Object parameterValue) {
-        HashMap<String, Object> parameters = parametersByDevices.get(graphicsDevice);
-        if (parameters == null) {
-            parameters = new HashMap<>();
-            parametersByDevices.put(graphicsDevice, parameters);
-        }
-        parameters.put(parameterName, parameterValue);
-    }
-
-    Object getParameterForDevice(GraphicsDevice graphicsDevice, int parameterName) {
-        HashMap<String, Object> parameters = parametersByDevices.get(graphicsDevice);
-        return parameters == null ? null : parameters.get(parameterName);
-    }
-
-    void removeAllParametersForDevice(GraphicsDevice graphicsDevice) {
-        parametersByDevices.remove(graphicsDevice);
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java
deleted file mode 100644
index 4f641d7a79..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.drawables;
-
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-import com.oracle.truffle.r.library.graphics.core.geometry.IntCoordinates;
-
-/**
- * Denotes an object which drawing depends only from {@link Coordinates}. And automates conversion
- * from <code>srcCoordinates</code> to <code>dstCoordinates</code>.
- */
-public abstract class CoordinatesDrawableObject extends DrawableObject {
-    private final Coordinates srcCoordinates;
-
-    private Coordinates dstCoordinates;
-
-    protected CoordinatesDrawableObject(CoordinateSystem coordinateSystem, Coordinates coordinates) {
-        super(coordinateSystem);
-        this.srcCoordinates = coordinates;
-    }
-
-    @Override
-    public void recalculateForDrawingIn(CoordinateSystem dstCoordinateSystem) {
-        Coordinates converted = dstCoordinateSystem.convertCoordinatesFrom(getSrcCoordinateSystem(), srcCoordinates);
-        dstCoordinates = new IntCoordinates(converted.getXCoordinatesAsInts(), converted.getYCoordinatesAsInts());
-    }
-
-    protected final Coordinates getDstCoordinates() {
-        return dstCoordinates;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java
deleted file mode 100644
index ec4b0d5824..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.drawables;
-
-import java.awt.Graphics2D;
-
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
-
-/**
- * Denotes an object defined in <code>srcCoordinateSystem</code> that can be drawn in
- * <code>dstCoordinateSystem</code> on {@link Graphics2D}.
- */
-public abstract class DrawableObject {
-    private final CoordinateSystem srcCoordinateSystem;
-
-    protected DrawableObject(CoordinateSystem srcCoordinateSystem) {
-        this.srcCoordinateSystem = srcCoordinateSystem;
-    }
-
-    public abstract void drawOn(Graphics2D g2);
-
-    /**
-     * Override to prepare coordinates given in <code>srcCoordinateSystem</code> to be drawn in
-     * <code>srcCoordinateSystem</code>.
-     */
-    public abstract void recalculateForDrawingIn(CoordinateSystem dstCoordinateSystem);
-
-    protected final CoordinateSystem getSrcCoordinateSystem() {
-        return srcCoordinateSystem;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java
deleted file mode 100644
index 2cf12e7f6a..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.drawables;
-
-import java.awt.Graphics2D;
-
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-
-/**
- * Able to draw a polyline on {@link Graphics2D}.
- */
-public class PolylineDrawableObject extends CoordinatesDrawableObject {
-    public PolylineDrawableObject(CoordinateSystem coordinateSystem, Coordinates coordinates) {
-        super(coordinateSystem, coordinates);
-    }
-
-    @Override
-    public void drawOn(Graphics2D g2) {
-        Coordinates coords = getDstCoordinates();
-        int[] xCoords = coords.getXCoordinatesAsInts();
-        g2.drawPolyline(xCoords, coords.getYCoordinatesAsInts(), xCoords.length);
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java
deleted file mode 100644
index ccf4e16876..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.drawables;
-
-import java.awt.Graphics2D;
-import java.util.stream.IntStream;
-
-import com.oracle.truffle.r.library.graphics.core.geometry.CoordinateSystem;
-import com.oracle.truffle.r.library.graphics.core.geometry.Coordinates;
-
-/**
- * Able to render a text on {@link Graphics2D}.
- */
-public class StringDrawableObject extends CoordinatesDrawableObject {
-    private final String[] strings;
-
-    public StringDrawableObject(CoordinateSystem coordinateSystem, Coordinates coordinates, String[] strings) {
-        super(coordinateSystem, coordinates);
-        this.strings = strings;
-    }
-
-    @Override
-    public void drawOn(Graphics2D g2) {
-        Coordinates dstCoordinates = getDstCoordinates();
-        int[] xCoords = dstCoordinates.getXCoordinatesAsInts();
-        int[] yCoords = dstCoordinates.getYCoordinatesAsInts();
-        IntStream.range(0, strings.length).forEach(i -> g2.drawString(strings[i], xCoords[i], yCoords[i]));
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java
deleted file mode 100644
index c9a33c65a8..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-public final class Axis {
-    private final double minValue;
-    private final double maxValue;
-    private final AxisDirection direction;
-
-    public Axis(double minValue, double maxValue, AxisDirection direction) {
-        this.minValue = minValue;
-        this.maxValue = maxValue;
-        this.direction = direction;
-    }
-
-    public double getMinValue() {
-        return minValue;
-    }
-
-    public double getMaxValue() {
-        return maxValue;
-    }
-
-    public AxisDirection getDirection() {
-        return direction;
-    }
-
-    public double getRange() {
-        return maxValue - minValue;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java
deleted file mode 100644
index 8099a58058..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-public enum AxisDirection {
-    NORTH,
-    SOUTH,
-    WEST,
-    EAST
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java
deleted file mode 100644
index 2c1fca3b81..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-import java.util.stream.DoubleStream;
-
-/**
- * Denotes X-Y coordinate system by specifying max and min values for X-Y axis. Able to convert
- * coordinates given in another {@link CoordinateSystem}
- */
-public final class CoordinateSystem {
-    private final Axis xAxis;
-    private final Axis yAxis;
-
-    /**
-     * Uses Java graphics default axis orientation: x increases to the right, y increases to the
-     * bottom.
-     */
-    public CoordinateSystem(double minX, double maxX, double minY, double maxY) {
-        this(minX, maxX, minY, maxY, AxisDirection.EAST, AxisDirection.SOUTH);
-    }
-
-    public CoordinateSystem(double minX, double maxX, double minY, double maxY, AxisDirection xDirection, AxisDirection yDirection) {
-        this(new Axis(minX, maxX, xDirection), new Axis(minY, maxY, yDirection));
-    }
-
-    public CoordinateSystem(Axis xAxis, Axis yAxis) {
-        this.xAxis = xAxis;
-        this.yAxis = yAxis;
-    }
-
-    /**
-     * Transforms <code> otherCoordinates </code> given in <code> otherCoordinateSystem</code> to
-     * this coordinate system. Also applies the affine transformation defined by ratio and shifts.
-     */
-    public Coordinates convertCoordinatesFrom(CoordinateSystem otherCoordinateSystem, Coordinates otherCoordinates, double ratio, double xAxisShift, double yAxisShift) {
-        double[] resultX = convertCoordinatesBetweenAxises(getXAxis(), otherCoordinateSystem.getXAxis(), otherCoordinates.getXCoordinatesAsDoubles(), ratio, xAxisShift);
-        double[] resultY = convertCoordinatesBetweenAxises(getYAxis(), otherCoordinateSystem.getYAxis(), otherCoordinates.getYCoordinatesAsDoubles(), ratio, yAxisShift);
-        return new DoubleCoordinates(resultX, resultY);
-    }
-
-    public Coordinates convertCoordinatesFrom(CoordinateSystem otherCoordinateSystem, Coordinates otherCoordinates) {
-        double noRatio = 1;
-        double noShift = 0;
-        return convertCoordinatesFrom(otherCoordinateSystem, otherCoordinates, noRatio, noShift, noShift);
-    }
-
-    private static double[] convertCoordinatesBetweenAxises(Axis toAxis, Axis fromAxis, double[] coords, double givenRatio, double givenShift) {
-        boolean sameDirection = toAxis.getDirection() == fromAxis.getDirection();
-        double ratio = toAxis.getRange() / fromAxis.getRange();
-        ratio = sameDirection ? ratio : -ratio;
-        ratio *= givenRatio; // adding given ratio
-        double shift = sameDirection ? 0 : toAxis.getMaxValue();
-        shift += givenShift * ratio; // adding given shift
-        return applyShiftAndRatio(coords, ratio, shift);
-    }
-
-    private static double[] applyShiftAndRatio(double[] coords, double ratio, double shift) {
-        return DoubleStream.of(coords).map(d -> d * ratio + shift).toArray();
-    }
-
-    private Axis getXAxis() {
-        return xAxis;
-    }
-
-    private Axis getYAxis() {
-        return yAxis;
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java
deleted file mode 100644
index 95396232f2..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-/**
- * Denotes X-Y coordinates. Instances must be immutable objects.
- */
-public interface Coordinates {
-    double[] getXCoordinatesAsDoubles();
-
-    double[] getYCoordinatesAsDoubles();
-
-    int[] getXCoordinatesAsInts();
-
-    int[] getYCoordinatesAsInts();
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java
deleted file mode 100644
index 33e81bb144..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-import java.util.Arrays;
-import java.util.stream.DoubleStream;
-import java.util.stream.IntStream;
-
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-
-public final class CoordinatesFactory {
-    private CoordinatesFactory() {
-    }
-
-    public static DoubleCoordinates createWithSameX(double x, double[] yCoords) {
-        double[] xCoords = createdFilledArray(x, yCoords.length);
-        return new DoubleCoordinates(xCoords, yCoords);
-    }
-
-    public static DoubleCoordinates createWithSameY(double[] xCoords, double y) {
-        double[] yCoords = createdFilledArray(y, xCoords.length);
-        return new DoubleCoordinates(xCoords, yCoords);
-    }
-
-    private static double[] createdFilledArray(double value, int size) {
-        double[] result = new double[size];
-        Arrays.fill(result, value);
-        return result;
-    }
-
-    public static DoubleCoordinates createByXYVector(RDoubleVector xyVector) {
-        int length = xyVector.getLength();
-        double[] xCoords = IntStream.range(0, length).filter(i -> i % 2 == 0).mapToDouble(xyVector::getDataAt).toArray();
-        double[] yCoords = IntStream.range(0, length).filter(i -> i % 2 != 0).mapToDouble(xyVector::getDataAt).toArray();
-        return new DoubleCoordinates(xCoords, yCoords);
-    }
-
-    public static DoubleCoordinates createByXYPairs(double[] xyPairs) {
-        int length = xyPairs.length;
-        double[] xCoords = IntStream.range(0, length).filter(i -> i % 2 == 0).mapToDouble(i -> xyPairs[i]).toArray();
-        double[] yCoords = IntStream.range(0, length).filter(i -> i % 2 != 0).mapToDouble(i -> xyPairs[i]).toArray();
-        return new DoubleCoordinates(xCoords, yCoords);
-    }
-
-    public static DoubleCoordinates withRatioAndShift(Coordinates coordinates, double ratio, double shift) {
-        return withRatioAndShift(coordinates, ratio, shift, shift);
-    }
-
-    public static DoubleCoordinates withRatioAndShift(Coordinates coordinates, double ratio, double xShift, double yShift) {
-        double[] convertedX = applyRatioAndShiftTo(coordinates.getXCoordinatesAsDoubles(), ratio, xShift);
-        double[] convertedY = applyRatioAndShiftTo(coordinates.getYCoordinatesAsDoubles(), ratio, yShift);
-        return new DoubleCoordinates(convertedX, convertedY);
-    }
-
-    private static double[] applyRatioAndShiftTo(double[] coordinates, double ratio, double shift) {
-        return DoubleStream.of(coordinates).map(d -> d * ratio + shift).toArray();
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java
deleted file mode 100644
index 90dcb51dd6..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-import java.util.stream.DoubleStream;
-
-public final class DoubleCoordinates implements Coordinates {
-
-    private final double[] xCoords;
-    private final double[] yCoords;
-
-    public DoubleCoordinates(double[] xCoords, double[] yCoords) {
-        this.xCoords = xCoords;
-        this.yCoords = yCoords;
-    }
-
-    @Override
-    public double[] getXCoordinatesAsDoubles() {
-        return xCoords;
-    }
-
-    @Override
-    public double[] getYCoordinatesAsDoubles() {
-        return yCoords;
-    }
-
-    @Override
-    public int[] getXCoordinatesAsInts() {
-        return toInt(getXCoordinatesAsDoubles());
-    }
-
-    @Override
-    public int[] getYCoordinatesAsInts() {
-        return toInt(getYCoordinatesAsDoubles());
-    }
-
-    private static int[] toInt(double[] doubleArray) {
-        return DoubleStream.of(doubleArray).mapToInt(d -> (int) d).toArray();
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java
deleted file mode 100644
index cd62ef35fe..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
- * Copyright (C) 1998 Ross Ihaka
- * Copyright (c) 1998--2014, The R Core Team
- * Copyright (c) 2002--2010, The R Foundation
- * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.graphics.core.geometry;
-
-import java.util.stream.IntStream;
-
-public final class IntCoordinates implements Coordinates {
-    private final int[] xCoords;
-    private final int[] yCoords;
-
-    public IntCoordinates(int[] xCoords, int[] yCoords) {
-        this.xCoords = xCoords;
-        this.yCoords = yCoords;
-    }
-
-    @Override
-    public double[] getXCoordinatesAsDoubles() {
-        return toDouble(xCoords);
-    }
-
-    @Override
-    public double[] getYCoordinatesAsDoubles() {
-        return toDouble(yCoords);
-    }
-
-    @Override
-    public int[] getXCoordinatesAsInts() {
-        return xCoords;
-    }
-
-    @Override
-    public int[] getYCoordinatesAsInts() {
-        return yCoords;
-    }
-
-    private static double[] toDouble(int[] intArray) {
-        return IntStream.of(intArray).mapToDouble(i -> i).toArray();
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index cbb9714312..b7bee9a581 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -22,31 +22,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.library.fastrGrid.GridState;
-import com.oracle.truffle.r.library.fastrGrid.GridStateGetNode;
-import com.oracle.truffle.r.library.fastrGrid.GridStateSetNode;
-import com.oracle.truffle.r.library.fastrGrid.IgnoredGridExternal;
-import com.oracle.truffle.r.library.fastrGrid.LCircle;
-import com.oracle.truffle.r.library.fastrGrid.LConvert;
-import com.oracle.truffle.r.library.fastrGrid.LGridDirty;
-import com.oracle.truffle.r.library.fastrGrid.LInitGPar;
-import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
-import com.oracle.truffle.r.library.fastrGrid.LInitViewPortStack;
-import com.oracle.truffle.r.library.fastrGrid.LLines;
-import com.oracle.truffle.r.library.fastrGrid.LNewPage;
-import com.oracle.truffle.r.library.fastrGrid.LPoints;
-import com.oracle.truffle.r.library.fastrGrid.LPolygon;
-import com.oracle.truffle.r.library.fastrGrid.LRect;
-import com.oracle.truffle.r.library.fastrGrid.LSegments;
-import com.oracle.truffle.r.library.fastrGrid.LText;
-import com.oracle.truffle.r.library.fastrGrid.LTextBounds;
-import com.oracle.truffle.r.library.fastrGrid.LUnsetViewPort;
-import com.oracle.truffle.r.library.fastrGrid.LUpViewPort;
-import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
-import com.oracle.truffle.r.library.graphics.GraphicsCCalls;
-import com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_PlotXY;
-import com.oracle.truffle.r.library.grid.GridFunctionsFactory.InitGridNodeGen;
-import com.oracle.truffle.r.library.grid.GridFunctionsFactory.ValidUnitsNodeGen;
+import com.oracle.truffle.r.library.fastrGrid.FastRGridExternalLookup;
 import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_M_setPrimitiveMethodsNodeGen;
 import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_externalPtrPrototypeObjectNodeGen;
 import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.R_getClassFromCacheNodeGen;
@@ -99,7 +75,6 @@ import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalCode;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -262,7 +237,7 @@ public class CallAndExternalFunctions {
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
             String name = lookupName(symbol);
             if (FastROptions.UseInternalGridGraphics.getBooleanValue() && name != null) {
-                RExternalBuiltinNode gridExternal = lookupFastRGridBuiltin(name);
+                RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotCall(name);
                 if (gridExternal != null) {
                     return gridExternal;
                 }
@@ -656,113 +631,11 @@ public class CallAndExternalFunctions {
                 // parallel
                 case "mc_is_child":
                     return MCIsChildNodeGen.create();
-                default:
-                    return FastROptions.UseInternalGraphics.getBooleanValue() ? lookupGraphicsBuiltin(name) : null;
-            }
-        }
-
-        private static RExternalBuiltinNode lookupGraphicsBuiltin(String name) {
-            switch (name) {
-                // grDevices
-                case "cairoProps":
-                    return CairoPropsNodeGen.create();
-                case "makeQuartzDefault":
-                    return new MakeQuartzDefault();
-
-                // grid
-                case "L_initGrid":
-                    return InitGridNodeGen.create();
-                case "L_validUnits":
-                    return ValidUnitsNodeGen.create();
                 default:
                     return null;
             }
         }
 
-        private RExternalBuiltinNode lookupFastRGridBuiltin(String name) {
-            switch (name) {
-                case "L_gridDirty":
-                    return new LGridDirty();
-                case "L_initGrid":
-                    return LInitGrid.create();
-                case "L_newpage":
-                    return new LNewPage();
-                case "L_convert":
-                    return LConvert.create();
-
-                // Viewport management
-                case "L_upviewport":
-                    return LUpViewPort.create();
-                case "L_initViewportStack":
-                    return new LInitViewPortStack();
-                case "L_unsetviewport":
-                    return LUnsetViewPort.create();
-                case "L_setviewport":
-                case "L_downviewport":
-                    return getExternalFastRGridBuiltinNode(name);
-
-                // Drawing primitives
-                case "L_rect":
-                    return LRect.create();
-                case "L_lines":
-                    return LLines.create();
-                case "L_polygon":
-                    return LPolygon.create();
-                case "L_text":
-                    return LText.create();
-                case "L_textBounds":
-                    return LTextBounds.create();
-                case "L_segments":
-                    return LSegments.create();
-                case "L_circle":
-                    return LCircle.create();
-                case "L_points":
-                    return LPoints.create();
-
-                // Simple grid state access
-                case "L_getGPar":
-                    return new GridStateGetNode(GridState::getGpar);
-                case "L_setGPar":
-                    return GridStateSetNode.create((state, val) -> state.setGpar((RList) val));
-                case "L_getCurrentGrob":
-                    return new GridStateGetNode(GridState::getCurrentGrob);
-                case "L_setCurrentGrob":
-                    return GridStateSetNode.create(GridState::setCurrentGrob);
-                case "L_currentViewport":
-                    return new GridStateGetNode(GridState::getViewPort);
-                case "L_initGPar":
-                    return new LInitGPar();
-
-                // Display list stuff: not implemented atm
-                case "L_getDisplayList":
-                    return new IgnoredGridExternal(RDataFactory.createList());
-                case "L_getDLindex":
-                    return new IgnoredGridExternal(0);
-                case "L_getDLon":
-                case "L_getEngineDLon":
-                    return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE);
-                case "L_initDisplayList":
-                case "L_newpagerecording":
-                case "L_setDisplayList":
-                case "L_setDLelt":
-                case "L_setDLindex":
-                case "L_setDLon":
-                    return new IgnoredGridExternal(RNull.instance);
-
-                // These methods do not use graphics system or any global state. For now,
-                // we can re-use the native implementation, which in the future should be rewritten
-                // to managed code.
-                case "L_validUnits":
-                    return null;
-                default:
-                    if (name.startsWith("L_")) {
-                        throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
-                    } else {
-                        return null;
-                    }
-            }
-        }
-
         /**
          * {@code .NAME = NativeSymbolInfo} implemented as a builtin.
          */
@@ -850,9 +723,9 @@ public class CallAndExternalFunctions {
         protected RExternalBuiltinNode lookupBuiltin(RList f) {
             String name = lookupName(f);
             if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
-                switch (name) {
-                    case "devholdflush":
-                        return new IgnoredGridExternal(RNull.instance);
+                RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotExternal(name);
+                if (gridExternal != null) {
+                    return gridExternal;
                 }
             }
             switch (name) {
@@ -966,13 +839,13 @@ public class CallAndExternalFunctions {
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
+            String name = lookupName(symbol);
             if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
-                switch (lookupName(symbol)) {
-                    case "C_par":
-                        return new CPar();
+                RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotExternal2(name);
+                if (gridExternal != null) {
+                    return gridExternal;
                 }
             }
-            String name = lookupName(symbol);
             switch (name) {
                 // tools
                 case "writetable":
@@ -1041,14 +914,6 @@ public class CallAndExternalFunctions {
         @Override
         @TruffleBoundary
         protected RExternalBuiltinNode lookupBuiltin(RList f) {
-            if (FastROptions.UseInternalGraphics.getBooleanValue()) {
-                switch (lookupName(f)) {
-                    case "C_mtext":
-                        return new GraphicsCCalls.C_mtext();
-                    case "C_plotXY":
-                        return new C_PlotXY();
-                }
-            }
             return null;
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index 84c0278f50..31f230f522 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.library.fastrGrid.LInitGrid;
 import com.oracle.truffle.r.library.stats.RandFunctionsNodes;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -178,10 +177,6 @@ abstract class LookupAdapter extends RBuiltinNode {
         return new RInternalCodeBuiltinNode(RContext.getInstance(), "stats", RInternalCode.loadSourceRelativeTo(RandFunctionsNodes.class, "model.R"), name);
     }
 
-    protected static RExternalBuiltinNode getExternalFastRGridBuiltinNode(String name) {
-        return new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"), name);
-    }
-
     protected static final int CallNST = DLL.NativeSymbolType.Call.ordinal();
     protected static final int ExternalNST = DLL.NativeSymbolType.External.ordinal();
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
index 98eb067b7a..1035f57473 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
@@ -58,12 +58,6 @@ public class ExtBuiltinsList {
                     com.oracle.truffle.r.library.tools.Rmd5NodeGen.class,
                     com.oracle.truffle.r.library.tools.DirChmodNodeGen.class,
                     com.oracle.truffle.r.library.tools.C_ParseRdNodeGen.class,
-                    com.oracle.truffle.r.library.grDevices.DevicesCCallsFactory.C_DevOffNodeGen.class,
-                    com.oracle.truffle.r.library.grDevices.DevicesCCalls.C_DevCur.class,
-                    com.oracle.truffle.r.library.grDevices.DevicesCCalls.C_PDF.class,
-                    com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_PlotXY.class,
-                    com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_Par.class,
-                    com.oracle.truffle.r.library.graphics.GraphicsCCalls.C_mtext.class,
                     com.oracle.truffle.r.library.stats.WilcoxFreeNode.class,
                     com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function3_2NodeGen.class,
                     com.oracle.truffle.r.library.stats.StatsFunctionsNodesFactory.Function4_1NodeGen.class,
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 157526ea1d..24f998565a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -51,7 +51,6 @@ public enum FastROptions {
     FullPrecisionSum("Use 128 bit arithmetic in sum builtin", false),
     InvisibleArgs("Argument writes do not trigger state transitions", true),
     RefCountIncrementOnly("Disable reference count decrements for experimental state transition implementation", false),
-    UseInternalGraphics("Whether the internal (Java) graphics subsystem should be used", false),
     UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", false),
     UseSpecials("Whether the fast-path special call nodes should be created for simple enough arguments.", true),
     ForceSources("Generate source sections for unserialized code", false),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index c999db5a78..32d4e88818 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -211,6 +211,17 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         return type;
     }
 
+    /**
+     * Appends given value as the last element of the pairlist.
+     */
+    public void appendToEnd(RPairList value) {
+        RPairList last = null;
+        for (RPairList item : this) {
+            last = item;
+        }
+        last.setCdr(value);
+    }
+
     @Override
     public boolean isComplete() {
         // TODO: is it important to get more precise information here?
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 8dc2bf1018..d3c6075238 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -1,30 +1,5 @@
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/BaseGraphicsSystem.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/AbstractGraphicsSystem.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/CoordinatesDrawableObject.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/DrawableObject.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/PolylineDrawableObject.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/drawables/StringDrawableObject.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/DrawingParameters.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Axis.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/AxisDirection.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/Coordinates.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinatesFactory.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/CoordinateSystem.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/DoubleCoordinates.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/geometry/IntCoordinates.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsDevice.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngine.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEngineImpl.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsEvent.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystem.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/core/GraphicsSystemParameters.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/FastRComponent.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/GraphicsCCalls.java,gnu_r_graphics.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/DevicesCCalls.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/fastrgd/FastRGraphicsDevice.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/NullGraphicsDevice.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grDevices/pdf/PdfGraphicsDevice.java,gnu_r_graphics.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java,gnu_r_graphics.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java,gnu_r.copyright
-- 
GitLab


From f8db27acee7999e794a07f033a1c06bd413afe38 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 22 Mar 2017 16:41:33 +0100
Subject: [PATCH 166/402] FastR Grid: add TruffleBoundary annotations

---
 .../com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java  | 3 +++
 .../com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java  | 2 ++
 .../com/oracle/truffle/r/library/fastrGrid/GridTextNode.java   | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LCircle.java    | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LConvert.java   | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java | 1 +
 .../src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java  | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java  | 2 ++
 .../oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java | 1 +
 .../src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java   | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LPoints.java    | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LRect.java      | 2 ++
 .../src/com/oracle/truffle/r/library/fastrGrid/LSegments.java  | 2 ++
 .../com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java | 2 ++
 .../r/library/fastrGrid/grDevices/InitWindowedDevice.java      | 2 ++
 15 files changed, 29 insertions(+)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index f15ca369fd..591c4e25f4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -24,6 +24,7 @@ import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation
 import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
@@ -52,6 +53,7 @@ class DoSetViewPort extends RBaseNode {
     @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
     @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
 
+    @TruffleBoundary
     public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
         GridState gridState = GridContext.getContext().getGridState();
         Object[] pushedVPData = pushedViewPort.getDataWithoutCopying();
@@ -88,6 +90,7 @@ class DoSetViewPort extends RBaseNode {
      * @param deviceDrawingContext This method needs to know the device default drawing context in
      *            order to convert units for the top level view port
      */
+    @TruffleBoundary
     public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
         double[][] parentTransform;
         ViewPortContext parentContext;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 11946cb521..2cceaeb82a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
@@ -44,6 +45,7 @@ public abstract class GridLinesNode extends Node {
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
     @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
 
+    @TruffleBoundary
     void execute(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 2c6dc5a516..b9d862b0fb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -31,6 +31,7 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
@@ -82,6 +83,7 @@ public final class GridTextNode extends RBaseNode {
         return new GridTextNode(false);
     }
 
+    @TruffleBoundary
     public Object gridText(RAbstractStringVector textVec, RAbstractVector x, RAbstractVector y, RAbstractDoubleVector hjustVec, RAbstractDoubleVector vjustVec, RAbstractDoubleVector rotationVec,
                     boolean checkOverlapIn, double theta) {
         if (textVec.getLength() == 0) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 4fc29b79f7..4d0183bf8f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
@@ -41,6 +42,7 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
     }
 
     @Specialization
+    @TruffleBoundary
     Object doCircle(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector radiusVec) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 96792070cc..b2300de6ab 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -18,6 +18,7 @@ import static com.oracle.truffle.r.library.fastrGrid.Unit.isListUnit;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
@@ -49,6 +50,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
+    @TruffleBoundary
     Object doConvert(RAbstractVector units, RAbstractIntVector axisFromVec, RAbstractIntVector axisToVec, RAbstractIntVector unitToVec) {
 
         GridContext ctx = GridContext.getContext();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index b187d6bc7d..b385a6091e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -37,6 +37,7 @@ class LGridDirty extends RExternalBuiltinNode {
         }
         if (initViewPortProfile.profile(gridState.getViewPort() == null)) {
             // this rarely happens, but we do not have a slow-path implementation (yet)
+            CompilerDirectives.transferToInterpreter();
             gridState.setViewPort(initViewPort.execute(frame));
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
index 5bca2d1b31..152aac26cd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -32,6 +33,7 @@ class LInitGPar extends RExternalBuiltinNode {
     }
 
     @Override
+    @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
         GridContext.getContext().getGridState().initGPar(GridContext.getContext().getCurrentDevice());
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
index 58903fc8be..885ace9762 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -27,6 +28,7 @@ public abstract class LInitGrid extends RExternalBuiltinNode.Arg1 {
     }
 
     @Specialization
+    @TruffleBoundary
     public Object doEnv(REnvironment gridEnv) {
         GridContext context = GridContext.getContext();
         context.getGridState().init(gridEnv, context.getCurrentDevice());
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
index 8a28365fc7..82c23f06ae 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 7e03f9b840..19c7bc6bf6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -20,6 +21,7 @@ class LNewPage extends RExternalBuiltinNode.Arg0 {
     }
 
     @Override
+    @TruffleBoundary
     public Object execute() {
         GridContext.getContext().getCurrentDevice().openNewPage();
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 0c457f1bed..fb8977b780 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -14,6 +14,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
@@ -57,6 +58,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
+    @TruffleBoundary
     public Object doPoints(RAbstractVector xVec, RAbstractVector yVec, RAbstractIntVector pchVec, RAbstractVector sizeVec) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index 062d23c46d..a666b07ede 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -15,6 +15,7 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
@@ -46,6 +47,7 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
     }
 
     @Specialization
+    @TruffleBoundary
     public Object execute(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector wVec, RAbstractVector hVec, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 6ec185aef1..1a3dda410e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
@@ -52,6 +53,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     }
 
     @Specialization
+    @TruffleBoundary
     Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RList arrow) {
         GridContext ctx = GridContext.getContext();
         GridDevice dev = ctx.getCurrentDevice();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
index 153358e5ef..0416b1f674 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -15,6 +15,7 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
@@ -39,6 +40,7 @@ public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
     }
 
     @Specialization
+    @TruffleBoundary
     Object unsetViewPort(int n) {
         GridContext ctx = GridContext.getContext();
         GridState gridState = ctx.getGridState();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 4e9f77c712..d6314346b2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
 import com.oracle.truffle.r.library.fastrGrid.GridState;
 import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
@@ -40,6 +41,7 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
     }
 
     @Override
+    @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
         GridState gridState = GridContext.getContext().getGridState();
         if (!gridState.isDeviceInitialized()) {
-- 
GitLab


From 8dfc4d19c04b162a242c1c7aef78a884b854ce98 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 11:25:33 +0100
Subject: [PATCH 167/402] FastR Grid: small code clean-up in unit conversions

---
 .../r/library/fastrGrid/GridUtils.java        | 13 ++++
 .../truffle/r/library/fastrGrid/Unit.java     | 69 +++++++++----------
 2 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index c7680a918f..b57eaaa994 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -50,6 +50,10 @@ final class GridUtils {
         return vec.getDataAt(idx % vec.getLength());
     }
 
+    static int getDataAtMod(RAbstractIntVector vec, int idx) {
+        return vec.getDataAt(idx % vec.getLength());
+    }
+
     @ExplodeLoop
     static int maxLength(UnitLengthNode unitLength, RAbstractVector... units) {
         int result = 0;
@@ -107,6 +111,15 @@ final class GridUtils {
         return (RList) value;
     }
 
+    static double getDoubleAt(RAbstractVector vector, int index) {
+        if (vector instanceof RAbstractDoubleVector) {
+            return ((RAbstractDoubleVector) vector).getDataAt(index);
+        } else if (vector instanceof RAbstractIntVector) {
+            return ((RAbstractIntVector) vector).getDataAt(index);
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non double/integer value");
+    }
+
     static double asDouble(Object val) {
         if (val instanceof Double) {
             return (double) val;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index fb8112cb3e..4cb343dfbf 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -13,16 +13,17 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDoubleVector;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asList;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asListOrNull;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmax;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.fmin;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDoubleAt;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.hasRClass;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.sum;
 import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
 import java.util.function.BiFunction;
 
@@ -35,9 +36,7 @@ import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -51,7 +50,6 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -116,6 +114,13 @@ public class Unit {
     private static final int L_minimising = 6;
     private static final int L_multiplying = 7;
 
+    // attributes in the unit object and unit classes
+    private static final String UNIT_ATTR_DATA = "data";
+    private static final String UNIT_ATTR_UNIT_ID = "valid.unit";
+    private static final String UNIT_CLASS = "unit";
+    private static final String UNIT_ARITHMETIC_CLASS = "unit.arithmetic";
+    private static final String UNIT_LIST_CLASS = "unit.list";
+
     private static final double CM_IN_INCH = 2.54;
 
     public static double inchesToCm(double inches) {
@@ -129,9 +134,9 @@ public class Unit {
     public static RAbstractDoubleVector newUnit(double value, int unitId) {
         assert unitId > 0 && unitId <= LAST_NORMAL_UNIT;
         RDoubleVector result = RDataFactory.createDoubleVector(new double[]{value}, RDataFactory.COMPLETE_VECTOR);
-        result.setClassAttr(RDataFactory.createStringVectorFromScalar("unit"));
-        result.setAttr("valid.unit", unitId);
-        result.setAttr("data", RNull.instance);
+        result.setClassAttr(RDataFactory.createStringVectorFromScalar(UNIT_CLASS));
+        result.setAttr(UNIT_ATTR_UNIT_ID, unitId);
+        result.setAttr(UNIT_ATTR_DATA, RNull.instance);
         return result;
     }
 
@@ -233,11 +238,11 @@ public class Unit {
     }
 
     static boolean isListUnit(Object unit) {
-        return unit instanceof RList && hasRClass((RAttributable) unit, "unit.list");
+        return unit instanceof RList && hasRClass((RAttributable) unit, UNIT_LIST_CLASS);
     }
 
     static boolean isArithmeticUnit(Object unit) {
-        return unit instanceof RList && hasRClass((RAttributable) unit, "unit.arithmetic");
+        return unit instanceof RList && hasRClass((RAttributable) unit, UNIT_ARITHMETIC_CLASS);
     }
 
     private static boolean isGrobUnit(int unitId) {
@@ -321,8 +326,8 @@ public class Unit {
     }
 
     abstract static class UnitNodeBase extends RBaseNode {
-        @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode("unit.arithmetic");
-        @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode("unit.list");
+        @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode(UNIT_ARITHMETIC_CLASS);
+        @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode(UNIT_LIST_CLASS);
 
         boolean isSimple(Object obj) {
             return !inheritsArithmeticCheckNode.execute(obj) && !inheritsUnitListCheckNode.execute(obj);
@@ -337,19 +342,6 @@ public class Unit {
         }
     }
 
-    public static final class UnitUnitIdNode extends Node {
-        @Child private GetFixedAttributeNode getValidUnitsAttr = GetFixedAttributeNode.create(VALID_UNIT_ATTR);
-
-        public int execute(RAbstractContainer unit, int index) {
-            RAbstractIntVector validUnits = asIntVector(getValidUnitsAttr.execute(unit));
-            return validUnits.getDataAt(index % validUnits.getLength());
-        }
-
-        public static UnitUnitIdNode create() {
-            return new UnitUnitIdNode();
-        }
-    }
-
     public static final class IsRelativeUnitNode extends UnitNodeBase {
         @Child private RGridCodeCall isPureNullCall = new RGridCodeCall("isPureNullUnit");
 
@@ -467,7 +459,7 @@ public class Unit {
      * interpreted as cyclic.
      */
     public abstract static class UnitToInchesNode extends UnitNodeBase {
-        @Child GrobUnitToInches grobUnitToInches = new GrobUnitToInches();
+        @Child GrobUnitToInches grobUnitToInches;
 
         public static UnitToInchesNode create() {
             return UnitToInchesNodeGen.create();
@@ -496,17 +488,14 @@ public class Unit {
         public abstract double execute(RAbstractContainer vector, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim);
 
         @Specialization(guards = "isSimple(value)")
-        double doNormal(RAbstractContainer value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
-                        @Cached("createAsDoubleCast()") CastNode asDoubleCast,
-                        @Cached("create()") UnitUnitIdNode unitUnitId) {
-            int unitId = unitUnitId.execute(value, index);
-            RAbstractDoubleVector vector = (RAbstractDoubleVector) asDoubleCast.execute(value);
-            double scalarValue = vector.getDataAt(index % vector.getLength());
+        double doNormal(RAbstractVector value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+            int unitId = getDataAtMod(asIntVector(value.getAttr(UNIT_ATTR_UNIT_ID)), index);
+            double scalarValue = getDoubleAt(value, index % value.getLength());
             if (isGrobUnit(unitId)) {
-                RList grobList = asList(vector.getAttr("data"));
-                return grobUnitToInches.execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
+                RList grobList = asList(value.getAttr(UNIT_ATTR_DATA));
+                return getGrobUnitToInchesNode().execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
             }
-            return convertToInches(scalarValue, unitId, asListOrNull(vector.getAttr("data")), ctx, axisOrDim);
+            return convertToInches(scalarValue, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
         }
 
         @Specialization(guards = "isUnitList(value)")
@@ -531,7 +520,7 @@ public class Unit {
                 case "-":
                     return recursive.apply(expr.arg1, L_subtracting) - recursive.apply(expr.arg2, L_subtracting);
                 case "*":
-                    RAbstractDoubleVector left = GridUtils.asDoubleVector(expr.arg1);
+                    RAbstractDoubleVector left = asDoubleVector(expr.arg1);
                     return left.getDataAt(index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying);
                 default:
                     break;
@@ -575,8 +564,12 @@ public class Unit {
             return L_plain;
         }
 
-        static CastNode createAsDoubleCast() {
-            return newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
+        private GrobUnitToInches getGrobUnitToInchesNode() {
+            if (grobUnitToInches == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                grobUnitToInches = insert(new GrobUnitToInches());
+            }
+            return grobUnitToInches;
         }
     }
 
-- 
GitLab


From 29f349abbc6f1cac2bc48a4e388425ac0d11f173 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Mar 2017 11:59:47 +0100
Subject: [PATCH 168/402] remove FastR-specific SEXPTYPE entries

---
 .../oracle/truffle/r/runtime/RDeparse.java    |  12 +-
 .../oracle/truffle/r/runtime/RRuntime.java    |   5 -
 .../oracle/truffle/r/runtime/RSerialize.java  | 105 +++++------------
 .../truffle/r/runtime/gnur/SEXPTYPE.java      |  60 ++--------
 .../truffle/r/test/ExpectedTestOutput.test    | 108 +++++++++++++++++-
 .../test/builtins/TestBuiltin_serialize.java  |  20 +++-
 .../builtins/TestBuiltin_unserialize.java     |   8 +-
 .../r/test/library/base/TestConnections.java  |   2 +-
 8 files changed, 172 insertions(+), 148 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index c2591fed09..ee419a0aec 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -578,24 +578,22 @@ public class RDeparse {
                     case BINARY:
                     case BINARY2:
                         RSyntaxElement[] subArgs = ((RSyntaxCall) arg).getSyntaxArguments();
-                        if (subArgs.length > 2) {
-                            needsParens = false;
-                            break;
-                        }
                         if (subArgs.length == 1) {
-                            if (!isLeft) {
+                            if (!isLeft && (arginfo.prec != RDeparse.PREC_NOT || mainOp.prec != RDeparse.PREC_NOT)) {
                                 needsParens = false;
                                 break;
                             }
                             if (arginfo.prec == RDeparse.PREC_SUM) {
                                 arginfo = arginfo.changePrec(RDeparse.PREC_SIGN);
                             }
-                        }
-                        if (subArgs.length == 2) {
+                        } else if (subArgs.length == 2) {
                             if (mainOp.prec == PREC_COMPARE && arginfo.prec == PREC_COMPARE) {
                                 needsParens = true;
                                 break;
                             }
+                        } else if (subArgs.length > 2) {
+                            needsParens = false;
+                            break;
                         }
                         needsParens = mainOp.prec > arginfo.prec || (mainOp.prec == arginfo.prec && isLeft == mainOp.rightassoc);
                         break;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index a9b666dd66..ad2573744b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -865,11 +865,6 @@ public class RRuntime {
             return RDataFactory.createLogicalVectorFromScalar((Byte) obj);
         } else if (obj instanceof String) {
             return RDataFactory.createStringVectorFromScalar((String) obj);
-        } else if (obj instanceof RComplex) {
-            RComplex complex = (RComplex) obj;
-            return RDataFactory.createComplexVector(new double[]{complex.getRealPart(), complex.getImaginaryPart()}, RDataFactory.COMPLETE_VECTOR);
-        } else if (obj instanceof RRaw) {
-            return RDataFactory.createRawVector(new byte[]{((RRaw) obj).getValue()});
         } else {
             return obj;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index 0c171118ed..a28f47de13 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -41,16 +41,13 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -839,10 +836,7 @@ public class RSerialize {
 
         /**
          * GnuR uses a pairlist to represent attributes, whereas FastR uses the abstract RAttributes
-         * class. FastR also uses different types to represent data/frame and factor which is
-         * handled in the setClassAttr. N.B. In theory connections can be unserialized but they are
-         * unusable, so we don't go to the trouble of converting the {@link RIntVector}
-         * representation into an {@link RConnection}.
+         * class.
          */
         @TruffleBoundary
         private static Object setAttributes(final Object object, Object attr) {
@@ -1461,46 +1455,56 @@ public class RSerialize {
                                 stream.writeInt(1);
                                 writeCHARSXP((String) obj);
                             } else {
-                                outStringVec((RStringVector) obj, true);
+                                outStringVec((RAbstractStringVector) obj, true);
                             }
                             break;
                         }
 
                         case INTSXP: {
-                            RAbstractIntVector vec = (RAbstractIntVector) obj;
-                            stream.writeInt(vec.getLength());
-                            for (int i = 0; i < vec.getLength(); i++) {
-                                stream.writeInt(vec.getDataAt(i));
+                            if (obj instanceof Integer) {
+                                stream.writeInt(1);
+                                stream.writeInt((int) obj);
+                            } else {
+                                RAbstractIntVector vec = (RAbstractIntVector) obj;
+                                stream.writeInt(vec.getLength());
+                                for (int i = 0; i < vec.getLength(); i++) {
+                                    stream.writeInt(vec.getDataAt(i));
+                                }
                             }
                             break;
                         }
 
                         case REALSXP: {
-                            RAbstractDoubleVector vec = (RAbstractDoubleVector) obj;
-                            stream.writeInt(vec.getLength());
-                            for (int i = 0; i < vec.getLength(); i++) {
-                                stream.writeDouble(vec.getDataAt(i));
+                            if (obj instanceof Double) {
+                                stream.writeInt(1);
+                                stream.writeDouble((double) obj);
+                            } else {
+                                RAbstractDoubleVector vec = (RAbstractDoubleVector) obj;
+                                stream.writeInt(vec.getLength());
+                                for (int i = 0; i < vec.getLength(); i++) {
+                                    stream.writeDouble(vec.getDataAt(i));
+                                }
                             }
                             break;
                         }
 
                         case LGLSXP: {
                             // Output as ints
-                            RLogicalVector vec = (RLogicalVector) obj;
-                            stream.writeInt(vec.getLength());
-                            for (int i = 0; i < vec.getLength(); i++) {
-                                byte val = vec.getDataAt(i);
-                                if (RRuntime.isNA(val)) {
-                                    stream.writeInt(RRuntime.INT_NA);
-                                } else {
-                                    stream.writeInt(vec.getDataAt(i));
+                            if (obj instanceof Byte) {
+                                stream.writeInt(1);
+                                stream.writeInt(RRuntime.logical2int((byte) obj));
+                            } else {
+                                RAbstractLogicalVector vec = (RAbstractLogicalVector) obj;
+                                stream.writeInt(vec.getLength());
+                                for (int i = 0; i < vec.getLength(); i++) {
+                                    stream.writeInt(RRuntime.logical2int(vec.getDataAt(i)));
                                 }
                             }
                             break;
                         }
 
                         case CPLXSXP: {
-                            RComplexVector vec = (RComplexVector) obj;
+                            RAbstractComplexVector vec = (RAbstractComplexVector) obj;
                             stream.writeInt(vec.getLength());
                             for (int i = 0; i < vec.getLength(); i++) {
                                 RComplex val = vec.getDataAt(i);
@@ -1551,55 +1555,6 @@ public class RSerialize {
                             break;
                         }
 
-                        /*
-                         * FastR scalar, (length 1) "vectors"
-                         */
-
-                        case FASTR_INT: {
-                            Integer value = (Integer) obj;
-                            stream.writeInt(1);
-                            stream.writeInt(value);
-                            break;
-                        }
-
-                        case FASTR_DOUBLE: {
-                            Double value = (Double) obj;
-                            stream.writeInt(1);
-                            stream.writeDouble(value);
-                            break;
-                        }
-
-                        case FASTR_BYTE: {
-                            Byte value = (Byte) obj;
-                            stream.writeInt(1);
-                            if (RRuntime.isNA(value)) {
-                                stream.writeInt(RRuntime.INT_NA);
-                            } else {
-                                stream.writeInt(value);
-                            }
-                            break;
-                        }
-
-                        case FASTR_COMPLEX: {
-                            RComplex value = (RComplex) obj;
-                            stream.writeInt(1);
-                            if (RRuntime.isNA(value)) {
-                                stream.writeDouble(RRuntime.DOUBLE_NA);
-                                stream.writeDouble(RRuntime.DOUBLE_NA);
-                            } else {
-                                stream.writeDouble(value.getRealPart());
-                                stream.writeDouble(value.getImaginaryPart());
-                            }
-                            break;
-                        }
-
-                        case FASTR_CONNECTION: {
-                            RConnection con = (RConnection) obj;
-                            stream.writeInt(1);
-                            stream.writeInt(con.getDescriptor());
-                            break;
-                        }
-
                         /*
                          * The objects that GnuR represents as a pairlist. To avoid stack overflow,
                          * these utilize manual tail recursion on the cdr of the pairlist.
@@ -1725,7 +1680,7 @@ public class RSerialize {
             return result;
         }
 
-        private void outStringVec(RStringVector vec, boolean strsxp) throws IOException {
+        private void outStringVec(RAbstractStringVector vec, boolean strsxp) throws IOException {
             if (!strsxp) {
                 stream.writeInt(0);
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index 4740bd9bc7..9aa6e79d34 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
@@ -14,9 +14,7 @@ package com.oracle.truffle.r.runtime.gnur;
 import java.util.HashMap;
 import java.util.Map;
 
-import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -48,18 +46,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 public enum SEXPTYPE {
 
-    /*
-     * FastR scalar variants of GnuR vector types (other than String) These could be removed in a
-     * similar way to String, but there is no pressing need.
-     */
-    FASTR_DOUBLE(300, Double.class),
-    FASTR_INT(301, Integer.class),
-    FASTR_BYTE(302, Byte.class),
-    FASTR_COMPLEX(303, RComplex.class),
-    // very special case
-    FASTR_SOURCESECTION(306, SourceSection.class),
-    FASTR_CONNECTION(307, RConnection.class),
-
     NILSXP(0, RNull.class), /* nil ()NULL */
     SYMSXP(1, RSymbol.class), /* symbols */
     LISTSXP(2, RPairList.class), /* lists of dotted pairs */
@@ -70,10 +56,10 @@ public enum SEXPTYPE {
     SPECIALSXP(7), /* special forms */
     BUILTINSXP(8), /* builtin non-special forms */
     CHARSXP(9), /* "scalar" string type (GnuR internal only) */
-    LGLSXP(10, RLogicalVector.class), /* logical vectors */
-    INTSXP(13, RIntVector.class, RIntSequence.class), /* integer vectors */
-    REALSXP(14, RDoubleVector.class, RDoubleSequence.class), /* real variables */
-    CPLXSXP(15, RComplexVector.class), /* complex variables */
+    LGLSXP(10, RLogicalVector.class, Byte.class), /* logical vectors */
+    INTSXP(13, RIntVector.class, RIntSequence.class, Integer.class), /* integer vectors */
+    REALSXP(14, RDoubleVector.class, RDoubleSequence.class, Double.class), /* real variables */
+    CPLXSXP(15, RComplexVector.class, RComplex.class), /* complex variables */
     STRSXP(16, RStringVector.class, String.class), /* string vectors */
     DOTSXP(17, RArgsValuesAndNames.class), /* dot-dot-dot object */
     ANYSXP(18), /* make "any" args work */
@@ -142,11 +128,9 @@ public enum SEXPTYPE {
                 }
             }
         }
-        // (only) promises, environments and connections have subtypes
+        // (only) promises and environments have subtypes
         if (REnvironment.class.isAssignableFrom(fastRClass)) {
             return ENVSXP;
-        } else if (RConnection.class.isAssignableFrom(fastRClass)) {
-            return FASTR_CONNECTION;
         } else if (RPromise.class.isAssignableFrom(fastRClass)) {
             return PROMSXP;
         }
@@ -174,52 +158,22 @@ public enum SEXPTYPE {
      */
     public static SEXPTYPE gnuRType(SEXPTYPE type, Object obj) {
         switch (type) {
-            case FUNSXP: {
+            case FUNSXP:
                 RFunction func = (RFunction) obj;
                 if (func.isBuiltin()) {
                     return SEXPTYPE.BUILTINSXP;
                 } else {
                     return SEXPTYPE.CLOSXP;
                 }
-            }
-
-            case LISTSXP: {
+            case LISTSXP:
                 RPairList pl = (RPairList) obj;
                 if (pl.getType() != null && pl.getType() == SEXPTYPE.LANGSXP) {
                     return SEXPTYPE.LANGSXP;
                 } else {
                     return type;
                 }
-            }
-
-            case FASTR_INT:
-                return SEXPTYPE.INTSXP;
-            case FASTR_DOUBLE:
-                return SEXPTYPE.REALSXP;
-            case FASTR_BYTE:
-                return SEXPTYPE.LGLSXP;
-            case FASTR_COMPLEX:
-                return SEXPTYPE.CPLXSXP;
-            case FASTR_CONNECTION:
-                return SEXPTYPE.INTSXP;
             default:
                 return type;
         }
     }
-
-    public static SEXPTYPE convertFastRScalarType(SEXPTYPE type) {
-        switch (type) {
-            case FASTR_DOUBLE:
-                return SEXPTYPE.REALSXP;
-            case FASTR_INT:
-                return SEXPTYPE.INTSXP;
-            case FASTR_BYTE:
-                return SEXPTYPE.LGLSXP;
-            case FASTR_COMPLEX:
-                return SEXPTYPE.CPLXSXP;
-            default:
-                assert false;
-                return null;
-        }
-    }
 }
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 0f04b19455..5d5d443d28 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
@@ -61694,6 +61694,90 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite
 #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv);
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize('asdf', connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 04 00
+[26] 09 00 00 00 04 61 73 64 66
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(111+8i, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0f 00 00 00 01 40 5b c0
+[26] 00 00 00 00 00 40 20 00 00 00 00 00 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(111, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0e 00 00 00 01 40 5b c0
+[26] 00 00 00 00 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(111L, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0d 00 00 00 01 00 00 00
+[26] 6f
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(FALSE, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0a 00 00 00 01 00 00 00
+[26] 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(NA_character_, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 00 00
+[26] 09 ff ff ff ff
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(NA_complex_, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0f 00 00 00 01 7f f0 00
+[26] 00 00 00 07 a2 7f f0 00 00 00 00 07 a2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(NA_integer_, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0d 00 00 00 01 80 00 00
+[26] 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(NA_real_, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0e 00 00 00 01 7f f0 00
+[26] 00 00 00 07 a2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(TRUE, connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0a 00 00 00 01 00 00 00
+[26] 01
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(as.raw(10), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 18 00 00 00 01 0a
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(as.raw(210), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 18 00 00 00 01 d2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(as.raw(c(1, 55, 210)), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 18 00 00 00 03 01 37 d2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(c(111+8i, 55+9i, NA), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0f 00 00 00 03 40 5b c0
+[26] 00 00 00 00 00 40 20 00 00 00 00 00 00 40 4b 80 00 00 00 00 00 40 22 00 00
+[51] 00 00 00 00 7f f0 00 00 00 00 07 a2 7f f0 00 00 00 00 07 a2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(c(111, 99, NA, 44), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0e 00 00 00 04 40 5b c0
+[26] 00 00 00 00 00 40 58 c0 00 00 00 00 00 7f f0 00 00 00 00 07 a2 40 46 00 00
+[51] 00 00 00 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(c(111L, 11L, 990000L, NA_integer_), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0d 00 00 00 04 00 00 00
+[26] 6f 00 00 00 0b 00 0f 1b 30 80 00 00 00
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); serialize(c(TRUE, FALSE, TRUE, NA, TRUE), connection=NULL)
+ [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 0a 00 00 00 05 00 00 00
+[26] 01 00 00 00 00 00 00 00 01 80 00 00 00 00 00 00 01
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
 #options(keep.source=FALSE); serialize(quote("bar"), connection=NULL)
  [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 04 00
@@ -71268,6 +71352,14 @@ numeric(0)
 #unserialize(serialize("Hello world", NULL))
 [1] "Hello world"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
+#unserialize(serialize((1:15)+0.1, NULL))
+ [1]  1.1  2.1  3.1  4.1  5.1  6.1  7.1  8.1  9.1 10.1 11.1 12.1 13.1 14.1 15.1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
+#unserialize(serialize(1:15, NULL))
+ [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
 #unserialize(serialize(3+2i, NULL))
 [1] 3+2i
@@ -71292,6 +71384,18 @@ NULL
 #unserialize(serialize(c(1,2,3,4), NULL))
 [1] 1 2 3 4
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
+#unserialize(serialize(c(1L,2L,99L,NA), NULL))
+[1]  1  2 99 NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
+#unserialize(serialize(c(3+2i, 5+944i, NA), NULL))
+[1] 3+  2i 5+944i     NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
+#unserialize(serialize(c(TRUE, FALSE, NA, FALSE, TRUE), NULL))
+[1]  TRUE FALSE    NA FALSE  TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.tests#
 #unserialize(serialize(data.frame(col1=c(9,8,7), col2=1:3), NULL))
   col1 col2
@@ -71455,7 +71559,7 @@ function(x, y = 1, ...) {
     NA
 }
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unserialize.testunserialize#
 #options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL))
 function(x = {
     1 + a
@@ -76903,7 +77007,7 @@ Error in cat(x, file = file, sep = c(rep.int(sep, ncolumns - 1), "\n"),  :
 [51] 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 08 00 00 00 00 00 00 00 00 00
 [76] fe
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.library.base.TestConnections.testRawWriteBinary#
 #conn <- rawConnection(raw(0), "wb"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn)
   [1] 52 44 58 32 0a 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 04 02 00 00
  [26] 00 01 00 04 00 09 00 00 00 05 76 61 6c 75 65 00 00 02 13 00 00 00 02 00 00
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
index 31dbe41a62..0679742b3e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,24 @@ public class TestBuiltin_serialize extends TestBase {
         assertEval("options(keep.source=FALSE); serialize(quote(111+11), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote(a+b), connection=NULL)");
 
+        assertEval("options(keep.source=FALSE); serialize(TRUE, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(FALSE, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(c(TRUE, FALSE, TRUE, NA, TRUE), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize('asdf', connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(NA_character_, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(NA_complex_, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(NA_integer_, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(NA_real_, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(111L, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(c(111L, 11L, 990000L, NA_integer_), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(111+8i, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(c(111+8i, 55+9i, NA), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(111, connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(c(111, 99, NA, 44), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(as.raw(10), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(as.raw(210), connection=NULL)");
+        assertEval("options(keep.source=FALSE); serialize(as.raw(c(1, 55, 210)), connection=NULL)");
+
         assertEval("options(keep.source=FALSE); serialize(quote((a+b)), connection=NULL)");
         assertEval("options(keep.source=FALSE); serialize(quote((a %asdf% b)), connection=NULL)");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java
index 786a26fcd9..db3283245f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unserialize.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,8 @@ import com.oracle.truffle.r.test.TestBase;
 
 public class TestBuiltin_unserialize extends TestBase {
     private static final String[] BASIC_TYPE_VALUES = new String[]{
-                    "c(1,2,3,4)", "3L", "42", "\"Hello world\"", "3+2i", "TRUE", "head(mtcars)",
-                    "data.frame(col1=c(9,8,7), col2=1:3)", "expression(x+1)", "list(1,2)", "NULL"
+                    "c(1,2,3,4)", "3L", "c(1L,2L,99L,NA)", "1:15", "(1:15)+0.1", "42", "\"Hello world\"", "3+2i", "c(3+2i, 5+944i, NA)", "TRUE", "c(TRUE, FALSE, NA, FALSE, TRUE)",
+                    "head(mtcars)", "data.frame(col1=c(9,8,7), col2=1:3)", "expression(x+1)", "list(1,2)", "NULL"
     };
 
     @Test
@@ -88,7 +88,7 @@ public class TestBuiltin_unserialize extends TestBase {
         assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y,...) { 1 }), connection=NULL))");
         assertEval(Output.IgnoreWhitespace, "options(keep.source=FALSE); unserialize(serialize(quote(function(x,y=1,...) { NA }), connection=NULL))");
         assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { NA }), connection=NULL))");
-        assertEval(Ignored.OutputFormatting, "options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL))");
+        assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !!NA }), connection=NULL))");
         assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y,...) { !1+5i }), connection=NULL))");
         assertEval("options(keep.source=FALSE); unserialize(serialize(quote(function(x={1 + a},y=c(1,2,3),z=\"foo\",...) { !1+5i }), connection=NULL))");
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index a727d532ef..d96b63d0c3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -244,7 +244,7 @@ public class TestConnections extends TestRBase {
         assertEval(Ignored.ImplementationError, "{ s <- \"äöüß\"; rc <- rawConnection(raw(0), \"wb\"); write(charToRaw(s), rc); res <- rawConnectionValue(rc); close(rc); res }");
         assertEval("{ zz <- rawConnection(raw(0), \"wb\"); x <- c(\"a\", \"this will be truncated\", \"abc\"); nc <- c(3, 10, 3); writeChar(x, zz, nc, eos = NULL); writeChar(x, zz, eos = \"\\r\\n\"); res <- rawConnectionValue(zz); close(zz); res }");
 
-        assertEval(Ignored.ImplementationError, "conn <- rawConnection(raw(0), \"wb\"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn)");
+        assertEval("conn <- rawConnection(raw(0), \"wb\"); value <- list(a=c(1,2,3), b='foo'); save(value, file=conn); rawConnectionValue(conn)");
         // ignored because save refuses to write to a rawConnection that is not configured to binary
         assertEval(Ignored.ImplementationError, "conn <- rawConnection(raw(0), \"w\"); value <- c(1,2,3); save(value, file=conn); rawConnectionValue(conn)");
     }
-- 
GitLab


From 2c300601224309c205cb0a929f529d67c9820464 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 13:33:32 +0100
Subject: [PATCH 169/402] FastR Grid: make DrawingContext immutable

---
 .../truffle/r/library/fastrGrid/GPar.java     | 24 +++---
 .../r/library/fastrGrid/GridState.java        |  7 +-
 .../truffle/r/library/fastrGrid/LPoints.java  | 81 ++++++++++++++-----
 .../fastrGrid/device/DrawingContext.java      | 15 ++--
 .../device/DrawingContextDefaults.java        | 32 ++++++++
 .../r/library/fastrGrid/device/GridColor.java | 13 +++
 .../library/fastrGrid/device/GridDevice.java  |  9 +--
 7 files changed, 129 insertions(+), 52 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 41d785ee1f..6f69df073c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -17,7 +17,9 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import java.util.Arrays;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContextDefaults;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -84,11 +86,12 @@ public final class GPar {
     };
     private static final RStringVector NAMES_VECTOR = (RStringVector) RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
 
-    public static RList createNew() {
+    public static RList createNew(GridDevice device) {
         Object[] data = new Object[GP_LENGTH];
+        DrawingContextDefaults defaults = device.getDrawingContextDefaults();
         Arrays.fill(data, RNull.instance);
-        data[GP_FILL] = "transparent";
-        data[GP_COL] = "black";
+        data[GP_COL] = defaults.color;
+        data[GP_FILL] = defaults.fillColor;
         data[GP_GAMMA] = newDoubleVec(0);
         data[GP_LTY] = "solid";
         data[GP_LWD] = newDoubleVec(1);
@@ -102,7 +105,9 @@ public final class GPar {
         data[GP_LINEJOIN] = "round";
         data[GP_LINEMITRE] = newDoubleVec(10);
         data[GP_LEX] = newDoubleVec(1);
-        return RDataFactory.createList(data, NAMES_VECTOR);
+        RList result = RDataFactory.createList(data, NAMES_VECTOR);
+        result.makeSharedPermanent();
+        return result;
     }
 
     public static double getCex(RList gpar) {
@@ -122,6 +127,7 @@ public final class GPar {
 
         private GParDrawingContext(RList list) {
             data = list.getDataWithoutCopying();
+            list.makeSharedPermanent();
         }
 
         @Override
@@ -158,11 +164,6 @@ public final class GPar {
             return getGridColor(GP_COL);
         }
 
-        @Override
-        public void setColor(GridColor color) {
-            data[GP_COL] = GridColorUtils.gridColorToRString(color);
-        }
-
         @Override
         public double getFontSize() {
             return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
@@ -178,11 +179,6 @@ public final class GPar {
             return getGridColor(GP_FILL);
         }
 
-        @Override
-        public void setFillColor(GridColor color) {
-            data[GP_FILL] = GridColorUtils.gridColorToRString(color);
-        }
-
         private GridColor getGridColor(int index) {
             return GridColorUtils.gridColorFromString(RRuntime.asString(data[index]));
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 5d840cbf68..a77c06245e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -40,14 +40,11 @@ public final class GridState {
     }
 
     void initGPar(GridDevice currentDevice) {
-        gpar = GPar.createNew();
-        currentDevice.initDrawingContext(GPar.asDrawingContext(gpar));
+        gpar = GPar.createNew(currentDevice);
     }
 
     public static DrawingContext getInitialGPar(GridDevice device) {
-        DrawingContext result = GPar.asDrawingContext(GPar.createNew());
-        device.initDrawingContext(result);
-        return result;
+        return GPar.asDrawingContext(GPar.createNew(device));
     }
 
     public RList getGpar() {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index fb8977b780..d4b71e0a5b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -73,11 +73,12 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
 
         // Note: unlike in other drawing primitives, we only consider length of x
         int length = unitLength.execute(xVec);
+        PointDrawingContext pointDrawingCtx = new PointDrawingContext(drawingCtx, drawingCtx.getFillColor(), drawingCtx.getFillColor());
         for (int i = 0; i < length; i++) {
             Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx), vpTransform.transform);
             double size = unitToInches.convertWidth(sizeVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(size)) {
-                drawSymbol(drawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
+                pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
             }
         }
         return RNull.instance;
@@ -85,38 +86,31 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
 
     // transcribed from engine.c function GESymbol
 
-    private void drawSymbol(DrawingContext drawingCtx, GridDevice dev, double cex, int pch, double size, double x, double y) {
+    private PointDrawingContext drawSymbol(PointDrawingContext drawingCtx, GridDevice dev, double cex, int pch, double size, double x, double y) {
         // pch 0 - 25 are interpreted as geometrical shapes, pch from ascii code of ' ' are
         // interpreted as corresponding ascii character, which should be drawn
         switch (pch) {
             case 46:
-                drawDot(drawingCtx, dev, cex, x, y);
-                break;
+                return drawDot(drawingCtx, dev, cex, x, y);
             case 1:
-                drawOctahedron(drawingCtx, dev, GridColor.TRANSPARENT, size, x, y);
-                break;
+                return drawOctahedron(drawingCtx, dev, GridColor.TRANSPARENT, size, x, y);
             case 16:
-                drawOctahedron(drawingCtx, dev, drawingCtx.getColor(), size, x, y);
-                break;
+                return drawOctahedron(drawingCtx, dev, drawingCtx.getWrapped().getColor(), size, x, y);
             default:
                 throw RInternalError.unimplemented("grid.points unimplemented symbol " + pch);
         }
     }
 
-    private static void drawOctahedron(DrawingContext drawingCtx, GridDevice dev, GridColor fill, double size, double x, double y) {
-        GridColor originalFill = drawingCtx.getFillColor();
-        drawingCtx.setFillColor(fill);
+    private static PointDrawingContext drawOctahedron(PointDrawingContext drawingCtxIn, GridDevice dev, GridColor fill, double size, double x, double y) {
+        PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), fill);
         dev.drawCircle(drawingCtx, x, y, RADIUS * size);
-        drawingCtx.setFillColor(originalFill);
+        return drawingCtx;
     }
 
-    private static void drawDot(DrawingContext drawingCtx, GridDevice dev, double cex, double x, double y) {
+    private static PointDrawingContext drawDot(PointDrawingContext drawingCtxIn, GridDevice dev, double cex, double x, double y) {
         // NOTE: we are *filling* a rect with the current colour (we are not drawing the border AND
         // we are not using the current fill colour)
-        GridColor originalFill = drawingCtx.getFillColor();
-        drawingCtx.setFillColor(drawingCtx.getColor());
-        drawingCtx.setColor(GridColor.TRANSPARENT);
-
+        PointDrawingContext drawingCtx = drawingCtxIn.update(GridColor.TRANSPARENT, drawingCtxIn.getWrapped().getColor());
         /*
          * The idea here is to use a 0.01" square, but to be of at least one device unit in each
          * direction, assuming that corresponds to pixels. That may be odd if pixels are not square,
@@ -135,8 +129,57 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             yc = 0.5;
         }
         dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc);
+        return drawingCtx;
+    }
+
+    private static final class PointDrawingContext implements DrawingContext {
+        private final DrawingContext inner;
+        private final GridColor color;
+        private final GridColor fillColor;
+
+        private PointDrawingContext(DrawingContext inner, GridColor color, GridColor fillColor) {
+            this.inner = inner;
+            this.color = color;
+            this.fillColor = fillColor;
+        }
+
+        // This allows to re-use the existing instance if it would have the same parameters. The
+        // assumption is that the users will actually draw many points in a row with the same
+        // parameters.
+        private PointDrawingContext update(GridColor color, GridColor fillColor) {
+            if (this.color.equals(color) && this.fillColor.equals(fillColor)) {
+                return this;
+            }
+            return new PointDrawingContext(inner, color, fillColor);
+        }
+
+        @Override
+        public GridLineType getLineType() {
+            return inner.getLineType();
+        }
 
-        drawingCtx.setColor(drawingCtx.getFillColor());
-        drawingCtx.setFillColor(originalFill);
+        @Override
+        public GridColor getColor() {
+            return color;
+        }
+
+        @Override
+        public double getFontSize() {
+            return inner.getFontSize();
+        }
+
+        @Override
+        public double getLineHeight() {
+            return inner.getLineHeight();
+        }
+
+        @Override
+        public GridColor getFillColor() {
+            return fillColor;
+        }
+
+        private DrawingContext getWrapped() {
+            return inner;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index f3d42fa703..b3baf6db3c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -23,7 +23,8 @@
 package com.oracle.truffle.r.library.fastrGrid.device;
 
 /**
- * Defines parameters for drawing, like color, line style etc.
+ * Defines parameters for drawing, like color, line style etc. The implementations must be
+ * immutable.
  */
 public interface DrawingContext {
     double INCH_TO_POINTS_FACTOR = 72.27;
@@ -52,12 +53,10 @@ public interface DrawingContext {
 
     GridLineType getLineType();
 
-    GridColor getColor();
-
     /**
-     * Alows to set the color drawing color of shape borders, lines and text.
+     * Drawing color of shape borders, lines and text.
      */
-    void setColor(GridColor color);
+    GridColor getColor();
 
     /**
      * Gets the font size in points.
@@ -71,10 +70,8 @@ public interface DrawingContext {
      */
     double getLineHeight();
 
-    GridColor getFillColor();
-
     /**
-     * Alows to set the fill color of shapes.
+     * The fill color of shapes.
      */
-    void setFillColor(GridColor color);
+    GridColor getFillColor();
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java
new file mode 100644
index 0000000000..b7043cbcd4
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+/**
+ * Allows the device to communicate the default values for its initial {@link DrawingContext}. The
+ * format of the values is the same as accepted by the {@code gpar()} function in R.
+ */
+public class DrawingContextDefaults {
+    public String fillColor = "transparent";
+    public String color = "black";
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
index e4cdd7517a..4b42cdce8c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
@@ -55,4 +55,17 @@ public class GridColor {
     public int getAlpha() {
         return (value >> 24) & 0xff;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof GridColor)) {
+            return false;
+        }
+        return value == ((GridColor) obj).value;
+    }
+
+    @Override
+    public int hashCode() {
+        return value;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 9e37a873bb..56592ff848 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -58,12 +58,11 @@ public interface GridDevice {
     double getHeight();
 
     /**
-     * May change the default values the of the initial drawing context instance.
-     * 
-     * @param ctx instance of drawing context to be altered.
+     * May change the default values the of the initial drawing context instance. Must return
+     * non-null value.
      */
-    default void initDrawingContext(DrawingContext ctx) {
-        // nop
+    default DrawingContextDefaults getDrawingContextDefaults() {
+        return new DrawingContextDefaults();
     }
 
     double getStringWidth(DrawingContext ctx, String text);
-- 
GitLab


From d0e4cd2b411cd049fe97d4b3002299797fe6a080 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 22 Mar 2017 17:25:02 +0100
Subject: [PATCH 170/402] FastR Grid: dev.hold/dev.flush support

---
 .../fastrGrid/FastRGridExternalLookup.java    |   3 +-
 .../r/library/fastrGrid/GridContext.java      |   3 +-
 .../r/library/fastrGrid/GridState.java        |  10 ++
 .../device/BufferedJFrameDevice.java          | 139 ++++++++++++++++++
 .../library/fastrGrid/device/GridDevice.java  |  15 ++
 .../fastrGrid/device/JFrameDevice.java        |  26 +++-
 .../fastrGrid/grDevices/DevHoldFlush.java     |  61 ++++++++
 7 files changed, 248 insertions(+), 9 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index 5863de72a4..b2d0f365a4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice;
 import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
@@ -42,7 +43,7 @@ public class FastRGridExternalLookup {
     public static RExternalBuiltinNode lookupDotExternal(String name) {
         switch (name) {
             case "devholdflush":
-                return new IgnoredGridExternal(RNull.instance);
+                return DevHoldFlush.create();
             case "PDF":
                 return new IgnoredGridExternal(RNull.instance);
             default:
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 2980378933..ec68fcff20 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.r.library.fastrGrid.device.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
 
@@ -43,7 +44,7 @@ public final class GridContext {
 
     public GridDevice getCurrentDevice() {
         if (currentDevice == null) {
-            currentDevice = new JFrameDevice();
+            currentDevice = new BufferedJFrameDevice(new JFrameDevice());
         }
         return currentDevice;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index a77c06245e..fbedb1f853 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -23,6 +23,7 @@ public final class GridState {
     private REnvironment gridEnv;
     private double scale = 1;
     private boolean deviceInitialized;
+    private int devHoldCount;
 
     /**
      * Current grob being drawn (for determining the list of grobs to search when evaluating a
@@ -33,6 +34,15 @@ public final class GridState {
     GridState() {
     }
 
+    public int getDevHoldCount() {
+        return devHoldCount;
+    }
+
+    public int setDevHoldCount(int devHoldCount) {
+        this.devHoldCount = devHoldCount;
+        return devHoldCount;
+    }
+
     public void init(REnvironment gridEnv, GridDevice currentDevice) {
         this.gridEnv = gridEnv;
         this.currentGrob = RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
new file mode 100644
index 0000000000..f85a04b4c4
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+import java.awt.image.BufferStrategy;
+import java.util.ArrayList;
+
+/**
+ * Decorator for {@link JFrameDevice} that implements {@link #hold()} and {@link #flush()}. Those
+ * methods open/draw a 2D graphics buffer, while the buffer is open, any drawing is done in the
+ * buffer not on the screen and we also record any drawing code to be able to replay it if the
+ * buffer happens to loose contents, which is a possibility mentioned in the documentation. Note: we
+ * rely on the fact that {@linkl DrawingContext} is immutable.
+ */
+public class BufferedJFrameDevice implements GridDevice {
+    private final JFrameDevice inner;
+    private BufferStrategy buffer;
+    private ArrayList<Runnable> drawActions;
+
+    public BufferedJFrameDevice(JFrameDevice inner) {
+        this.inner = inner;
+    }
+
+    @Override
+    public void openNewPage() {
+        inner.openNewPage();
+    }
+
+    @Override
+    public void hold() {
+        if (buffer != null) {
+            return; // already buffering
+        }
+        buffer = inner.getCurrentFrame().getBufferStrategy();
+        if (buffer == null) {
+            inner.getCurrentFrame().createBufferStrategy(2);
+            buffer = inner.getCurrentFrame().getBufferStrategy();
+        }
+        if (drawActions == null) {
+            drawActions = new ArrayList<>();
+        } else {
+            drawActions.clear();
+        }
+        inner.initGraphics(buffer.getDrawGraphics());
+    }
+
+    @Override
+    public void flush() {
+        if (buffer == null) {
+            return;
+        }
+
+        buffer.show();
+        // re-draw the buffer if the contents were lost
+        while (buffer.contentsLost()) {
+            inner.initGraphics(buffer.getDrawGraphics());
+            for (Runnable drawAction : drawActions) {
+                drawAction.run();
+            }
+            buffer.show();
+        }
+
+        inner.initGraphics(inner.getCurrentFrame().getGraphics());
+        buffer.dispose();
+        buffer = null;
+    }
+
+    @Override
+    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height) {
+        inner.drawRect(ctx, leftX, topY, width, height);
+        if (buffer != null) {
+            drawActions.add(() -> inner.drawRect(ctx, leftX, topY, width, height));
+        }
+    }
+
+    @Override
+    public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        inner.drawPolyLines(ctx, x, y, startIndex, length);
+        if (buffer != null) {
+            drawActions.add(() -> inner.drawPolyLines(ctx, x, y, startIndex, length));
+        }
+    }
+
+    @Override
+    public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
+        inner.drawCircle(ctx, centerX, centerY, radius);
+        if (buffer != null) {
+            drawActions.add(() -> inner.drawCircle(ctx, centerX, centerY, radius));
+        }
+    }
+
+    @Override
+    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
+        inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text);
+        if (buffer != null) {
+            drawActions.add(() -> inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text));
+        }
+    }
+
+    @Override
+    public double getWidth() {
+        return inner.getWidth();
+    }
+
+    @Override
+    public double getHeight() {
+        return inner.getHeight();
+    }
+
+    @Override
+    public double getStringWidth(DrawingContext ctx, String text) {
+        return inner.getStringWidth(ctx, text);
+    }
+
+    @Override
+    public double getStringHeight(DrawingContext ctx, String text) {
+        return inner.getStringHeight(ctx, text);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 56592ff848..91593aebf6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -31,6 +31,21 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 public interface GridDevice {
     void openNewPage();
 
+    /**
+     * If the device is capable of buffering, calling {@code hold} should start buffering, e.g.
+     * nothing is displayed on the device, until {@link #flush()} is called.
+     */
+    default void hold() {
+    }
+
+    /**
+     * Should display the whole buffer at once.
+     *
+     * @see #hold()
+     */
+    default void flush() {
+    }
+
     void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height);
 
     /**
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 8821b8dd0f..2ac24f74a6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -28,6 +28,7 @@ import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.HeadlessException;
 import java.awt.Paint;
@@ -73,12 +74,7 @@ public class JFrameDevice implements GridDevice {
         if (currentFrame == null) {
             currentFrame = new FastRFrame();
             currentFrame.setVisible(true);
-            graphics = (Graphics2D) currentFrame.getGraphics();
-            graphics.translate(0, currentFrame.getHeight());
-            graphics.scale(POINTS_IN_INCH, -POINTS_IN_INCH);
-            graphics.setStroke(new BasicStroke((float) (1d / POINTS_IN_INCH)));
-            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-            graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+            initGraphics(currentFrame.getGraphics());
         } else {
             noTranform(() -> {
                 graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
@@ -156,6 +152,22 @@ public class JFrameDevice implements GridDevice {
         });
     }
 
+    FastRFrame getCurrentFrame() {
+        return currentFrame;
+    }
+
+    void initGraphics(Graphics newGraphics) {
+        if (graphics != null) {
+            graphics.dispose();
+        }
+        graphics = (Graphics2D) newGraphics;
+        graphics.translate(0, currentFrame.getHeight());
+        graphics.scale(POINTS_IN_INCH, -POINTS_IN_INCH);
+        graphics.setStroke(new BasicStroke((float) (1d / POINTS_IN_INCH)));
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+    }
+
     private void drawShape(DrawingContext drawingCtx, Shape shape) {
         Paint paint = graphics.getPaint();
         graphics.setPaint(fromGridColor(drawingCtx.getFillColor()));
@@ -223,7 +235,7 @@ public class JFrameDevice implements GridDevice {
         longdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{2f * dashSize}, 0f);
     }
 
-    private static class FastRFrame extends JFrame {
+    static class FastRFrame extends JFrame {
         private static final long serialVersionUID = 1L;
         private final Dimension framePreferredSize = new Dimension(720, 720);
         private final JPanel fastRComponent = new JPanel();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java
new file mode 100644
index 0000000000..853f82bcf3
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.GridState;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+
+public abstract class DevHoldFlush extends RExternalBuiltinNode.Arg1 {
+    static {
+        Casts casts = new Casts(DevHoldFlush.class);
+        casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst();
+    }
+
+    public static DevHoldFlush create() {
+        return DevHoldFlushNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    int doInteger(int num) {
+        GridState gridState = GridContext.getContext().getGridState();
+        int result = gridState.getDevHoldCount();
+        if (num < 0) {
+            result = gridState.setDevHoldCount(Math.max(0, result + num));
+            if (result == 0) {
+                GridContext.getContext().getCurrentDevice().flush();
+            }
+        } else if (num > 0) {
+            if (result == 0) {
+                GridContext.getContext().getCurrentDevice().hold();
+            }
+            result = gridState.setDevHoldCount(result + num);
+        }
+        return result;
+    }
+}
-- 
GitLab


From 6650c08be84a33f7df746aa375f142dfa0c7d79f Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 14:53:59 +0100
Subject: [PATCH 171/402] FastR Grid: support font family and style

---
 .../truffle/r/library/fastrGrid/GPar.java     | 15 ++++++-
 .../truffle/r/library/fastrGrid/LPoints.java  | 10 +++++
 .../fastrGrid/device/DrawingContext.java      | 32 +++++++++++++
 .../fastrGrid/device/JFrameDevice.java        | 45 ++++++++++++++++---
 4 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 6f69df073c..04932a5a8b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -64,7 +64,8 @@ public final class GPar {
     private static final int GP_LINEJOIN = 12;
     private static final int GP_LINEMITRE = 13;
     private static final int GP_LEX = 14;
-    private static final int GP_FONTFACE = 15;
+
+    // Note: there is last slot "fontface" which is either unused at all, or only used in R code
     private static final int GP_LENGTH = 16;
     private static final String[] NAMES = new String[]{
                     "fill",
@@ -82,7 +83,7 @@ public final class GPar {
                     "linejoin",
                     "linemitre",
                     "lex",
-                    "fontface"  // TODO: could not find this name in grid sources
+                    "fontface"
     };
     private static final RStringVector NAMES_VECTOR = (RStringVector) RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
 
@@ -169,6 +170,16 @@ public final class GPar {
             return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
         }
 
+        @Override
+        public GridFontStyle getFontStyle() {
+            return GridFontStyle.fromInt(RRuntime.asInteger(data[GP_FONT]));
+        }
+
+        @Override
+        public String getFontFamily() {
+            return RRuntime.asString(data[GP_FONTFAMILY]);
+        }
+
         @Override
         public double getLineHeight() {
             return asDouble(data[GP_LINEHEIGHT]);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index d4b71e0a5b..51747552cb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -168,6 +168,16 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             return inner.getFontSize();
         }
 
+        @Override
+        public GridFontStyle getFontStyle() {
+            return inner.getFontStyle();
+        }
+
+        @Override
+        public String getFontFamily() {
+            return inner.getFontFamily();
+        }
+
         @Override
         public double getLineHeight() {
             return inner.getLineHeight();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index b3baf6db3c..4ff84b7777 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -29,6 +29,10 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 public interface DrawingContext {
     double INCH_TO_POINTS_FACTOR = 72.27;
 
+    String FONT_FAMILY_MONO = "mono";
+    String FONT_FAMILY_SANS = "sans";
+    String FONT_FAMILY_SERIF = "serif";
+
     enum GridLineType {
         // The order is important!
         BLANK,
@@ -51,6 +55,25 @@ public interface DrawingContext {
         }
     }
 
+    enum GridFontStyle {
+        PLAIN,
+        BOLD,
+        ITALIC,
+        BOLDITALIC,
+        /**
+         * Supposed to be symbol font in Adobe symbol encoding.
+         */
+        SYMBOL;
+
+        /**
+         * Return enum's value corresponding to R's value.
+         */
+        public static GridFontStyle fromInt(int num) {
+            assert num > 0 && num <= SYMBOL.ordinal() + 1;
+            return values()[num - 1];
+        }
+    }
+
     GridLineType getLineType();
 
     /**
@@ -65,6 +88,15 @@ public interface DrawingContext {
      */
     double getFontSize();
 
+    GridFontStyle getFontStyle();
+
+    /**
+     * Gets the font family name. The standard values that any device must implement are "serif",
+     * "sans" and "mono". On top of that the device can recognize name of any font that it can
+     * support.
+     */
+    String getFontFamily();
+
     /**
      * Gets the height of a line in multiplies of the base line height.
      */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 2ac24f74a6..cb0f0a6462 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -28,6 +28,7 @@ import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.HeadlessException;
@@ -46,6 +47,7 @@ import java.util.function.Supplier;
 import javax.swing.JFrame;
 import javax.swing.JPanel;
 
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineType;
 import com.oracle.truffle.r.runtime.RInternalError;
 
@@ -116,7 +118,7 @@ public class JFrameDevice implements GridDevice {
             tr.translate((float) (leftX * POINTS_IN_INCH), (float) (currentFrame.getContentPane().getHeight() - bottomY * POINTS_IN_INCH));
             tr.rotate(-rotationAnticlockWise);
             graphics.setTransform(tr);
-            setFontSize(ctx);
+            setFont(ctx);
             graphics.drawString(text, 0, 0);
             return null;
         });
@@ -136,7 +138,7 @@ public class JFrameDevice implements GridDevice {
     public double getStringWidth(DrawingContext ctx, String text) {
         setContext(ctx);
         return noTranform(() -> {
-            setFontSize(ctx);
+            setFont(ctx);
             int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
             return swingUnits / POINTS_IN_INCH;
         });
@@ -146,7 +148,7 @@ public class JFrameDevice implements GridDevice {
     public double getStringHeight(DrawingContext ctx, String text) {
         setContext(ctx);
         return noTranform(() -> {
-            setFontSize(ctx);
+            setFont(ctx);
             int swingUnits = graphics.getFont().getSize();
             return swingUnits / POINTS_IN_INCH;
         });
@@ -181,9 +183,42 @@ public class JFrameDevice implements GridDevice {
         graphics.setStroke(fromGridLineType(ctx.getLineType()));
     }
 
-    private void setFontSize(DrawingContext ctx) {
+    private void setFont(DrawingContext ctx) {
         float fontSize = (float) ((ctx.getFontSize() / INCH_TO_POINTS_FACTOR) * POINTS_IN_INCH);
-        graphics.setFont(graphics.getFont().deriveFont(fontSize));
+        Font font = new Font(getFontName(ctx.getFontFamily()), getAwtFontStyle(ctx.getFontStyle()), 1).deriveFont(fontSize);
+        graphics.setFont(font);
+    }
+
+    private String getFontName(String gridFontFamily) {
+        if (gridFontFamily == null) {
+            return null;
+        }
+        switch (gridFontFamily) {
+            case DrawingContext.FONT_FAMILY_MONO:
+                return Font.MONOSPACED;
+            case DrawingContext.FONT_FAMILY_SANS:
+                return Font.SANS_SERIF;
+            case DrawingContext.FONT_FAMILY_SERIF:
+                return Font.SERIF;
+            case "":
+                return null;
+        }
+        return gridFontFamily;
+    }
+
+    private int getAwtFontStyle(GridFontStyle fontStyle) {
+        switch (fontStyle) {
+            case PLAIN:
+                return Font.PLAIN;
+            case BOLD:
+                return Font.BOLD;
+            case ITALIC:
+                return Font.ITALIC;
+            case BOLDITALIC:
+                return Font.BOLD | Font.ITALIC;
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected value of GridFontStyle enum");
+        }
     }
 
     private <T> T noTranform(Supplier<T> action) {
-- 
GitLab


From bde2c48432c862fd2b92dcd015ed75a85c3f7744 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Thu, 23 Mar 2017 16:19:43 +0100
Subject: [PATCH 172/402] [GR-2098] Support for NaN vector access

---
 .../access/vector/PositionCheckSubsetNode.java  |  2 +-
 .../com/oracle/truffle/r/runtime/RDeparse.java  |  2 +-
 .../r/test/library/base/TestSimpleLists.java    |  4 ++++
 .../r/test/library/base/TestSimpleMatrix.java   |  5 ++++-
 .../r/test/library/base/TestSimpleVectors.java  | 17 +++++++++++++++++
 5 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
index 22dfb909a4..f45d9018a6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
@@ -144,7 +144,6 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
                     @Cached("create()") GetNamesAttributeNode getNamesNode,
                     @Cached("create()") SetNamesAttributeNode setNamesNode) {
         RAbstractIntVector intPosition = RDataFactory.createIntVector(positionLength);
-        intPosition.setComplete(position.isComplete());
         // requires names preservation
         RStringVector names = hasNamesProfile.profile(getNamesNode.getNames(position));
         if (names != null) {
@@ -204,6 +203,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
             }
             intPosition.setDataAt(convertedStore, i, intPositionValue);
         }
+        intPosition.setComplete(!hasSeenNA);
         return doIntegerProfiled(profile, dimensionLength, intPosition, positionLength, hasSeenPositive, hasSeenNegative, hasSeenNA, outOfBoundsCount, zeroCount, maxOutOfBoundsIndex);
 
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 3fe65ddf1d..a2b582ecce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -642,7 +642,7 @@ public class RDeparse {
                 }
             } else if (value instanceof RPairList) {
                 RPairList arglist = (RPairList) value;
-                assert arglist.getType() == SEXPTYPE.LISTSXP;
+                assert arglist.getType() == null || arglist.getType() == SEXPTYPE.LISTSXP : arglist.getType();
                 append("pairlist(");
                 int i = 0;
                 boolean lbreak = false;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java
index 88b2cbf42e..f9391d284b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleLists.java
@@ -48,10 +48,14 @@ public class TestSimpleLists extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ l <- list(1,2,3) ; l[[0]] }");
 
         assertEval("{ l <- list(1,2,3) ; l[[NA]] }");
+        assertEval("{ l <- list(1,2,3) ; l[[NaN]] }");
         assertEval("{ l <- list(1,2,3) ; typeof(l[[NA]]) }");
+        assertEval("{ l <- list(1,2,3) ; typeof(l[[NaN]]) }");
 
         assertEval("{ l <- list(1,2,3) ; l[NA] }");
+        assertEval("{ l <- list(1,2,3) ; l[NaN] }");
         assertEval("{ l <- list(1,2,3) ; typeof(l[NA]) }");
+        assertEval("{ l <- list(1,2,3) ; typeof(l[NaN]) }");
 
         assertEval("{ l <- list(1,2,3) ; l[-2] }");
         assertEval("{ l <- list(1,2,3) ; typeof(l[-2]) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java
index 3ce0c94e12..2324ef9e6a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleMatrix.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -82,8 +82,11 @@ public class TestSimpleMatrix extends TestBase {
         assertEval(template("{ x<-%0; dim(x)<-c(1,4); dimnames(x)<-list(\"z\", c(\"a\", \"b\", \"c\", \"d\")); x[1, c(1,3)] }", TESTED_4L_VECTORS));
         assertEval(template("{ x<-%0; dim(x)<-c(1,4); dimnames(x)<-list(\"z\", c(\"a\", \"b\", \"d\", \"e\")); x[1, c(1,3)] }", TESTED_4L_VECTORS));
         assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(1, NA), ] }", TESTED_4L_VECTORS));
+        assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(1, NaN), ] }", TESTED_4L_VECTORS));
         assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(TRUE, NA), ] }", TESTED_4L_VECTORS));
+        assertEval(template("{ x<-%0; dim(x)<-c(2,2); x[c(TRUE, NaN), ] }", TESTED_4L_VECTORS));
         assertEval(template("{ x<-%0; x<-1:4; dim(x)<-c(2,2); x[NA, ] }", TESTED_4L_VECTORS));
+        assertEval(template("{ x<-%0; x<-1:4; dim(x)<-c(2,2); x[NaN, ] }", TESTED_4L_VECTORS));
         // A misalignment error similar to those in TestSimpleVector (testIgnored1-3)
         WhiteList wl = WhiteList.create("matrix formatting1");
         wl.add("{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); dimnames(x)<-list(c(\"a\", \"b\"), c(\"c\", \"d\")); x[c(1,NA), 1] }",
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
index 21158c964e..60ee20a4ef 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
@@ -162,6 +162,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-3:1; x[1L] }");
         assertEval("{ x<-3:1; x[2L] }");
         assertEval("{ x<-3:1; x[3L] }");
+        assertEval("{ x<-3:1; x[NA_integer_] }");
     }
 
     @Test
@@ -192,6 +193,8 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-3:1; x[1.1] }");
         assertEval("{ x<-3:1; x[2.1] }");
         assertEval("{ x<-3:1; x[3.1] }");
+        assertEval("{ x<-3:1; x[NaN] }");
+        assertEval("{ x<-3:1; x[NA_real_] }");
     }
 
     @Test
@@ -225,6 +228,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-NULL; x[1L] }");
         assertEval("{ x<-NULL; x[2L] }");
         assertEval("{ x<-NULL; x[3L] }");
+        assertEval("{ x<-NULL; x[NaN] }");
         assertEval("{ x<-1.1:3.1; x[1L] }");
         assertEval("{ x<-1.1:3.1; x[2L] }");
         assertEval("{ x<-1.1:3.1; x[3L] }");
@@ -242,7 +246,10 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-1L; x[-2L] }");
         assertEval("{ x<-1L; x[TRUE] }");
         assertEval("{ x<-1L; x[FALSE] }");
+        assertEval("{ x<-1L; x[NA_real_] }");
+        assertEval("{ x<-1L; x[NA_integer_] }");
         assertEval("{ x<-1L; x[NA] }");
+        assertEval("{ x<-1L; x[NaN] }");
     }
 
     @Test
@@ -262,6 +269,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-1; x[TRUE] }");
         assertEval("{ x<-1; x[FALSE] }");
         assertEval("{ x<-1; x[NA] }");
+        assertEval("{ x<-1; x[NaN] }");
     }
 
     @Test
@@ -399,6 +407,10 @@ public class TestSimpleVectors extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ x<-7; x[[0]]<-42; x }");
         assertEval("{ x<-1:4;  x[c(1, 0)]<-42; x }");
         assertEval("{ x<-1:4;  x[c(0, 1)]<-42; x }");
+        assertEval("{ x<-1:4;  x[c(1, NA)]<-42; x }");
+        assertEval("{ x<-1:4;  x[c(1, NaN)]<-42; x }");
+        assertEval("{ x<-1:4;  x[c(NA, 1)]<-42; x }");
+        assertEval("{ x<-1:4;  x[c(NaN, 1)]<-42; x }");
         assertEval("{ x<-1:4;  x[c(1, 0)]<-c(7, 42); x }");
         assertEval("{ x<-1:4;  x[c(0, 1)]<-c(7, 42); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[NULL]<-42; x }");
@@ -407,7 +419,9 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,4)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,4)]]<-c(42, 43); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,NA)]<-c(42, 43); x }");
+        assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,NaN)]<-c(42, 43); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(NA,1)]<-c(42, 43); x }");
+        assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(NaN,1)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,0)]]<-c(42, 43); x }");
         assertEval("{ x<-1:4; dim(x)<-c(2,2); x[c(1,0)]<-c(42, 43); x }");
         assertEval(Output.IgnoreErrorContext, "{ x<-1:4; dim(x)<-c(2,2); x[[c(1,0,0)]]<-c(42, 43); x }");
@@ -689,6 +703,9 @@ public class TestSimpleVectors extends TestBase {
         assertEval("{ e <- quote(f(x=a, y=b)); names(e[-1]) }");
 
         assertEval("{ x<-quote(function(x, y) 42); x[[2]] }");
+        assertEval("{ x<-quote(function(x, y) 42); x[2] }");
+        assertEval("{ x<-quote(function(x, y) 42); x[NA] }");
+        assertEval("{ x<-quote(function(x, y) 42); x[NaN] }");
         assertEval("{ x<-quote(function(x, y) 42); typeof(x[[2]][[1]]) }");
         assertEval("{ x<-quote(function(x, y) 42); names(x[[2]]) }");
         assertEval("{ x<-quote(function(x, y=7) 42); x[[2]] }");
-- 
GitLab


From d1fd6030865d708ad0baf6e0e8af2acef94df82f Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Thu, 23 Mar 2017 16:19:59 +0100
Subject: [PATCH 173/402] generated expected output messages

---
 .../truffle/r/test/ExpectedTestOutput.test    | 200 ++++++++++++++++++
 1 file changed, 200 insertions(+)

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 47a9ac5e75..847a117110 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
@@ -84566,6 +84566,12 @@ NULL
 NULL
 
 
+##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
+#{ l <- list(1,2,3) ; l[NaN] }
+[[1]]
+NULL
+
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#Output.IgnoreErrorContext#
 #{ l <- list(1,2,3) ; l[[-2]] }
 Error in l[[-2]] :
@@ -84589,6 +84595,10 @@ Error in l[[5]] : subscript out of bounds
 #{ l <- list(1,2,3) ; l[[NA]] }
 NULL
 
+##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
+#{ l <- list(1,2,3) ; l[[NaN]] }
+NULL
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
 #{ l <- list(1,2,3) ; typeof(l[-2]) }
 [1] "list"
@@ -84601,10 +84611,18 @@ NULL
 #{ l <- list(1,2,3) ; typeof(l[NA]) }
 [1] "list"
 
+##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
+#{ l <- list(1,2,3) ; typeof(l[NaN]) }
+[1] "list"
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
 #{ l <- list(1,2,3) ; typeof(l[[NA]]) }
 [1] "NULL"
 
+##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
+#{ l <- list(1,2,3) ; typeof(l[[NaN]]) }
+[1] "NULL"
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListAccess#
 #{ l <- list(c(1,2,3),"eep") ; l[[1]] }
 [1] 1 2 3
@@ -85338,18 +85356,34 @@ a     1   NA
 [1,]    1    3
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-(1:4); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,]    1    3
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-(1:4); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,]    1    3
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-(1:4); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,]    1    3
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-(1:4); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-(1:4); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-(1:8); dim(x)<-c(2, 4); x[c(-1, -2),c(-1)] }
      [,1] [,2] [,3]
@@ -85683,18 +85717,34 @@ a    "a" NA
 [1,] "a"  "c"
 [2,] NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c("a", "b", "c", "d"); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,] "a"  "c"
+[2,] NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c("a", "b", "c", "d"); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,] "a"  "c"
 [2,] NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c("a", "b", "c", "d"); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,] "a"  "c"
+[2,] NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c("a", "b", "c", "d"); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c("a", "b", "c", "d"); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(1,4); dimnames(x)<-list("z", c("a", "b", "c", "d")); x[, 0] }
 complex(0)
@@ -85819,18 +85869,34 @@ a    1+1i   NA
 [1,] 1+1i 3+3i
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,] 1+1i 3+3i
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,] 1+1i 3+3i
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,] 1+1i 3+3i
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(1+1i, 2+2i, 3+3i, 4+4i); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1+1i, 2+2i, 3+3i, 4+4i, 5+5i, 6+6i, 7+7i, 8+8i); dim(x)<-c(2, 4); x[c(-1, -2),c(-1)] }
      [,1] [,2] [,3]
@@ -86041,18 +86107,34 @@ a    1.1   NA
 [1,]  1.1  3.3
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(1.1, 2.2, 3.3, 4.4); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,]  1.1  3.3
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1.1, 2.2, 3.3, 4.4); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,]  1.1  3.3
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(1.1, 2.2, 3.3, 4.4); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,]  1.1  3.3
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1.1, 2.2, 3.3, 4.4); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(1.1, 2.2, 3.3, 4.4); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8); dim(x)<-c(2, 4); x[c(-1, -2),c(-1)] }
      [,1] [,2] [,3]
@@ -86271,18 +86353,34 @@ TRUE   NA
 [1,] TRUE TRUE
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(TRUE, FALSE, TRUE, FALSE); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,] TRUE TRUE
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(TRUE, FALSE, TRUE, FALSE); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,] TRUE TRUE
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(TRUE, FALSE, TRUE, FALSE); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,] TRUE TRUE
+[2,]   NA   NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(TRUE, FALSE, TRUE, FALSE); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(TRUE, FALSE, TRUE, FALSE); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(1,4); dimnames(x)<-list("z", c("a", "b", "c", "d")); x[, 0] }
 raw(0)
@@ -86403,18 +86501,34 @@ a    01   00
 [1,]   01   03
 [2,]   00   00
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,]   01   03
+[2,]   00   00
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,]   01   03
 [2,]   00   00
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,]   01   03
+[2,]   00   00
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-c(as.raw(1),as.raw(2),as.raw(3),as.raw(4)); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(1,4); dimnames(x)<-list("z", c("a", "b", "c", "d")); x[, 0] }
 list()
@@ -86577,18 +86691,34 @@ NULL
 [1,] TRUE 42
 [2,] NULL NULL
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(2,2); x[c(1, NaN), ] }
+     [,1] [,2]
+[1,] TRUE 42
+[2,] NULL NULL
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(2,2); x[c(TRUE, NA), ] }
      [,1] [,2]
 [1,] TRUE 42
 [2,] NULL NULL
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-list(TRUE, "a", 42, 1.1); dim(x)<-c(2,2); x[c(TRUE, NaN), ] }
+     [,1] [,2]
+[1,] TRUE 42
+[2,] NULL NULL
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
 #{ x<-list(TRUE, "a", 42, 1.1); x<-1:4; dim(x)<-c(2,2); x[NA, ] }
      [,1] [,2]
 [1,]   NA   NA
 [2,]   NA   NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testAccessScalarIndex#
+#{ x<-list(TRUE, "a", 42, 1.1); x<-1:4; dim(x)<-c(2,2); x[NaN, ] }
+[1] NA NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleMatrix.testMatrixAccessWithScalarAndVector#
 #{ i <- c(1L,3L,5L) ; m <- 1:10 ; dim(m) <- c(2,5) ; m[2,i] }
 [1]  2  6 10
@@ -119141,6 +119271,18 @@ Error in match(x, table, nomatch = 0L) :
 #{ x<-quote(function(x, y) 42); typeof(x[[2]][[1]]) }
 [1] "symbol"
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
+#{ x<-quote(function(x, y) 42); x[2] }
+pairlist(x = , y = )()
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
+#{ x<-quote(function(x, y) 42); x[NA] }
+NULL(NULL, NULL, NULL)
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
+#{ x<-quote(function(x, y) 42); x[NaN] }
+NULL()
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testLanguageIndex#
 #{ x<-quote(function(x, y) 42); x[[2]] }
 $x
@@ -121454,6 +121596,10 @@ NULL
 #{ x<-NULL; x[3L] }
 NULL
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectors#
+#{ x<-NULL; x[NaN] }
+NULL
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ b <- as.list(3:5) ; dim(b) <- c(1,3) ; b[NULL] <- NULL ; b }
      [,1] [,2] [,3]
@@ -122112,6 +122258,22 @@ Warning message:
 In x[c(1, 0)] <- c(7, 42) :
   number of items to replace is not a multiple of replacement length
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
+#{ x<-1:4;  x[c(1, NA)]<-42; x }
+[1] 42  2  3  4
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
+#{ x<-1:4;  x[c(1, NaN)]<-42; x }
+[1] 42  2  3  4
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
+#{ x<-1:4;  x[c(NA, 1)]<-42; x }
+[1] 42  2  3  4
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
+#{ x<-1:4;  x[c(NaN, 1)]<-42; x }
+[1] 42  2  3  4
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2);  x[NA, NA]<-7; x }
      [,1] [,2]
@@ -122470,6 +122632,11 @@ In x[c(1, 0, 0)] <- c(42, 43) :
 Error in x[c(1, NA)] <- c(42, 43) :
   NAs are not allowed in subscripted assignments
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
+#{ x<-1:4; dim(x)<-c(2,2); x[c(1,NaN)]<-c(42, 43); x }
+Error in x[c(1, NaN)] <- c(42, 43) :
+  NAs are not allowed in subscripted assignments
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2); x[c(NA, 1),1]<-7; x }
      [,1] [,2]
@@ -122492,6 +122659,11 @@ Error in x[c(NA, 1), 1] <- c(7, 42) :
 Error in x[c(NA, 1)] <- c(42, 43) :
   NAs are not allowed in subscripted assignments
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
+#{ x<-1:4; dim(x)<-c(2,2); x[c(NaN,1)]<-c(42, 43); x }
+Error in x[c(NaN, 1)] <- c(42, 43) :
+  NAs are not allowed in subscripted assignments
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testMoreVectorsOther#
 #{ x<-1:4; dim(x)<-c(2,2); x[c(as.raw(42))]<-c(42,43); x }
 Error in x[c(as.raw(42))] <- c(42, 43) : invalid subscript type 'raw'
@@ -125573,6 +125745,10 @@ numeric(0)
 #{ x<-1; x[NA] }
 [1] NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleAsVector#
+#{ x<-1; x[NaN] }
+[1] NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleAsVector#
 #{ x<-1; x[TRUE] }
 [1] 1
@@ -125601,6 +125777,14 @@ numeric(0)
 #{ x<-3:1; x[3.1] }
 [1] 1
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleIndexOnVector#
+#{ x<-3:1; x[NA_real_] }
+[1] NA
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleIndexOnVector#
+#{ x<-3:1; x[NaN] }
+[1] NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarDoubleIndexOnVector#
 #{ x<-c(1,2,3); x[1.1] }
 [1] 1
@@ -126251,6 +126435,18 @@ integer(0)
 #{ x<-1L; x[NA] }
 [1] NA
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector#
+#{ x<-1L; x[NA_integer_] }
+[1] NA
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector#
+#{ x<-1L; x[NA_real_] }
+[1] NA
+
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector#
+#{ x<-1L; x[NaN] }
+[1] NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntAsVector#
 #{ x<-1L; x[TRUE] }
 [1] 1
@@ -126279,6 +126475,10 @@ integer(0)
 #{ x<-3:1; x[3L] }
 [1] 1
 
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntIndexOnVector#
+#{ x<-3:1; x[NA_integer_] }
+[1] NA
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testScalarIntIndexOnVector#
 #{ x<-c(1,2,3); x[1L] }
 [1] 1
-- 
GitLab


From b58bd82efbc813ff4234ce5e70d1045071da98eb Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Mar 2017 14:22:01 +0100
Subject: [PATCH 174/402] =?UTF-8?q?send=20KEYS=20message=20for=20names(?=
 =?UTF-8?q?=E2=80=A6)=20of=20foreign=20objects,=20intrinsics=20for=20java?=
 =?UTF-8?q?=20class=20and=20NEW=20message?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../r/nodes/builtin/base/BasePackage.java     |  2 +
 .../builtin/base/ConnectionFunctions.java     |  4 +-
 .../truffle/r/nodes/builtin/base/Names.java   | 39 +++++++++
 .../r/nodes/builtin/base/SeqFunctions.java    |  1 -
 .../r/nodes/builtin/fastr/FastRInterop.java   | 80 +++++++++++++++++++
 .../r/nodes/function/ArgumentMatcher.java     |  1 -
 .../com/oracle/truffle/r/runtime/RError.java  |  2 +-
 .../truffle/r/runtime/data/RVector.java       |  1 -
 .../truffle/r/test/ExpectedTestOutput.test    | 21 ++---
 .../r/test/library/fastr/TestInterop.java     |  3 +-
 10 files changed, 130 insertions(+), 24 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index ac9d5aa0bc..938bee74e6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -371,8 +371,10 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create);
         add(FastRInterop.HasSize.class, FastRInteropFactory.HasSizeNodeGen::create);
         add(FastRInterop.Import.class, FastRInteropFactory.ImportNodeGen::create);
+        add(FastRInterop.InteropNew.class, FastRInteropFactory.InteropNewNodeGen::create);
         add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create);
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
+        add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
         add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create);
         add(FastRPkgSource.class, FastRPkgSourceNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 333055b1fb..e8b5fdc22f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -1360,12 +1360,10 @@ public abstract class ConnectionFunctions {
                     ByteChannel ch = JavaInterop.asJavaObject(ByteChannel.class, channel);
                     return new ChannelRConnection("", ch, open, encoding).asVector();
                 }
-                throw error(RError.Message.INVALID_CHANNEL_OBJECT, JavaInterop.unbox(channel).getClass());
+                throw error(RError.Message.INVALID_CHANNEL_OBJECT);
             } catch (IOException ex) {
                 throw RInternalError.shouldNotReachHere();
             }
         }
-
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index bb8b0830c7..cbce750d09 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -27,17 +27,27 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
+@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 @RBuiltin(name = "names", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class Names extends RBuiltinNode {
 
@@ -64,6 +74,35 @@ public abstract class Names extends RBuiltinNode {
         return env.ls(true, null, false);
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected Object getNames(TruffleObject obj,
+                    @Cached("GET_SIZE.createNode()") Node getSizeNode,
+                    @Cached("KEYS.createNode()") Node keysNode,
+                    @Cached("READ.createNode()") Node readNode,
+                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
+                    @Cached("UNBOX.createNode()") Node unboxNode) {
+
+        try {
+            TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
+            if (keys != null) {
+                int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
+                String[] names = new String[size];
+                for (int i = 0; i < size; i++) {
+                    Object value;
+                    value = ForeignAccess.sendRead(readNode, keys, i);
+                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
+                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
+                    }
+                    names[i] = (String) value;
+                }
+                return RDataFactory.createStringVector(names, true);
+            }
+            return RNull.instance;
+        } catch (InteropException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        }
+    }
+
     @Fallback
     protected RNull getNames(@SuppressWarnings("unused") Object operand) {
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 5b86993957..25e8d6eaeb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index 90f9307588..fcc48d956d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -40,9 +40,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
@@ -55,9 +60,15 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class FastRInterop {
 
@@ -250,4 +261,73 @@ public class FastRInterop {
             return value;
         }
     }
+
+    @RBuiltin(name = ".fastr.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX)
+    public abstract static class JavaClass extends RBuiltinNode {
+
+        static {
+            Casts casts = new Casts(JavaClass.class);
+            casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public TruffleObject javaClass(String clazz) {
+            try {
+                return JavaInterop.asTruffleObject(Class.forName(clazz));
+            } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) {
+                throw error(Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+    }
+
+    @ImportStatic({com.oracle.truffle.api.interop.Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
+    public abstract static class InteropNew extends RBuiltinNode {
+
+        static {
+            Casts.noCasts(InteropNew.class);
+        }
+
+        private static Object toJava(Object value) {
+            Object vector = RRuntime.asAbstractVector(value);
+            if (vector instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) vector).getLength() == 1) {
+                if (vector instanceof RAbstractDoubleVector) {
+                    RAbstractDoubleVector v = (RAbstractDoubleVector) vector;
+                    return v.getDataAt(0);
+                } else if (vector instanceof RAbstractLogicalVector) {
+                    RAbstractLogicalVector v = (RAbstractLogicalVector) vector;
+                    return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
+                } else if (vector instanceof RAbstractRawVector) {
+                    RAbstractRawVector v = (RAbstractRawVector) vector;
+                    return v.getDataAt(0).getValue();
+                } else if (vector instanceof RAbstractStringVector) {
+                    RAbstractStringVector v = (RAbstractStringVector) vector;
+                    return v.getDataAt(0);
+                }
+            }
+            return value;
+        }
+
+        @Specialization(limit = "99", guards = {"isForeignObject(clazz)", "length == args.getLength()"})
+        @TruffleBoundary
+        public Object interopNew(TruffleObject clazz, RArgsValuesAndNames args,
+                        @SuppressWarnings("unused") @Cached("args.getLength()") int length,
+                        @Cached("createNew(length).createNode()") Node sendNew) {
+            try {
+                Object[] argValues = new Object[args.getLength()];
+                for (int i = 0; i < argValues.length; i++) {
+                    argValues[i] = toJava(args.getArgument(i));
+                }
+                return ForeignAccess.sendNew(sendNew, clazz, argValues);
+            } catch (SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
+                throw error(Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
+            }
+        }
+
+        @Fallback
+        public Object interopNew(@SuppressWarnings("unused") Object clazz, @SuppressWarnings("unused") Object args) {
+            throw error(Message.GENERIC, "interop object needed as receiver of NEW message");
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index b79bd83127..3268b3bd76 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -60,7 +60,6 @@ import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * <p>
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 72ab6fa32c..38f80bcd6a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -855,7 +855,7 @@ public final class RError extends RuntimeException {
         TRUNCATE_NOT_ENABLED("truncation not enabled for this connection"),
         TRUNCATE_UNSUPPORTED_FOR_CONN("cannot truncate connection: %s"),
         INCOMPLETE_STRING_AT_EOF_DISCARDED("incomplete string at end of file has been discarded"),
-        INVALID_CHANNEL_OBJECT("invalid channel object type: %s"),
+        INVALID_CHANNEL_OBJECT("invalid channel object (ByteChannel expected)"),
         INVALID_TAG("invalid tag"),
         INVALID_VARIABLE_NAMES("invalid variable names"),
         INVALID_EXPRESSION("invalid expression in '%s'"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 82eec933b6..e0d3de6980 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
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 47a9ac5e75..eca54bee2c 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
@@ -129769,6 +129769,11 @@ a b c d e
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', new.env()) }
 
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue') } else { v <- .fastr.interop.import('testPOJO'); names(v) }
+[1] "intValue"     "longValue"    "charValue"    "shortValue"   "booleanValue"
+[6] "stringValue"
+
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testPOJO'); print(v) }
 $intValue
@@ -129838,22 +129843,6 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); 3 * (unit(1, 'mm')); }
-[1] 3*1mm
-
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); grid:::unit.list(3 * unit(1, 'mm')); }
-[1] 3*1mm
-
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); unit.c(unit(1,'mm'), 42*unit(1,'mm')); }
-[1] 1mm    42*1mm
-
-##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
-#{ library(grid); unit.c(unit(1,'mm'), unit(1,'mm')) }
-[1] 1mm 1mm
-
 ##com.oracle.truffle.r.test.library.methods.TestSubstituteDirect.basicTests#
 #a<-substituteDirect(quote(x+1), NA); a
 Error in substituteDirect(quote(x + 1), NA) :
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index 2250149cb2..35c727bf15 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,5 +118,6 @@ public class TestInterop extends TestBase {
         assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[1]   1  -5 199\\n" +
                         "attr(,\"is.truffle.object\")\\n" +
                         "[1] TRUE\\n')");
+        assertEvalFastR("v <- .fastr.interop.import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')");
     }
 }
-- 
GitLab


From 97817b2b68d7ee00a603f7238163700acfb2bae8 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Mar 2017 16:29:40 +0100
Subject: [PATCH 175/402] reorder specializations in DoCall

---
 .../truffle/r/nodes/builtin/base/DoCall.java  | 21 +------------------
 .../r/nodes/builtin/base/LogFunctions.java    | 12 +++++------
 .../r/nodes/builtin/base/SortFunctions.java   | 12 +++++------
 3 files changed, 12 insertions(+), 33 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index adf2cc9288..0c6e143e00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -36,7 +35,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctions.Get;
@@ -67,7 +65,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-// TODO Implement completely, this is a simple implementation that works when the envir argument is ignored
 @RBuiltin(name = ".fastr.do.call", visibility = CUSTOM, kind = RBuiltinKind.INTERNAL, parameterNames = {"what", "args", "quote", "envir"}, behavior = COMPLEX)
 public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNodeChildren {
 
@@ -90,33 +87,17 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
         return GetNodeGen.create();
     }
 
-    protected ReadVariableNode createRead(RAbstractStringVector what) {
-        if (what.getLength() != 1) {
-            CompilerDirectives.transferToInterpreter();
-            throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
-        }
-        return ReadVariableNode.createForcedFunctionLookup(RSyntaxNode.INTERNAL, what.getDataAt(0));
-    }
-
     @Specialization
     protected Object doCall(VirtualFrame frame, RAbstractStringVector what, RList argsAsList, boolean quote, REnvironment env,
                     @Cached("createGet()") Get getNode) {
         if (what.getLength() != 1) {
-            CompilerDirectives.transferToInterpreter();
             throw error(RError.Message.MUST_BE_STRING_OR_FUNCTION, "what");
         }
         RFunction func = (RFunction) getNode.execute(frame, what.getDataAt(0), env, RType.Function.getName(), true);
         return doCall(frame, func, argsAsList, quote, env);
     }
 
-    @Specialization(limit = "3", guards = {"what.getLength() == 1", "read.getIdentifier() == what.getDataAt(0)"})
-    protected Object doCallCached(VirtualFrame frame, @SuppressWarnings("unused") RAbstractStringVector what, RList argsAsList, boolean quote, REnvironment env,
-                    @Cached("createRead(what)") ReadVariableNode read) {
-        RFunction func = (RFunction) read.execute(frame);
-        return doCall(frame, func, argsAsList, quote, env);
-    }
-
-    @Specialization(replaces = "doCallCached")
+    @Specialization
     protected Object doCall(VirtualFrame frame, RFunction func, RList argsAsList, boolean quote, REnvironment env) {
         /*
          * To re-create the illusion of a normal call, turn the values in argsAsList into promises.
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 5d2ddfdef3..76cea754f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -178,7 +178,7 @@ public class LogFunctions {
             return log(vector, base, index -> checkDouble(vector.getDataAt(index), xNACheck), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
         }
 
-        private double checkDouble(double d, NACheck na) {
+        private static double checkDouble(double d, NACheck na) {
             na.check(d);
             return d;
         }
@@ -248,7 +248,7 @@ public class LogFunctions {
             return log(vector, base, index -> checkComplex(vector.getDataAt(index), xNACheck), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
         }
 
-        private RComplex checkComplex(RComplex rc, NACheck xNACheck) {
+        private static RComplex checkComplex(RComplex rc, NACheck xNACheck) {
             xNACheck.check(rc);
             return rc;
         }
@@ -345,7 +345,7 @@ public class LogFunctions {
             return createResult(vector, complexVector, complete, getDimsNode, getNamesNode, copyAttrsNode);
         }
 
-        private void fill(double[] array, int i, RComplex rc) {
+        private static void fill(double[] array, int i, RComplex rc) {
             array[i] = rc.getRealPart();
             array[i + 1] = rc.getImaginaryPart();
         }
@@ -375,7 +375,7 @@ public class LogFunctions {
             return ret;
         }
 
-        private RComplex logb(RComplex x) {
+        private static RComplex logb(RComplex x) {
             double re = x.getRealPart();
             double im = x.getImaginaryPart();
 
@@ -392,14 +392,14 @@ public class LogFunctions {
             return result;
         }
 
-        private RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode,
+        private static RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode,
                         CopyOfRegAttributesNode copyAttrsNode) {
             RComplexVector result = RDataFactory.createComplexVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source));
             copyAttrsNode.execute(source, result);
             return result;
         }
 
-        private boolean isNaN(RComplex base) {
+        private static boolean isNaN(RComplex base) {
             return Double.isNaN(base.getRealPart()) || Double.isNaN(base.getImaginaryPart());
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index f06a920474..1dc73f7345 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -23,13 +23,16 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL;
-import static com.oracle.truffle.r.runtime.RError.Message.RAW_SORT;
+import static com.oracle.truffle.r.runtime.RError.Message.NOT_NUMERIC_VECTOR;
 import static com.oracle.truffle.r.runtime.RError.Message.ONLY_ATOMIC_CAN_BE_SORTED;
+import static com.oracle.truffle.r.runtime.RError.Message.RAW_SORT;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -39,12 +42,8 @@ import java.util.Collections;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asVector;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import static com.oracle.truffle.r.runtime.RError.Message.NOT_NUMERIC_VECTOR;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -60,7 +59,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * The internal functions mandated by {@code base/sort.R}. N.B. We use the standard JDK sorting
-- 
GitLab


From 5f1a9378e28cefe0ef4cf7052984b4513dbe4f72 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 15:25:30 +0100
Subject: [PATCH 176/402] FastR Grid: proper line style support

---
 .../truffle/r/library/fastrGrid/GPar.java     | 40 +++++++++++-------
 .../truffle/r/library/fastrGrid/LPoints.java  |  2 +-
 .../fastrGrid/device/DrawingContext.java      | 33 +++++----------
 .../fastrGrid/device/JFrameDevice.java        | 42 +++++--------------
 4 files changed, 48 insertions(+), 69 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 04932a5a8b..be7d76d5f9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -132,10 +132,10 @@ public final class GPar {
         }
 
         @Override
-        public GridLineType getLineType() {
+        public byte[] getLineType() {
             Object lty = data[GP_LTY];
             if (lty == null || lty == RNull.instance) {
-                return GridLineType.SOLID;
+                return DrawingContext.GRID_LINE_SOLID;
             }
             String name = RRuntime.asString(lty);
             if (name != null) {
@@ -154,10 +154,10 @@ public final class GPar {
                 num = RRuntime.INT_NA;
             }
 
-            if (RRuntime.isNA(num)) {
+            if (RRuntime.isNA(num) || num < LINE_STYLES.length) {
                 throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line type.");
             }
-            return GridLineType.fromInt(num);
+            return LINE_STYLES[num];
         }
 
         @Override
@@ -194,26 +194,38 @@ public final class GPar {
             return GridColorUtils.gridColorFromString(RRuntime.asString(data[index]));
         }
 
-        private GridLineType lineTypeFromName(String name) {
+        private static final byte[] DASHED_LINE = new byte[]{4, 4};
+        private static final byte[] DOTTED_LINE = new byte[]{1, 3};
+        private static final byte[] DOTDASH_LINE = new byte[]{1, 3, 4, 3};
+        private static final byte[] LONGDASH_LINE = new byte[]{7, 3};
+        private static final byte[] TWODASH_LINE = new byte[]{2, 2, 6, 2};
+        private static final byte[][] LINE_STYLES = new byte[][]{DrawingContext.GRID_LINE_BLANK, DrawingContext.GRID_LINE_SOLID, DASHED_LINE, DOTTED_LINE, DOTDASH_LINE, LONGDASH_LINE, TWODASH_LINE};
+
+        private byte[] lineTypeFromName(String name) {
             switch (name) {
                 case "solid":
-                    return GridLineType.SOLID;
+                    return DrawingContext.GRID_LINE_SOLID;
                 case "dashed":
-                    return GridLineType.DASHED;
+                    return DASHED_LINE;
                 case "dotted":
-                    return GridLineType.DOTTED;
+                    return DOTTED_LINE;
                 case "dotdashed":
-                    return GridLineType.DOTDASHED;
+                    return DOTDASH_LINE;
                 case "longdash":
-                    return GridLineType.LONGDASH;
+                    return LONGDASH_LINE;
                 case "twodash":
-                    return GridLineType.TWODASH;
+                    return TWODASH_LINE;
                 case "blank":
-                    return GridLineType.BLANK;
-                default:
-                    // TODO: implement hex digits as line style
+                    return DrawingContext.GRID_LINE_BLANK;
+            }
+            byte[] result = new byte[name.length()];
+            for (int i = 0; i < name.length(); i++) {
+                result[i] = (byte) Character.digit(name.charAt(i), 16);
+                if (result[i] == -1) {
                     throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected line type '" + name + "'.");
+                }
             }
+            return result;
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 51747552cb..07545f1ba2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -154,7 +154,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         }
 
         @Override
-        public GridLineType getLineType() {
+        public byte[] getLineType() {
             return inner.getLineType();
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index 4ff84b7777..55993db1e7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -33,27 +33,8 @@ public interface DrawingContext {
     String FONT_FAMILY_SANS = "sans";
     String FONT_FAMILY_SERIF = "serif";
 
-    enum GridLineType {
-        // The order is important!
-        BLANK,
-        SOLID,
-        DASHED,
-        DOTTED,
-        DOTDASHED,
-        LONGDASH,
-        TWODASH;
-
-        private static final int LINE_TYPES_COUNT = 7;
-        private static final GridLineType[] allValues = values();
-
-        public static GridLineType fromInt(int num) {
-            if (num == -1) {
-                return BLANK;
-            }
-            assert num >= 1;
-            return allValues[(num - 1) % LINE_TYPES_COUNT + 1];
-        }
-    }
+    byte[] GRID_LINE_BLANK = null;
+    byte[] GRID_LINE_SOLID = new byte[0];
 
     enum GridFontStyle {
         PLAIN,
@@ -74,7 +55,15 @@ public interface DrawingContext {
         }
     }
 
-    GridLineType getLineType();
+    /**
+     * Returns either one of the constants {@link #GRID_LINE_BLANK} or {@link #GRID_LINE_SOLID} or
+     * an array with a pattern consisting of lengths. Lengths at odd positions are dashes and
+     * lengths at the even positions are spaces between them, the pattern should be interpreted as
+     * cyclic. Example: '3,2,10,1' means 3 units of line, 2 units of space, 10 units of line, 1 unit
+     * of space and repeat. The unit here can be device dependent, but should be something "small",
+     * like a pixel.
+     */
+    byte[] getLineType();
 
     /**
      * Drawing color of shape borders, lines and text.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index cb0f0a6462..6b012f4492 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -48,7 +48,6 @@ import javax.swing.JFrame;
 import javax.swing.JPanel;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineType;
 import com.oracle.truffle.r.runtime.RInternalError;
 
 public class JFrameDevice implements GridDevice {
@@ -61,11 +60,6 @@ public class JFrameDevice implements GridDevice {
 
     private static BasicStroke solidStroke;
     private static BasicStroke blankStroke;
-    private static BasicStroke dashedStroke;
-    private static BasicStroke longdashedStroke;
-    private static BasicStroke twodashedStroke;
-    private static BasicStroke dotdashedStroke;
-    private static BasicStroke dottedStroke;
 
     private FastRFrame currentFrame;
     private Graphics2D graphics;
@@ -233,41 +227,25 @@ public class JFrameDevice implements GridDevice {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
 
-    private static BasicStroke fromGridLineType(GridLineType type) {
-        switch (type) {
-            case SOLID:
-                return solidStroke;
-            case BLANK:
-                return blankStroke;
-            case DASHED:
-                return dashedStroke;
-            case DOTDASHED:
-                return dotdashedStroke;
-            case DOTTED:
-                return dottedStroke;
-            case TWODASH:
-                return twodashedStroke;
-            case LONGDASH:
-                return longdashedStroke;
-            default:
-                throw RInternalError.shouldNotReachHere("unexpected value of GridLineType enum");
+    private static BasicStroke fromGridLineType(byte[] type) {
+        if (type == DrawingContext.GRID_LINE_BLANK) {
+            return blankStroke;
+        } else if (type == DrawingContext.GRID_LINE_SOLID) {
+            return solidStroke;
+        }
+        float[] pattern = new float[type.length];
+        for (int i = 0; i < pattern.length; i++) {
+            pattern[i] = (float) (type[i] / POINTS_IN_INCH);
         }
+        return new BasicStroke((float) (1. / POINTS_IN_INCH), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, pattern, 0f);
     }
 
     private static void initStrokes() {
         if (solidStroke != null) {
             return;
         }
-        float defaultWidth = (float) (1. / POINTS_IN_INCH);
-        float dashSize = (float) (10. / POINTS_IN_INCH);
-        float dotSize = (float) (2. / POINTS_IN_INCH);
         solidStroke = new BasicStroke((float) (1f / POINTS_IN_INCH));
         blankStroke = new BasicStroke(0f);
-        dashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize}, 0f);
-        dottedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dotSize}, 0f);
-        dotdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dotSize, dashSize}, 0f);
-        twodashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{dashSize / 2f, dashSize}, 0f);
-        longdashedStroke = new BasicStroke(defaultWidth, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, new float[]{2f * dashSize}, 0f);
     }
 
     static class FastRFrame extends JFrame {
-- 
GitLab


From dd9691ddb81998fcffd324f895483e4327dad4a5 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 17:13:27 +0100
Subject: [PATCH 177/402] FastR Grid: support gpar containing vectors

---
 .../r/library/fastrGrid/DoSetViewPort.java    | 40 ++++----
 .../r/library/fastrGrid/DrawArrowsNode.java   |  2 +-
 .../truffle/r/library/fastrGrid/GPar.java     | 91 ++++++++++++++-----
 .../r/library/fastrGrid/GridLinesNode.java    |  8 +-
 .../r/library/fastrGrid/GridState.java        |  9 +-
 .../r/library/fastrGrid/GridTextNode.java     |  8 +-
 .../r/library/fastrGrid/GridUtils.java        | 13 +++
 .../truffle/r/library/fastrGrid/LCircle.java  |  7 +-
 .../truffle/r/library/fastrGrid/LConvert.java |  7 +-
 .../library/fastrGrid/LInitViewPortStack.java |  1 -
 .../truffle/r/library/fastrGrid/LPoints.java  | 19 +++-
 .../truffle/r/library/fastrGrid/LRect.java    |  7 +-
 .../r/library/fastrGrid/LSegments.java        |  7 +-
 .../truffle/r/library/fastrGrid/Unit.java     | 26 +++---
 .../device/BufferedJFrameDevice.java          |  2 +-
 .../r/library/fastrGrid/device/GridColor.java |  5 +-
 16 files changed, 155 insertions(+), 97 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 591c4e25f4..3154017025 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -29,7 +29,6 @@ import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -65,11 +64,11 @@ class DoSetViewPort extends RBaseNode {
         }
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
-        DrawingContext deviceDrawingContext = GridState.getInitialGPar(currentDevice);
+        GPar gpar = GridState.getInitialGPar(currentDevice);
 
         RList parent = asListOrNull(pushedViewPort.getDataAt(ViewPort.PVP_PARENT));
         boolean doNotRecalculateParent = hasParent && !ViewPort.updateDeviceSizeInVP(parent, currentDevice);
-        calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, deviceDrawingContext);
+        calcViewportTransform(pushedViewPort, parent, doNotRecalculateParent, currentDevice, gpar);
 
         // TODO: clipping
         pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
@@ -87,37 +86,37 @@ class DoSetViewPort extends RBaseNode {
      * @param incremental If {@code true} it is assumed that we can just take the transformation
      *            matrix and other values from the parent without re-calculating them recursively.
      * @param device This method needs the device in order to convert units
-     * @param deviceDrawingContext This method needs to know the device default drawing context in
+     * @param deviceTopLevelGpar This method needs to know the device default drawing context in
      *            order to convert units for the top level view port
      */
     @TruffleBoundary
-    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, DrawingContext deviceDrawingContext) {
+    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
         Size parentSize;
-        DrawingContext drawingContext;
+        GPar drawingContext;
         double parentAngle;
         if (parent == null || parent == RNull.instance) {
             parentTransform = TransformMatrix.identity();
             parentContext = ViewPortContext.createDefault();
             parentSize = new Size(device.getWidth(), device.getHeight());
             vpl = ViewPortLocation.fromViewPort(viewPort);
-            drawingContext = deviceDrawingContext;
+            drawingContext = deviceTopLevelGpar;
             parentAngle = 0;
         } else {
             assert parent instanceof RList : "inconsistent data: parent of a viewport must be a list";
             RList parentVPList = (RList) parent;
             Object[] parentData = parentVPList.getDataWithoutCopying();
             if (!incremental) {
-                calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceDrawingContext);
+                calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceTopLevelGpar);
             }
             parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
             parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
             parentContext = ViewPortContext.fromViewPort(parentVPList);
             parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]);
 
-            drawingContext = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
+            drawingContext = GPar.create(asList(viewPort.getDataAt(ViewPort.PVP_PARENTGPAR)));
             boolean noLayout = (isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSROW)) && isNull(viewPort.getDataAt(ViewPort.VP_VALIDLPOSCOL))) || isNull(parentData[ViewPort.VP_LAYOUT]);
             if (noLayout) {
                 vpl = ViewPortLocation.fromViewPort(viewPort);
@@ -157,8 +156,7 @@ class DoSetViewPort extends RBaseNode {
         // Finally, allocate the rows and columns for this viewport's layout if it has one
         if (!isNull(viewPort.getDataAt(ViewPort.VP_LAYOUT))) {
             ViewPortContext vpCtx = ViewPortContext.fromViewPort(viewPort);
-            DrawingContext drawingCtx = GPar.asDrawingContext(asList(viewPort.getDataAt(ViewPort.PVP_GPAR)));
-            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, drawingCtx);
+            calcViewPortLayout(viewPort, new Size(width, height), vpCtx, device, GPar.create(asList(viewPort.getDataAt(ViewPort.PVP_GPAR))));
         }
 
         Object[] viewPortData = viewPort.getDataWithoutCopying();
@@ -168,13 +166,13 @@ class DoSetViewPort extends RBaseNode {
         viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
     }
 
-    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx) {
+    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) {
         LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort);
         double[] npcWidths = new double[layoutSize.ncol];
         double[] npcHeights = new double[layoutSize.nrow];
         boolean[] relativeWidths = new boolean[layoutSize.ncol];
         boolean[] relativeHeights = new boolean[layoutSize.nrow];
-        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, device, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(size, parentVPCtx, device, gpar);
 
         // For both dimensions we find out which units are other than "null" for those we can
         // immediately calculate the physical size in npcWidth/npcHeights. The reducedWidth/Height
@@ -195,8 +193,8 @@ class DoSetViewPort extends RBaseNode {
         int respect = RRuntime.asInteger(layoutAsList.getDataAt(ViewPort.LAYOUT_VRESPECT));
         int[] layoutRespectMat = ((RAbstractIntVector) layoutAsList.getDataAt(ViewPort.LAYOUT_MRESPECT)).materialize().getDataWithoutCopying();
         if ((reducedHeight > 0 || reducedWidth > 0) && respect > 0) {
-            double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, drawingCtx, true);
-            double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, drawingCtx, false);
+            double sumRelWidth = sumRelativeDimension(layoutWidths, relativeWidths, parentVPCtx, device, gpar, true);
+            double sumRelHeight = sumRelativeDimension(layoutHeights, relativeHeights, parentVPCtx, device, gpar, false);
             double tempWidth = reducedWidth;
             double tempHeight = reducedHeight;
             double denom;
@@ -250,8 +248,8 @@ class DoSetViewPort extends RBaseNode {
         }
 
         // Secondly, allocate remaining relative widths and heights in the remaining space
-        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, device, drawingCtx, parentVPCtx, true);
-        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, device, drawingCtx, parentVPCtx, false);
+        allocateRelativeDim(layoutSize, layoutWidths, npcWidths, relativeWidths, reducedWidth, respect, layoutRespectMat, device, gpar, parentVPCtx, true);
+        allocateRelativeDim(layoutSize, layoutHeights, npcHeights, relativeHeights, reducedHeight, respect, layoutRespectMat, device, gpar, parentVPCtx, false);
 
         // Create the result
         Object[] vpData = viewPort.getDataWithoutCopying();
@@ -260,9 +258,9 @@ class DoSetViewPort extends RBaseNode {
     }
 
     private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
-                    GridDevice device, DrawingContext drawingCtx, ViewPortContext parentVPCtx, boolean isWidth) {
+                    GridDevice device, GPar gpar, ViewPortContext parentVPCtx, boolean isWidth) {
         assert relativeItems.length == npcItems.length;
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
         double totalUnrespectedSize = 0;
         if (reducedDim > 0) {
             for (int i = 0; i < relativeItems.length; i++) {
@@ -311,9 +309,9 @@ class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, DrawingContext drawingCtx,
+    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar,
                     boolean isWidth) {
-        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, drawingCtx, 1, 0);
+        UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
         double totalWidth = 0;
         for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i]) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
index e177c722b1..cda58b06a3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
@@ -66,7 +66,7 @@ class DrawArrowsNode extends Node {
         arrowLength = Math.max(arrowLength, unitToInches.convertWidth(lengthVec, parentIndex, conversionCtx));
         // draw the arrows
         GridDevice device = conversionCtx.device;
-        DrawingContext drawingCtx = conversionCtx.drawingContext;
+        DrawingContext drawingCtx = conversionCtx.gpar.getDrawingContext(parentIndex);
         if (first && start) {
             drawArrow(drawingCtx, device, arrowType, x[startIndex], y[startIndex], x[startIndex + 1], y[startIndex + 1], angle, arrowLength);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index be7d76d5f9..16288015d9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
 
 import java.util.Arrays;
 
@@ -30,10 +31,20 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * In the context of grid package, GPar is a list that contains the parameters for the drawing, like
- * line style, color, etc. This class wraps the list and provides type-safe access to its elements.
+ * line style, color, etc. This class wraps the list and provides way to convert it to
+ * {@link DrawingContext}. First create instance of {@link GPar} and then use
+ * {@link #getDrawingContext(int)} to get the drawing context. Note that grid's gpar can
+ * theoretically contain vector as the value of some graphical parameters, in such case, when
+ * drawing i-th element, e.g. i-th rectangle in {@link LRect}, we should use i-th (mod length)
+ * element of such vector. Note that this is sort of ignored in layout calculations, where we always
+ * take the first element. In other words, instance of {@link GPar} represents grid's gpar where the
+ * graphical parameter may be vectors, whereas {@link DrawingContext} is flattened view where it is
+ * already determined which index is used to access the vectors.
  */
 public final class GPar {
     private static final int GP_FILL = 0;
@@ -86,6 +97,40 @@ public final class GPar {
                     "fontface"
     };
     private static final RStringVector NAMES_VECTOR = (RStringVector) RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
+    private final RList gpar;
+    // majority of gpar instances contains only scalar values, for those we make sure we do not
+    // create a new drawing context instance for every index.
+    private final boolean singleDrawingCtx;
+    private DrawingContext indexZeroDrawingCtx;
+
+    public GPar(RList gpar, boolean singleDrawingCtx) {
+        this.gpar = gpar;
+        this.gpar.makeSharedPermanent();
+        this.singleDrawingCtx = singleDrawingCtx;
+        indexZeroDrawingCtx = new GParDrawingContext(gpar, 0);
+    }
+
+    public static double getCex(RList gpar) {
+        return asDouble(gpar.getDataAt(GP_CEX));
+    }
+
+    public static GPar create(RList gpar) {
+        boolean singleDrawingCtx = true;
+        for (int i = 0; i < gpar.getLength(); i++) {
+            Object item = gpar.getDataAt(i);
+            if (item instanceof RAbstractVector) {
+                singleDrawingCtx &= ((RAbstractVector) item).getLength() == 1;
+            }
+        }
+        return new GPar(gpar, singleDrawingCtx);
+    }
+
+    public DrawingContext getDrawingContext(int cyclicIndex) {
+        if (singleDrawingCtx || cyclicIndex == 0) {
+            return indexZeroDrawingCtx;
+        }
+        return new GParDrawingContext(gpar, cyclicIndex);
+    }
 
     public static RList createNew(GridDevice device) {
         Object[] data = new Object[GP_LENGTH];
@@ -111,24 +156,17 @@ public final class GPar {
         return result;
     }
 
-    public static double getCex(RList gpar) {
-        return asDouble(gpar.getDataAt(GP_CEX));
-    }
-
-    public static DrawingContext asDrawingContext(RList gpar) {
-        return new GParDrawingContext(gpar);
-    }
-
     private static RAbstractDoubleVector newDoubleVec(double val) {
         return RDataFactory.createDoubleVectorFromScalar(val);
     }
 
     private static final class GParDrawingContext implements DrawingContext {
         private final Object[] data;
+        private final int index;
 
-        private GParDrawingContext(RList list) {
+        private GParDrawingContext(RList list, int index) {
             data = list.getDataWithoutCopying();
-            list.makeSharedPermanent();
+            this.index = index;
         }
 
         @Override
@@ -137,24 +175,27 @@ public final class GPar {
             if (lty == null || lty == RNull.instance) {
                 return DrawingContext.GRID_LINE_SOLID;
             }
-            String name = RRuntime.asString(lty);
-            if (name != null) {
-                return lineTypeFromName(name);
+            // convert string values
+            if (lty instanceof String || lty instanceof RAbstractStringVector) {
+                String name = GridUtils.asString(lty, index);
+                if (name != null) {
+                    return lineTypeFromName(name);
+                }
             }
+            // convert numeric values
             RAbstractContainer ltyVec = asAbstractContainer(lty);
-            int num;
+            int num; // NA will indicate error
             if (ltyVec.getLength() == 0) {
                 num = RRuntime.INT_NA;
             } else if (ltyVec instanceof RAbstractDoubleVector) {
-                double realVal = ((RAbstractDoubleVector) ltyVec).getDataAt(0);
+                double realVal = getDataAtMod((RAbstractDoubleVector) ltyVec, index);
                 num = RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal;
             } else if (ltyVec instanceof RAbstractIntVector) {
-                num = ((RAbstractIntVector) ltyVec).getDataAt(0);
+                num = getDataAtMod((RAbstractIntVector) ltyVec, index);
             } else {
                 num = RRuntime.INT_NA;
             }
-
-            if (RRuntime.isNA(num) || num < LINE_STYLES.length) {
+            if (RRuntime.isNA(num) || num < 0 || num >= LINE_STYLES.length) {
                 throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line type.");
             }
             return LINE_STYLES[num];
@@ -167,22 +208,22 @@ public final class GPar {
 
         @Override
         public double getFontSize() {
-            return asDouble(data[GP_FONTSIZE]) * asDouble(data[GP_CEX]);
+            return asDouble(data[GP_FONTSIZE], index) * asDouble(data[GP_CEX], index);
         }
 
         @Override
         public GridFontStyle getFontStyle() {
-            return GridFontStyle.fromInt(RRuntime.asInteger(data[GP_FONT]));
+            return GridFontStyle.fromInt(GridUtils.asInt(data[GP_FONT], index));
         }
 
         @Override
         public String getFontFamily() {
-            return RRuntime.asString(data[GP_FONTFAMILY]);
+            return GridUtils.asString(data[GP_FONTFAMILY], index);
         }
 
         @Override
         public double getLineHeight() {
-            return asDouble(data[GP_LINEHEIGHT]);
+            return asDouble(data[GP_LINEHEIGHT], index);
         }
 
         @Override
@@ -190,8 +231,8 @@ public final class GPar {
             return getGridColor(GP_FILL);
         }
 
-        private GridColor getGridColor(int index) {
-            return GridColorUtils.gridColorFromString(RRuntime.asString(data[index]));
+        private GridColor getGridColor(int listIndex) {
+            return GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index));
         }
 
         private static final byte[] DASHED_LINE = new byte[]{4, 4};
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 2cceaeb82a..d2bc1d2830 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -51,10 +51,10 @@ public abstract class GridLinesNode extends Node {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         // Convert the list of vectors of indexes to type-safe array and calculate the max length of
         // the vectors.
@@ -67,7 +67,9 @@ public abstract class GridLinesNode extends Node {
 
         double[] xx = new double[maxIndexesLen + 1];    // plus one for polygons
         double[] yy = new double[maxIndexesLen + 1];
-        for (RAbstractIntVector unitIndexes : unitIndexesList) {
+        for (int unitIndexesListIdx = 0; unitIndexesListIdx < unitIndexesList.length; unitIndexesListIdx++) {
+            RAbstractIntVector unitIndexes = unitIndexesList[unitIndexesListIdx];
+            DrawingContext drawingCtx = gpar.getDrawingContext(unitIndexesListIdx);
             boolean oldIsFinite = false;
             int start = 0;
             int unitIndexesLen = unitIndexes.getLength();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index fbedb1f853..6774a7b722 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -11,7 +11,6 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -53,8 +52,12 @@ public final class GridState {
         gpar = GPar.createNew(currentDevice);
     }
 
-    public static DrawingContext getInitialGPar(GridDevice device) {
-        return GPar.asDrawingContext(GPar.createNew(device));
+    /**
+     * Returns something like a canonical gpar, or top level gpar. This is used when we need a
+     * context to do e.g. unit conversion, but we are in a situation that no context is available.
+     */
+    public static GPar getInitialGPar(GridDevice device) {
+        return GPar.create(GPar.createNew(device));
     }
 
     public RList getGpar() {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index b9d862b0fb..594bca1676 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -95,10 +95,10 @@ public final class GridTextNode extends RBaseNode {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, x, y);
 
@@ -131,7 +131,7 @@ public final class GridTextNode extends RBaseNode {
             boolean doDraw = true;
             Rectangle trect = null;
             if (checkOverlap || !draw) {
-                trect = textRect(loc, hjust, vjust, rotation, text, drawingCtx, dev);
+                trect = textRect(loc, hjust, vjust, rotation, text, gpar.getDrawingContext(i), dev);
                 for (int j = 0; j < boundsCount; j++) {
                     if (trect.intersects(bounds[j])) {
                         doDraw = false;
@@ -145,7 +145,7 @@ public final class GridTextNode extends RBaseNode {
 
             // actual drawing
             if (draw && doDraw) {
-                text(loc.x, loc.y, text, hjust, vjust, rotation, drawingCtx, dev);
+                text(loc.x, loc.y, text, hjust, vjust, rotation, gpar.getDrawingContext(i), dev);
             }
 
             // or bounds checking
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index b57eaaa994..8b34ba02b1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 final class GridUtils {
@@ -161,6 +162,18 @@ final class GridUtils {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non integer value " + val.getClass().getSimpleName());
     }
 
+    static String asString(Object val, int cyclicIndex) {
+        if (val instanceof String) {
+            return (String) val;
+        } else if (val instanceof RAbstractStringVector) {
+            RAbstractStringVector vec = (RAbstractStringVector) val;
+            if (vec.getLength() > 0) {
+                return vec.getDataAt(cyclicIndex % vec.getLength());
+            }
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non character value " + val.getClass().getSimpleName());
+    }
+
     static RAbstractIntVector asIntVector(Object value) {
         if (value instanceof Integer) {
             return RDataFactory.createIntVectorFromScalar((Integer) value);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 4d0183bf8f..07ff0d4e40 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -17,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -48,10 +47,10 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
@@ -59,7 +58,7 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
             double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
-            dev.drawCircle(drawingCtx, loc.x, loc.y, radius);
+            dev.drawCircle(gpar.getDrawingContext(i), loc.x, loc.y, radius);
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index b2300de6ab..134def4c4e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -57,10 +56,10 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = unitLength.execute(units);
         double[] result = new double[length];
@@ -94,7 +93,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
                 boolean isX = axisTo.isHorizontal();
                 double scalemin = isX ? vpContext.xscalemin : vpContext.yscalemin;
                 double scalemax = isX ? vpContext.xscalemax : vpContext.yscalemax;
-                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, axisTo.isDimension(), drawingCtx);
+                result[i] = Unit.convertFromInches(inches, unitTo, vpToSize, scalemin, scalemax, axisTo.isDimension(), gpar.getDrawingContext(i));
             }
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
index 82c23f06ae..8a28365fc7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -11,7 +11,6 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 07545f1ba2..d4bd5f8217 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -64,20 +64,22 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        RList gpar = ctx.getGridState().getGpar();
-        DrawingContext drawingCtx = GPar.asDrawingContext(gpar);
-        double cex = GPar.getCex(gpar);
+        RList gparList = ctx.getGridState().getGpar();
+        GPar gpar = GPar.create(gparList);
+        double cex = GPar.getCex(gparList);
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         // Note: unlike in other drawing primitives, we only consider length of x
         int length = unitLength.execute(xVec);
-        PointDrawingContext pointDrawingCtx = new PointDrawingContext(drawingCtx, drawingCtx.getFillColor(), drawingCtx.getFillColor());
+        DrawingContext initialDrawingCtx = gpar.getDrawingContext(0);
+        PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor());
         for (int i = 0; i < length; i++) {
             Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx), vpTransform.transform);
             double size = unitToInches.convertWidth(sizeVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(size)) {
+                pointDrawingCtx = pointDrawingCtx.update(gpar.getDrawingContext(i));
                 pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
             }
         }
@@ -153,6 +155,13 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             return new PointDrawingContext(inner, color, fillColor);
         }
 
+        private PointDrawingContext update(DrawingContext inner) {
+            if (this.inner == inner) {
+                return this;
+            }
+            return new PointDrawingContext(inner, this.color, this.fillColor);
+        }
+
         @Override
         public byte[] getLineType() {
             return inner.getLineType();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index a666b07ede..7c69b09329 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -19,7 +19,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -53,10 +52,10 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
@@ -66,7 +65,7 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
-            dev.drawRect(drawingCtx, loc.x, loc.y, size.getWidth(), size.getHeight());
+            dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight());
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 1a3dda410e..c2e1cf10ba 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -17,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
-import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -59,10 +58,10 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         GridDevice dev = ctx.getCurrentDevice();
 
         RList currentVP = ctx.getGridState().getViewPort();
-        DrawingContext drawingCtx = GPar.asDrawingContext(ctx.getGridState().getGpar());
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
         ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, drawingCtx);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
         double[] xx = new double[2];
@@ -77,7 +76,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
             xx[1] = loc2.x;
             yy[0] = loc1.y;
             yy[1] = loc2.y;
-            dev.drawPolyLines(drawingCtx, xx, yy, 0, 2);
+            dev.drawPolyLines(gpar.getDrawingContext(i), xx, yy, 0, 2);
             if (arrow != null) {
                 drawArrowsNode.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
             }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 4cb343dfbf..3c20956103 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -183,7 +183,7 @@ public class Unit {
         }
     }
 
-    private static double convertToInches(double value, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+    private static double convertToInches(double value, int index, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
         double vpSize = ctx.getViewPortSize(axisOrDim);
         switch (unitId) {
             case INCHES:
@@ -201,16 +201,16 @@ public class Unit {
                 return value / (CM_IN_INCH * 10);
             case CHAR:
             case MYCHAR:
-                return (value * ctx.drawingContext.getFontSize()) / INCH_TO_POINTS_FACTOR;
+                return (value * ctx.gpar.getDrawingContext(index).getFontSize()) / INCH_TO_POINTS_FACTOR;
             case LINES:
             case MYLINES:
-                return (value * ctx.drawingContext.getFontSize() * ctx.drawingContext.getLineHeight()) / INCH_TO_POINTS_FACTOR;
+                return (value * ctx.gpar.getDrawingContext(index).getFontSize() * ctx.gpar.getDrawingContext(index).getLineHeight()) / INCH_TO_POINTS_FACTOR;
             case STRINGWIDTH:
             case MYSTRINGWIDTH:
-                return ctx.device.getStringWidth(ctx.drawingContext, RRuntime.asString(data.getDataAt(0)));
+                return ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), RRuntime.asString(data.getDataAt(0)));
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
-                return ctx.device.getStringHeight(ctx.drawingContext, RRuntime.asString(data.getDataAt(0)));
+                return ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), RRuntime.asString(data.getDataAt(0)));
             case NULL:
                 return evaluateNullUnit(value, vpSize, ctx.nullLayoutMode, ctx.nullArithmeticMode);
             default:
@@ -423,20 +423,20 @@ public class Unit {
     public static final class UnitConversionContext {
         public final Size viewPortSize;
         public final ViewPortContext viewPortContext;
-        public final DrawingContext drawingContext;
+        public final GPar gpar;
         public final GridDevice device;
         public final int nullLayoutMode;
         public final int nullArithmeticMode;
 
-        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, DrawingContext drawingContext) {
-            this(viewPortSize, viewPortContext, device, drawingContext, 0, 0);
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, GPar gpar) {
+            this(viewPortSize, viewPortContext, device, gpar, 0, 0);
         }
 
-        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, DrawingContext drawingContext, int nullLMode, int nullAMode) {
+        public UnitConversionContext(Size viewPortSize, ViewPortContext viewPortContext, GridDevice device, GPar gpar, int nullLMode, int nullAMode) {
             this.viewPortSize = viewPortSize;
             this.viewPortContext = viewPortContext;
             this.device = device;
-            this.drawingContext = drawingContext;
+            this.gpar = gpar;
             this.nullLayoutMode = nullLMode;
             this.nullArithmeticMode = nullAMode;
         }
@@ -495,7 +495,7 @@ public class Unit {
                 RList grobList = asList(value.getAttr(UNIT_ATTR_DATA));
                 return getGrobUnitToInchesNode().execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
             }
-            return convertToInches(scalarValue, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
+            return convertToInches(scalarValue, index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
         }
 
         @Specialization(guards = "isUnitList(value)")
@@ -548,7 +548,7 @@ public class Unit {
 
         // Note the catch: newNullAMode is applied only if the axisOrDim is dimension
         private static UnitConversionContext getNewCtx(UnitConversionContext ctx, AxisOrDimension axisOrDim, int newNullAMode) {
-            return new UnitConversionContext(ctx.viewPortSize, ctx.viewPortContext, ctx.device, ctx.drawingContext, ctx.nullLayoutMode,
+            return new UnitConversionContext(ctx.viewPortSize, ctx.viewPortContext, ctx.device, ctx.gpar, ctx.nullLayoutMode,
                             axisOrDim.isDimension() ? newNullAMode : ctx.nullArithmeticMode);
         }
 
@@ -628,7 +628,7 @@ public class Unit {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
                         result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else {
-                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.asDrawingContext(currentGP));
+                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP));
                         initUnitToInchesNode();
                         if (unitId == GROBWIDTH) {
                             result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
index f85a04b4c4..e36fcac3d7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -30,7 +30,7 @@ import java.util.ArrayList;
  * methods open/draw a 2D graphics buffer, while the buffer is open, any drawing is done in the
  * buffer not on the screen and we also record any drawing code to be able to replay it if the
  * buffer happens to loose contents, which is a possibility mentioned in the documentation. Note: we
- * rely on the fact that {@linkl DrawingContext} is immutable.
+ * rely on the fact that {@link DrawingContext} is immutable.
  */
 public class BufferedJFrameDevice implements GridDevice {
     private final JFrameDevice inner;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
index 4b42cdce8c..6b1c9451bd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
@@ -58,10 +58,7 @@ public class GridColor {
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof GridColor)) {
-            return false;
-        }
-        return value == ((GridColor) obj).value;
+        return obj instanceof GridColor && value == ((GridColor) obj).value;
     }
 
     @Override
-- 
GitLab


From ce2e65be744ba006fa0bd51482e71a200b827c6b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 17:20:01 +0100
Subject: [PATCH 178/402] FastR Grid: support for alpha gpar

---
 .../src/com/oracle/truffle/r/library/fastrGrid/GPar.java | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 16288015d9..227800bae3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -232,7 +232,14 @@ public final class GPar {
         }
 
         private GridColor getGridColor(int listIndex) {
-            return GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index));
+            GridColor color = GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index));
+            double alpha = asDouble(data[GP_ALPHA], index);
+            if (alpha != 1.) {
+                int newAlpha = Math.min(255, (int) (alpha * ((color.getAlpha() / 255.0) * 255)));
+                return new GridColor(color.getRed(), color.getGreen(), color.getBlue(), newAlpha);
+            } else {
+                return color;
+            }
         }
 
         private static final byte[] DASHED_LINE = new byte[]{4, 4};
-- 
GitLab


From 91f81f46b95145417ca62c91b11a21bdba520ca2 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 17:35:04 +0100
Subject: [PATCH 179/402] FastR Grid: support line width

---
 .../com/oracle/truffle/r/library/fastrGrid/GPar.java   |  5 +++++
 .../oracle/truffle/r/library/fastrGrid/LPoints.java    |  5 +++++
 .../r/library/fastrGrid/device/DrawingContext.java     |  5 +++++
 .../r/library/fastrGrid/device/JFrameDevice.java       | 10 ++++++----
 4 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 227800bae3..2cc88aa2fa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -201,6 +201,11 @@ public final class GPar {
             return LINE_STYLES[num];
         }
 
+        @Override
+        public double getLineWidth() {
+            return asDouble(data[GP_LWD], index);
+        }
+
         @Override
         public GridColor getColor() {
             return getGridColor(GP_COL);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index d4bd5f8217..eef994103f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -167,6 +167,11 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             return inner.getLineType();
         }
 
+        @Override
+        public double getLineWidth() {
+            return inner.getLineWidth();
+        }
+
         @Override
         public GridColor getColor() {
             return color;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index 55993db1e7..df49377bc2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -65,6 +65,11 @@ public interface DrawingContext {
      */
     byte[] getLineType();
 
+    /**
+     * Line width in multiplies of what is considered the basic "thin" line for given device.
+     */
+    double getLineWidth();
+
     /**
      * Drawing color of shape borders, lines and text.
      */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 6b012f4492..a8e4b4bb46 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -174,7 +174,7 @@ public class JFrameDevice implements GridDevice {
 
     private void setContext(DrawingContext ctx) {
         graphics.setColor(fromGridColor(ctx.getColor()));
-        graphics.setStroke(fromGridLineType(ctx.getLineType()));
+        graphics.setStroke(getStrokeFromCtx(ctx));
     }
 
     private void setFont(DrawingContext ctx) {
@@ -227,17 +227,19 @@ public class JFrameDevice implements GridDevice {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
 
-    private static BasicStroke fromGridLineType(byte[] type) {
+    private static BasicStroke getStrokeFromCtx(DrawingContext ctx) {
+        byte[] type = ctx.getLineType();
+        double width = ctx.getLineWidth();
         if (type == DrawingContext.GRID_LINE_BLANK) {
             return blankStroke;
         } else if (type == DrawingContext.GRID_LINE_SOLID) {
-            return solidStroke;
+            return width == 1. ? solidStroke : new BasicStroke((float) (width / POINTS_IN_INCH));
         }
         float[] pattern = new float[type.length];
         for (int i = 0; i < pattern.length; i++) {
             pattern[i] = (float) (type[i] / POINTS_IN_INCH);
         }
-        return new BasicStroke((float) (1. / POINTS_IN_INCH), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, pattern, 0f);
+        return new BasicStroke((float) (width / POINTS_IN_INCH), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, pattern, 0f);
     }
 
     private static void initStrokes() {
-- 
GitLab


From 7b9503d67cd0d7860f733d66eed6e7af07318e63 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 23 Mar 2017 17:58:06 +0100
Subject: [PATCH 180/402] FastR Grid: support line join, mitre, end and lex
 (line width multiplier).

---
 .../truffle/r/library/fastrGrid/GPar.java     | 150 ++++++++++++++----
 .../truffle/r/library/fastrGrid/LPoints.java  |  15 ++
 .../fastrGrid/device/DrawingContext.java      |  40 +++++
 .../fastrGrid/device/JFrameDevice.java        |  38 ++++-
 4 files changed, 206 insertions(+), 37 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index 2cc88aa2fa..de1e6a86dd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -11,11 +11,12 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContainer;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asString;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
 
 import java.util.Arrays;
+import java.util.function.Function;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContextDefaults;
@@ -68,12 +69,18 @@ public final class GPar {
      * fontsize*cex*lineheight.
      */
     private static final int GP_LINEHEIGHT = 7;
+    /**
+     * In fact means font style: bold, italic, bolditalic or normal.
+     */
     private static final int GP_FONT = 8;
     private static final int GP_FONTFAMILY = 9;
     private static final int GP_ALPHA = 10;
     private static final int GP_LINEEND = 11;
     private static final int GP_LINEJOIN = 12;
     private static final int GP_LINEMITRE = 13;
+    /**
+     * Multiplier of line width {@link #GP_LWD}.
+     */
     private static final int GP_LEX = 14;
 
     // Note: there is last slot "fontface" which is either unused at all, or only used in R code
@@ -138,14 +145,14 @@ public final class GPar {
         Arrays.fill(data, RNull.instance);
         data[GP_COL] = defaults.color;
         data[GP_FILL] = defaults.fillColor;
-        data[GP_GAMMA] = newDoubleVec(0);
+        data[GP_GAMMA] = newDoubleVec(0);   // Note: we do not use this parameter
         data[GP_LTY] = "solid";
         data[GP_LWD] = newDoubleVec(1);
         data[GP_CEX] = newDoubleVec(1);
         data[GP_FONTSIZE] = newDoubleVec(16);
         data[GP_LINEHEIGHT] = newDoubleVec(1.2);
-        data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);  // TODO: font constants?
-        data[GP_FONTFAMILY] = ""; // means default font (probably)
+        data[GP_FONT] = RDataFactory.createIntVectorFromScalar(1);
+        data[GP_FONTFAMILY] = ""; // means default font
         data[GP_ALPHA] = newDoubleVec(1);
         data[GP_LINEEND] = "round";
         data[GP_LINEJOIN] = "round";
@@ -171,39 +178,31 @@ public final class GPar {
 
         @Override
         public byte[] getLineType() {
-            Object lty = data[GP_LTY];
-            if (lty == null || lty == RNull.instance) {
-                return DrawingContext.GRID_LINE_SOLID;
-            }
-            // convert string values
-            if (lty instanceof String || lty instanceof RAbstractStringVector) {
-                String name = GridUtils.asString(lty, index);
-                if (name != null) {
-                    return lineTypeFromName(name);
-                }
-            }
-            // convert numeric values
-            RAbstractContainer ltyVec = asAbstractContainer(lty);
-            int num; // NA will indicate error
-            if (ltyVec.getLength() == 0) {
-                num = RRuntime.INT_NA;
-            } else if (ltyVec instanceof RAbstractDoubleVector) {
-                double realVal = getDataAtMod((RAbstractDoubleVector) ltyVec, index);
-                num = RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal;
-            } else if (ltyVec instanceof RAbstractIntVector) {
-                num = getDataAtMod((RAbstractIntVector) ltyVec, index);
-            } else {
-                num = RRuntime.INT_NA;
-            }
-            if (RRuntime.isNA(num) || num < 0 || num >= LINE_STYLES.length) {
-                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line type.");
-            }
-            return LINE_STYLES[num];
+            return convertNamedValue(data[GP_LTY], LINE_STYLES.length - 1, "line type", GParDrawingContext::lineTypeFromName, num -> LINE_STYLES[num]);
         }
 
         @Override
         public double getLineWidth() {
-            return asDouble(data[GP_LWD], index);
+            return asDouble(data[GP_LWD], index) * asDouble(data[GP_LEX], index);
+        }
+
+        @Override
+        public GridLineJoin getLineJoin() {
+            return convertNamedValue(data[GP_LINEJOIN], GridLineJoin.LAST_VALUE, "line join", GParDrawingContext::lineJoinFromName, GridLineJoin::fromInt);
+        }
+
+        @Override
+        public GridLineEnd getLineEnd() {
+            return convertNamedValue(data[GP_LINEEND], GridLineEnd.LAST_VALUE, "line end", GParDrawingContext::lineEndFromName, GridLineEnd::fromInt);
+        }
+
+        @Override
+        public double getLineMitre() {
+            double value = asDouble(data[GP_LINEMITRE], index);
+            if (value < 1.) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid line mitre.");
+            }
+            return value;
         }
 
         @Override
@@ -236,6 +235,34 @@ public final class GPar {
             return getGridColor(GP_FILL);
         }
 
+        /**
+         * Converts value to given enum type using either {@code nameMapper} for String values or
+         * {@code valueMapper} for integer value, which is first validated to be greater or equal to
+         * 0 and less or equal to the {@code maxValue} parameter. If {@code nameMapper} returns
+         * {@code null} or integer validation fails, error with given {@code propertyName} in the
+         * message is thrown.
+         */
+        public <T> T convertNamedValue(Object value, int maxValue, String propertyName, Function<String, T> nameMapper, Function<Integer, T> valueMapper) {
+            T result = null;
+            if (isStringValue(value)) {
+                String name = asString(value, index);
+                if (name != null) {
+                    result = nameMapper.apply(name);
+                }
+            } else {
+                int num = getIntAtMod(value, index);
+                if (RRuntime.isNA(num) || num < 0 || num > maxValue) {
+                    result = null;
+                } else {
+                    result = valueMapper.apply(num);
+                }
+            }
+            if (result == null) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid " + propertyName);
+            }
+            return result;
+        }
+
         private GridColor getGridColor(int listIndex) {
             GridColor color = GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index));
             double alpha = asDouble(data[GP_ALPHA], index);
@@ -254,7 +281,7 @@ public final class GPar {
         private static final byte[] TWODASH_LINE = new byte[]{2, 2, 6, 2};
         private static final byte[][] LINE_STYLES = new byte[][]{DrawingContext.GRID_LINE_BLANK, DrawingContext.GRID_LINE_SOLID, DASHED_LINE, DOTTED_LINE, DOTDASH_LINE, LONGDASH_LINE, TWODASH_LINE};
 
-        private byte[] lineTypeFromName(String name) {
+        private static byte[] lineTypeFromName(String name) {
             switch (name) {
                 case "solid":
                     return DrawingContext.GRID_LINE_SOLID;
@@ -275,10 +302,63 @@ public final class GPar {
             for (int i = 0; i < name.length(); i++) {
                 result[i] = (byte) Character.digit(name.charAt(i), 16);
                 if (result[i] == -1) {
-                    throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected line type '" + name + "'.");
+                    return null;
                 }
             }
             return result;
         }
+
+        private static GridLineEnd lineEndFromName(String name) {
+            switch (name) {
+                case "round":
+                    return GridLineEnd.ROUND;
+                case "butt":
+                    return GridLineEnd.BUTT;
+                case "square":
+                    return GridLineEnd.SQUARE;
+                default:
+                    return null;
+            }
+        }
+
+        private static GridLineJoin lineJoinFromName(String name) {
+            switch (name) {
+                case "round":
+                    return GridLineJoin.ROUND;
+                case "mitre":
+                    return GridLineJoin.MITRE;
+                case "bevel":
+                    return GridLineJoin.BEVEL;
+                default:
+                    return null;
+            }
+        }
+
+        private static boolean isStringValue(Object lty) {
+            return lty instanceof String || lty instanceof RAbstractStringVector;
+        }
+
+        // NA indicates error
+        private static int getIntAtMod(Object obj, int index) {
+            if (obj instanceof Integer) {
+                return (int) obj;
+            } else if (obj instanceof Double) {
+                return (int) ((double) obj);
+            } else if (!(obj instanceof RAbstractContainer)) {
+                return RRuntime.INT_NA;
+            }
+
+            RAbstractContainer value = (RAbstractContainer) obj;
+            if (value.getLength() == 0) {
+                return RRuntime.INT_NA;
+            } else if (value instanceof RAbstractDoubleVector) {
+                double realVal = getDataAtMod((RAbstractDoubleVector) value, index);
+                return RRuntime.isNA(realVal) ? RRuntime.INT_NA : (int) realVal;
+            } else if (value instanceof RAbstractIntVector) {
+                return getDataAtMod((RAbstractIntVector) value, index);
+            } else {
+                return RRuntime.INT_NA;
+            }
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index eef994103f..477e1e4993 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -172,6 +172,21 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
             return inner.getLineWidth();
         }
 
+        @Override
+        public GridLineJoin getLineJoin() {
+            return inner.getLineJoin();
+        }
+
+        @Override
+        public GridLineEnd getLineEnd() {
+            return inner.getLineEnd();
+        }
+
+        @Override
+        public double getLineMitre() {
+            return inner.getLineMitre();
+        }
+
         @Override
         public GridColor getColor() {
             return color;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index df49377bc2..2986d9ffba 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -55,6 +55,36 @@ public interface DrawingContext {
         }
     }
 
+    enum GridLineJoin {
+        ROUND,
+        MITRE,
+        BEVEL;
+
+        public static final int LAST_VALUE = BEVEL.ordinal();
+
+        /**
+         * Return enum's value corresponding to R's value.
+         */
+        public static GridLineJoin fromInt(int num) {
+            return values()[num];
+        }
+    }
+
+    enum GridLineEnd {
+        ROUND,
+        BUTT,
+        SQUARE;
+
+        public static final int LAST_VALUE = SQUARE.ordinal();
+
+        /**
+         * Return enum's value corresponding to R's value.
+         */
+        public static GridLineEnd fromInt(int num) {
+            return values()[num];
+        }
+    }
+
     /**
      * Returns either one of the constants {@link #GRID_LINE_BLANK} or {@link #GRID_LINE_SOLID} or
      * an array with a pattern consisting of lengths. Lengths at odd positions are dashes and
@@ -70,6 +100,16 @@ public interface DrawingContext {
      */
     double getLineWidth();
 
+    GridLineJoin getLineJoin();
+
+    GridLineEnd getLineEnd();
+
+    /**
+     * The mitre limit, larger than 1, default is 10. The unit should be interpreted the way as in
+     * {@link #getLineType()}.
+     */
+    double getLineMitre();
+
     /**
      * Drawing color of shape borders, lines and text.
      */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index a8e4b4bb46..b27f820139 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -48,6 +48,8 @@ import javax.swing.JFrame;
 import javax.swing.JPanel;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin;
 import com.oracle.truffle.r.runtime.RInternalError;
 
 public class JFrameDevice implements GridDevice {
@@ -230,16 +232,48 @@ public class JFrameDevice implements GridDevice {
     private static BasicStroke getStrokeFromCtx(DrawingContext ctx) {
         byte[] type = ctx.getLineType();
         double width = ctx.getLineWidth();
+        int lineJoin = fromGridLineJoin(ctx.getLineJoin());
+        float lineMitre = (float) ctx.getLineMitre();
+        int endCap = fromGridLineEnd(ctx.getLineEnd());
         if (type == DrawingContext.GRID_LINE_BLANK) {
             return blankStroke;
         } else if (type == DrawingContext.GRID_LINE_SOLID) {
-            return width == 1. ? solidStroke : new BasicStroke((float) (width / POINTS_IN_INCH));
+            if (width == 1. && solidStroke.getLineJoin() == lineJoin && solidStroke.getMiterLimit() == lineMitre && solidStroke.getEndCap() == endCap) {
+                return solidStroke;
+            }
+            return new BasicStroke((float) (width / POINTS_IN_INCH), endCap, lineJoin, lineMitre);
         }
         float[] pattern = new float[type.length];
         for (int i = 0; i < pattern.length; i++) {
             pattern[i] = (float) (type[i] / POINTS_IN_INCH);
         }
-        return new BasicStroke((float) (width / POINTS_IN_INCH), BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10f, pattern, 0f);
+        return new BasicStroke((float) (width / POINTS_IN_INCH), endCap, lineJoin, lineMitre, pattern, 0f);
+    }
+
+    private static int fromGridLineEnd(GridLineEnd lineEnd) {
+        switch (lineEnd) {
+            case ROUND:
+                return BasicStroke.CAP_ROUND;
+            case BUTT:
+                return BasicStroke.CAP_BUTT;
+            case SQUARE:
+                return BasicStroke.CAP_SQUARE;
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected value of GridLineEnd enum");
+        }
+    }
+
+    private static int fromGridLineJoin(GridLineJoin lineJoin) {
+        switch (lineJoin) {
+            case BEVEL:
+                return BasicStroke.JOIN_BEVEL;
+            case MITRE:
+                return BasicStroke.JOIN_MITER;
+            case ROUND:
+                return BasicStroke.JOIN_ROUND;
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected value of GridLineJoin enum");
+        }
     }
 
     private static void initStrokes() {
-- 
GitLab


From 9210d516873cfa66c2cd1d2ea52d889ac23795a7 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 24 Mar 2017 14:12:00 +0100
Subject: [PATCH 181/402] FastR Grid: distinguish filled polygon and polylines

---
 .../r/library/fastrGrid/GridLinesNode.java    |  2 +-
 .../device/BufferedJFrameDevice.java          |  8 ++++++
 .../library/fastrGrid/device/GridDevice.java  |  9 +++++++
 .../fastrGrid/device/JFrameDevice.java        | 27 ++++++++++++++-----
 4 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index d2bc1d2830..ba1b404e0d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -121,7 +121,7 @@ public abstract class GridLinesNode extends Node {
         void drawPolylines(GridDevice dev, DrawingContext drawingCtx, double[] yy, double[] xx, int start, int length) {
             xx[start + length] = xx[start];
             yy[start + length] = yy[start];
-            dev.drawPolyLines(drawingCtx, xx, yy, start, length + 1);
+            dev.drawPolygon(drawingCtx, xx, yy, start, length + 1);
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
index e36fcac3d7..a1f5bdd4dc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -101,6 +101,14 @@ public class BufferedJFrameDevice implements GridDevice {
         }
     }
 
+    @Override
+    public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        inner.drawPolygon(ctx, x, y, startIndex, length);
+        if (buffer != null) {
+            drawActions.add(() -> inner.drawPolygon(ctx, x, y, startIndex, length));
+        }
+    }
+
     @Override
     public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
         inner.drawCircle(ctx, centerX, centerY, radius);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 91593aebf6..03df48b53f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -54,6 +54,15 @@ public interface GridDevice {
      */
     void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length);
 
+    /**
+     * Version of {@link #drawPolyLines(DrawingContext, double[], double[], int, int)}, which should
+     * fill in the area bounded by the lines. Note that it is responsibility of the caller to
+     * connect the first and the last point if the caller wishes to draw actual polygon.
+     *
+     * @see DrawingContext#getFillColor()
+     */
+    void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length);
+
     void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius);
 
     /**
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index b27f820139..8c826158a6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.library.fastrGrid.device;
 
 import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+import static java.awt.geom.Path2D.WIND_EVEN_ODD;
 
 import java.awt.BasicStroke;
 import java.awt.BorderLayout;
@@ -89,17 +90,18 @@ public class JFrameDevice implements GridDevice {
 
     @Override
     public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
-        assert startIndex >= 0 && startIndex < x.length && startIndex < y.length : "startIndex out of bounds";
-        assert length > 0 && (startIndex + length) <= Math.min(x.length, y.length) : "length out of bounds";
+        Path2D.Double path = getPath2D(x, y, startIndex, length);
         setContext(ctx);
-        Path2D.Double path = new Path2D.Double();
-        path.moveTo(x[startIndex], y[startIndex]);
-        for (int i = startIndex + 1; i < length; i++) {
-            path.lineTo(x[i], y[i]);
-        }
         graphics.draw(path);
     }
 
+    @Override
+    public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        Path2D.Double path = getPath2D(x, y, startIndex, length);
+        setContext(ctx);
+        drawShape(ctx, path);
+    }
+
     @Override
     public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
         setContext(ctx);
@@ -166,6 +168,17 @@ public class JFrameDevice implements GridDevice {
         graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
     }
 
+    private Path2D.Double getPath2D(double[] x, double[] y, int startIndex, int length) {
+        assert startIndex >= 0 && startIndex < x.length && startIndex < y.length : "startIndex out of bounds";
+        assert length > 0 && (startIndex + length) <= Math.min(x.length, y.length) : "length out of bounds";
+        Path2D.Double path = new Path2D.Double(WIND_EVEN_ODD, x.length);
+        path.moveTo(x[startIndex], y[startIndex]);
+        for (int i = startIndex + 1; i < length; i++) {
+            path.lineTo(x[i], y[i]);
+        }
+        return path;
+    }
+
     private void drawShape(DrawingContext drawingCtx, Shape shape) {
         Paint paint = graphics.getPaint();
         graphics.setPaint(fromGridColor(drawingCtx.getFillColor()));
-- 
GitLab


From c2d127f9555aef447d3fe18dd7a0e8289d83df46 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 24 Mar 2017 14:22:56 +0100
Subject: [PATCH 182/402] FastR Grid: code clean-up: final, spelling, supress
 warning for unused parameters.

---
 .../truffle/r/library/fastrGrid/DoSetViewPort.java   |  2 +-
 .../truffle/r/library/fastrGrid/DrawArrowsNode.java  |  2 +-
 .../r/library/fastrGrid/FastRGridExternalLookup.java |  6 +++++-
 .../com/oracle/truffle/r/library/fastrGrid/GPar.java |  2 +-
 .../truffle/r/library/fastrGrid/GridColorUtils.java  |  6 +++++-
 .../r/library/fastrGrid/GridStateGetNode.java        |  2 +-
 .../r/library/fastrGrid/IgnoredGridExternal.java     |  2 +-
 .../truffle/r/library/fastrGrid/LGridDirty.java      |  2 +-
 .../truffle/r/library/fastrGrid/LInitGPar.java       |  2 +-
 .../r/library/fastrGrid/LInitViewPortStack.java      |  2 +-
 .../oracle/truffle/r/library/fastrGrid/LLines.java   |  2 +-
 .../oracle/truffle/r/library/fastrGrid/LNewPage.java |  2 +-
 .../truffle/r/library/fastrGrid/LSegments.java       |  2 +-
 .../truffle/r/library/fastrGrid/RGridCodeCall.java   |  2 +-
 .../com/oracle/truffle/r/library/fastrGrid/Unit.java |  2 +-
 .../oracle/truffle/r/library/fastrGrid/ViewPort.java |  2 +-
 .../r/library/fastrGrid/ViewPortLocation.java        |  2 +-
 .../fastrGrid/device/BufferedJFrameDevice.java       |  2 +-
 .../fastrGrid/device/DrawingContextDefaults.java     |  2 +-
 .../r/library/fastrGrid/device/GridColor.java        |  2 +-
 .../r/library/fastrGrid/device/JFrameDevice.java     | 12 ++++++------
 .../truffle/r/library/fastrGrid/graphics/CPar.java   |  4 ++--
 .../fastrGrid/graphics/RGridGraphicsAdapter.java     |  6 +++++-
 23 files changed, 41 insertions(+), 29 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 3154017025..9d35941ac8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -45,7 +45,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-class DoSetViewPort extends RBaseNode {
+final class DoSetViewPort extends RBaseNode {
     @Child private CastNode castScalarDouble = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
     @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
     @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
index cda58b06a3..656d5fd698 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
@@ -23,7 +23,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
-class DrawArrowsNode extends Node {
+final class DrawArrowsNode extends Node {
     // Structure of an arrow description
     private static final int ARROWANGLE = 0;
     private static final int ARROWLENGTH = 1;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index b2d0f365a4..f77ddeb6c5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -38,7 +38,11 @@ import com.oracle.truffle.r.runtime.data.RNull;
 /**
  * Implements the lookup for externals replaced by the FastR grid package.
  */
-public class FastRGridExternalLookup {
+public final class FastRGridExternalLookup {
+
+    private FastRGridExternalLookup() {
+        // only static members
+    }
 
     public static RExternalBuiltinNode lookupDotExternal(String name) {
         switch (name) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index de1e6a86dd..f826ccd696 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -108,7 +108,7 @@ public final class GPar {
     // majority of gpar instances contains only scalar values, for those we make sure we do not
     // create a new drawing context instance for every index.
     private final boolean singleDrawingCtx;
-    private DrawingContext indexZeroDrawingCtx;
+    private final DrawingContext indexZeroDrawingCtx;
 
     public GPar(RList gpar, boolean singleDrawingCtx) {
         this.gpar = gpar;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
index 1fc036ea84..07a01a98c4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
@@ -18,9 +18,13 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 
-public class GridColorUtils {
+public final class GridColorUtils {
     private static HashMap<String, Object> synonymToColor;
 
+    private GridColorUtils() {
+        // only static members
+    }
+
     /**
      * Converts the representation of color used within R, e.g. as value for
      * {@code gpar(col='value')}, to our internal representation that grid device should understand.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
index 9006431d60..f54af61482 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 /**
  * Gets a specified attribute of current {@link GridState}.
  */
-class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
+final class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
     private final Function<GridState, Object> getter;
 
     static {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
index 9166dac774..37090901e1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
  * A node for externals that we ignore, becuase we do not need to implement them or because they
  * support functionallity we do not implement yet, especially record/replay.
  */
-class IgnoredGridExternal extends RExternalBuiltinNode {
+final class IgnoredGridExternal extends RExternalBuiltinNode {
     private final Object result;
 
     static {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index b385a6091e..2fe0e336c3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -19,7 +19,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-class LGridDirty extends RExternalBuiltinNode {
+final class LGridDirty extends RExternalBuiltinNode {
     @Child private InitViewPortNode initViewPort = new InitViewPortNode();
     private final ConditionProfile initViewPortProfile = ConditionProfile.createCountingProfile();
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
index 152aac26cd..f902ec8d81 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGPar.java
@@ -27,7 +27,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-class LInitGPar extends RExternalBuiltinNode {
+final class LInitGPar extends RExternalBuiltinNode {
     static {
         Casts.noCasts(LInitGPar.class);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
index 8a28365fc7..fd32959d47 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -18,7 +18,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-class LInitViewPortStack extends RExternalBuiltinNode {
+final class LInitViewPortStack extends RExternalBuiltinNode {
     @Child private InitViewPortNode initViewPortNode = new InitViewPortNode();
     static {
         Casts.noCasts(LInitViewPortStack.class);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
index e38149b8f1..a61208b89e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -46,7 +46,7 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, RNull arrowIgnored) {
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") RNull arrowIgnored) {
         gridLinesNode.execute(x, y, lengths, null);
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 19c7bc6bf6..917154715f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -15,7 +15,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-class LNewPage extends RExternalBuiltinNode.Arg0 {
+final class LNewPage extends RExternalBuiltinNode.Arg0 {
     static {
         Casts.noCasts(LNewPage.class);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index c2e1cf10ba..4904a3dd0e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -47,7 +47,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     }
 
     @Specialization
-    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, RNull arrow) {
+    Object doSegments(RAbstractVector x0, RAbstractVector y0, RAbstractVector x1, RAbstractVector y1, @SuppressWarnings("unused") RNull arrow) {
         return doSegments(x0, y0, x1, y1, (RList) null);
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
index 7f6b3f18ea..6ff0c0c5f2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 /**
  * Allows to call arbitrary R function from {@code fastrGrid.R} source.
  */
-class RGridCodeCall extends Node {
+final class RGridCodeCall extends Node {
     private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("<fastrGrid.R tmp frame>");
     @Child private RInternalCodeBuiltinNode child;
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 3c20956103..04165ca174 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -59,7 +59,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * the R code should contain values in centimeters, we convert such values immediatelly once they
  * enter our system.
  */
-public class Unit {
+public final class Unit {
     static final String VALID_UNIT_ATTR = "valid.unit";
 
     public static final int NPC = 0;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 99fdd428d3..2a694a69f9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
  * port. One such list is pushed using {@code pushViewpoint} it is transformed to a 'pushed
  * viewpoint', which is a copy of the original view point and it has some additional attributes.
  */
-class ViewPort {
+final class ViewPort {
     /*
      * Structure of a viewport
      */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
index 2ea1a4d776..cd45334ace 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java
@@ -24,7 +24,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
  * The vectors in this class represent a unit objects, therefore we cannot just have a double value
  * for them. However, the unit object should contain only single value.
  */
-public class ViewPortLocation {
+public final class ViewPortLocation {
     public RAbstractContainer x;
     public RAbstractContainer y;
     public RAbstractContainer width;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
index a1f5bdd4dc..fa8e3a5b6f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -32,7 +32,7 @@ import java.util.ArrayList;
  * buffer happens to loose contents, which is a possibility mentioned in the documentation. Note: we
  * rely on the fact that {@link DrawingContext} is immutable.
  */
-public class BufferedJFrameDevice implements GridDevice {
+public final class BufferedJFrameDevice implements GridDevice {
     private final JFrameDevice inner;
     private BufferStrategy buffer;
     private ArrayList<Runnable> drawActions;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java
index b7043cbcd4..7aa6f3f9b4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContextDefaults.java
@@ -26,7 +26,7 @@ package com.oracle.truffle.r.library.fastrGrid.device;
  * Allows the device to communicate the default values for its initial {@link DrawingContext}. The
  * format of the values is the same as accepted by the {@code gpar()} function in R.
  */
-public class DrawingContextDefaults {
+public final class DrawingContextDefaults {
     public String fillColor = "transparent";
     public String color = "black";
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
index 6b1c9451bd..28abf944f1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
@@ -26,7 +26,7 @@ package com.oracle.truffle.r.library.fastrGrid.device;
  * Simple color representation, so that the device interface does not have to depend on a specific
  * GUI framework.
  */
-public class GridColor {
+public final class GridColor {
     public static final int OPAQUE_ALPHA = 0xff;
     private static final int TRANSPARENT_ALPHA = 0;
     public static final GridColor TRANSPARENT = new GridColor(0, 0, 0, TRANSPARENT_ALPHA);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 8c826158a6..c92cb0558d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -53,7 +53,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin;
 import com.oracle.truffle.r.runtime.RInternalError;
 
-public class JFrameDevice implements GridDevice {
+public final class JFrameDevice implements GridDevice {
     // Grid's coordinate system has origin in left bottom corner and y axis grows from bottom to
     // top. Moreover, the grid system uses inches as units. We use transformation to adjust the java
     // coordinate system to the grid one. However, in the case of text rendering, we cannot simply
@@ -75,7 +75,7 @@ public class JFrameDevice implements GridDevice {
             currentFrame.setVisible(true);
             initGraphics(currentFrame.getGraphics());
         } else {
-            noTranform(() -> {
+            noTransform(() -> {
                 graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
                 return null;
             });
@@ -111,7 +111,7 @@ public class JFrameDevice implements GridDevice {
     @Override
     public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
         setContext(ctx);
-        noTranform(() -> {
+        noTransform(() -> {
             AffineTransform tr = graphics.getTransform();
             tr.translate((float) (leftX * POINTS_IN_INCH), (float) (currentFrame.getContentPane().getHeight() - bottomY * POINTS_IN_INCH));
             tr.rotate(-rotationAnticlockWise);
@@ -135,7 +135,7 @@ public class JFrameDevice implements GridDevice {
     @Override
     public double getStringWidth(DrawingContext ctx, String text) {
         setContext(ctx);
-        return noTranform(() -> {
+        return noTransform(() -> {
             setFont(ctx);
             int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
             return swingUnits / POINTS_IN_INCH;
@@ -145,7 +145,7 @@ public class JFrameDevice implements GridDevice {
     @Override
     public double getStringHeight(DrawingContext ctx, String text) {
         setContext(ctx);
-        return noTranform(() -> {
+        return noTransform(() -> {
             setFont(ctx);
             int swingUnits = graphics.getFont().getSize();
             return swingUnits / POINTS_IN_INCH;
@@ -230,7 +230,7 @@ public class JFrameDevice implements GridDevice {
         }
     }
 
-    private <T> T noTranform(Supplier<T> action) {
+    private <T> T noTransform(Supplier<T> action) {
         AffineTransform transform = graphics.getTransform();
         graphics.setTransform(new AffineTransform());
         T result = action.get();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
index e4b6fd0f7e..39cca90ea1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 
-public class CPar extends RExternalBuiltinNode {
+public final class CPar extends RExternalBuiltinNode {
     static {
         Casts.noCasts(CPar.class);
     }
@@ -69,7 +69,7 @@ public class CPar extends RExternalBuiltinNode {
             case "din":
                 return RDataFactory.createDoubleVector(new double[]{device.getWidth(), device.getHeight()}, RDataFactory.COMPLETE_VECTOR);
             default:
-                throw RError.nyi(RError.NO_CALLER, "C_Par paramter '" + name + "'");
+                throw RError.nyi(RError.NO_CALLER, "C_Par parameter '" + name + "'");
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
index 4d4629bc7f..2bb5adf63c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  * interactive sessions, or some image format device for batch sessions. We should also honor the
  * R_INTERACTIVE_DEVICE and R_DEFAULT_DEVICE environment variables.
  */
-public class RGridGraphicsAdapter {
+public final class RGridGraphicsAdapter {
     private static final String NULL_DEVICE = "null device";
     /**
      * The graphics devices system maintains two variables .Device and .Devices in the base
@@ -50,6 +50,10 @@ public class RGridGraphicsAdapter {
     private static final String DOT_DEVICE = ".Device";
     private static final String DOT_DEVICES = ".Devices";
 
+    private RGridGraphicsAdapter() {
+        // only static members
+    }
+
     public static void initialize() {
         setCurrentDevice(NULL_DEVICE);
         ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
-- 
GitLab


From 6982b42046ec4eb589419cc3fe3cfea705e5dc5c Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 24 Mar 2017 15:48:51 +0100
Subject: [PATCH 183/402] FastR Grid: support view port rotation (rectangles
 and text)

---
 .../truffle/r/library/fastrGrid/GridTextNode.java  |  6 +++---
 .../truffle/r/library/fastrGrid/LPoints.java       |  2 +-
 .../oracle/truffle/r/library/fastrGrid/LRect.java  |  2 +-
 .../r/library/fastrGrid/ViewPortTransform.java     |  5 ++++-
 .../fastrGrid/device/BufferedJFrameDevice.java     |  6 +++---
 .../r/library/fastrGrid/device/GridDevice.java     |  6 +++++-
 .../r/library/fastrGrid/device/JFrameDevice.java   | 14 ++++++++++++--
 7 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 594bca1676..a088244c1b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -145,7 +145,7 @@ public final class GridTextNode extends RBaseNode {
 
             // actual drawing
             if (draw && doDraw) {
-                text(loc.x, loc.y, text, hjust, vjust, rotation, gpar.getDrawingContext(i), dev);
+                text(loc.x, loc.y, text, hjust, vjust, rotation + vpTransform.rotationAngle, gpar.getDrawingContext(i), dev);
             }
 
             // or bounds checking
@@ -210,13 +210,13 @@ public final class GridTextNode extends RBaseNode {
 
     // transcribed from engine.c
 
-    private void text(double x, double y, String text, double xadjIn, double yadj, double rotation, DrawingContext drawingCtx, GridDevice device) {
+    private void text(double x, double y, String text, double xadjIn, double yadj, double rotationDegrees, DrawingContext drawingCtx, GridDevice device) {
         if (!Double.isFinite(yadj)) {
             throw RInternalError.unimplemented("'exact' vertical centering, see engine.c:1700");
         }
         double xadj = Double.isFinite(xadjIn) ? xadjIn : 0.5;
 
-        double radRotation = Math.toRadians(rotation);
+        double radRotation = Math.toRadians(rotationDegrees);
         double cosRot = Math.cos(radRotation);
         double sinRot = Math.sin(radRotation);
         String[] lines = text.split("\n");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 477e1e4993..4931572555 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -130,7 +130,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         if (cex > 0 && yc < 0.5) {
             yc = 0.5;
         }
-        dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc);
+        dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc, 0);
         return drawingCtx;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index 7c69b09329..8fc3969d15 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -65,7 +65,7 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
-            dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight());
+            dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight(), Math.toRadians(vpTransform.rotationAngle));
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
index 0e8ea8aa08..bed955d7f2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -25,7 +25,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
  * Holds the data of a viewport needed to perform transformations.
  */
 public final class ViewPortTransform {
-    private final double rotationAngle;
+    /**
+     * Angle in radians.
+     */
+    public final double rotationAngle;
     public final double[][] transform;
     public final Size size;
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
index fa8e3a5b6f..131165f954 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -86,10 +86,10 @@ public final class BufferedJFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height) {
-        inner.drawRect(ctx, leftX, topY, width, height);
+    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise) {
+        inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise);
         if (buffer != null) {
-            drawActions.add(() -> inner.drawRect(ctx, leftX, topY, width, height));
+            drawActions.add(() -> inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise));
         }
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 03df48b53f..afe759f3f0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -46,7 +46,11 @@ public interface GridDevice {
     default void flush() {
     }
 
-    void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height);
+    /**
+     * Draws a rectangle at given position, the center of the rotation should be the center of the
+     * rectangle. The rotation is given in radians.
+     */
+    void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise);
 
     /**
      * Connects given points with a line, there has to be at least two points in order to actually
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index c92cb0558d..6ee2268766 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -83,9 +83,19 @@ public final class JFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height) {
+    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise) {
         setContext(ctx);
-        drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height));
+        if (rotationAnticlockWise == 0.) {
+            drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height));
+            return;
+        }
+        AffineTransform oldTr = graphics.getTransform();
+        AffineTransform newTr = new AffineTransform(oldTr);
+        newTr.translate(leftX + width / 2, topY + height / 2);
+        newTr.rotate(rotationAnticlockWise);
+        graphics.setTransform(newTr);
+        drawShape(ctx, new Rectangle2D.Double(-(width / 2), -(height / 2), width, height));
+        graphics.setTransform(oldTr);
     }
 
     @Override
-- 
GitLab


From 482fa57046da59b06dc4783fd0095dfa8f973d2c Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 24 Mar 2017 13:24:28 +0100
Subject: [PATCH 184/402] Implemented native function
 "R_new_custom_connection". Added class NativeConnections represented such
 connections and performing native calls for reading and writing. This changes
 make package "curl" working.

---
 .../fficall/src/jni/Connections.c             | 176 +++++++++++-
 com.oracle.truffle.r.native/version.source    |   2 +-
 .../builtin/base/ConnectionFunctions.java     |   3 +-
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  26 +-
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java |   1 +
 .../r/nodes/ffi/TracingUpCallsRFFIImpl.java   |   6 +
 .../r/runtime/conn/ConnectionSupport.java     |  38 ++-
 .../r/runtime/conn/DelegateRConnection.java   |   3 +-
 .../r/runtime/conn/NativeConnections.java     | 250 ++++++++++++++++++
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |   2 +
 .../truffle/r/test/ExpectedTestOutput.test    |   6 +
 .../r/test/library/base/TestConnections.java  |   5 +
 12 files changed, 496 insertions(+), 22 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java

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 8b4fc50ddc..907e9a08e0 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
@@ -33,6 +33,7 @@ static jmethodID getConnClassMethodID;
 static jmethodID getSummaryDescMethodID;
 static jmethodID isSeekableMethodID;
 static jmethodID getOpenModeMethodID;
+static jmethodID newCustomConnectionMethodID;
 
 static jbyteArray wrap(JNIEnv *thisenv, void* buf, size_t n) {
     jbyteArray barr = (*thisenv)->NewByteArray(thisenv, n);
@@ -82,6 +83,9 @@ void init_connections(JNIEnv *env) {
 
 	/* String getOpenModeString(BaseRConnection) */
 	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);
 }
 
 static char *connStringToChars(JNIEnv *env, jstring string) {
@@ -179,7 +183,177 @@ static void init_con(Rconnection new, char *description, int enc,
 }
 
 SEXP R_new_custom_connection(const char *description, const char *mode, const char *class_name, Rconnection *ptr) {
-	return unimplemented("R_new_custom_connection");
+	JNIEnv *thisenv = getEnv();
+	Rconnection new;
+	SEXP ans, class;
+
+	new = (Rconnection) malloc(sizeof(struct Rconn));
+	if (!new)
+		error(_("allocation of %s connection failed"), class_name);
+
+	jstring jsDescription = (*thisenv)->NewStringUTF(thisenv, description);
+	jstring jsMode = (*thisenv)->NewStringUTF(thisenv, mode);
+	jstring jsClassName = (*thisenv)->NewStringUTF(thisenv, class_name);
+	printf("New conn addr = %llx\n", (jlong)new);
+	ans = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, newCustomConnectionMethodID, jsDescription, jsMode, jsClassName, (jlong)new);
+	printf("native fd = %d\n", asInteger(ans));
+	if (ans) {
+
+		new->class = (char *) malloc(strlen(class_name) + 1);
+		if (!new->class) {
+			free(new);
+			error(_("allocation of %s connection failed"), class_name);
+		}
+		strcpy(new->class, class_name);
+		new->description = (char *) malloc(strlen(description) + 1);
+		if (!new->description) {
+			free(new->class);
+			free(new);
+			error(_("allocation of %s connection failed"), class_name);
+		}
+		init_con(new, description, CE_NATIVE, mode);
+		/* all ptrs are init'ed to null_* so no need to repeat that,
+		 but the following two are useful tools which could not be accessed otherwise */
+		// TODO dummy_vfprintf and dummy_fgetc not implemented yet
+//    new->vfprintf = &dummy_vfprintf;
+//    new->fgetc = &dummy_fgetc;
+
+		/* new->blocking = block; */
+		new->encname[0] = 0; /* "" (should have the same effect as "native.enc") */
+		new->ex_ptr = R_MakeExternalPtr(new->id, install("connection"), R_NilValue);
+
+		class = allocVector(STRSXP, 2);
+		SET_STRING_ELT(class, 0, mkChar(class_name));
+		SET_STRING_ELT(class, 1, mkChar("connection"));
+		classgets(ans, class);
+//		setAttrib(ans, R_ConnIdSymbol, new->ex_ptr);
+
+		if (ptr) {
+			ptr[0] = new;
+		}
+	}
+
+	return ans;
+}
+
+/*
+ * The address of the Rconnection struct is passed to Java.
+ * Since down calls can only have Object parameters, we put the address into an int vector.
+ * 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)) {
+		error(_("invalid address object"));
+	}
+
+	// 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;
+}
+
+/*
+ * This function is used as Java down call function to query the value of a connection's flag.
+ * DO NOT CHANGE ITS SIGNATURE !
+ * If changing the signature is unavoidable, adapt it in class 'NativeConnections'.
+ */
+SEXP __GetFlagNativeConnection(SEXP rConnAddrObj, jstring jname) {
+    JNIEnv *thisenv = getEnv();
+	Rconnection con = convertToAddress(rConnAddrObj);
+	const char *name = connStringToChars(thisenv, jname);
+	Rboolean result = 0;
+
+	if(strcmp(name, "text") == 0) {
+		result = con->text;
+	} else if(strcmp(name, "isopen") == 0) {
+		result = con->isopen;
+	}else if(strcmp(name, "incomplete") == 0) {
+		result = con->incomplete;
+	}else if(strcmp(name, "canread") == 0) {
+		result = con->canread;
+	}else if(strcmp(name, "canwrite") == 0) {
+		result = con->canwrite;
+	}else if(strcmp(name, "canseek") == 0) {
+		result = con->canseek;
+	}else if(strcmp(name, "blocking") == 0) {
+		result = con->blocking;
+	}
+	free(name);
+
+	return Rf_ScalarLogical(result);
+}
+
+/*
+ * This function is used as Java down call function to invoke the open function of a natively created connection.
+ * DO NOT CHANGE ITS SIGNATURE !
+ * If changing the signature is unavoidable, adapt it in class 'NativeConnections'.
+ */
+SEXP __OpenNativeConnection(SEXP rConnAddrObj) {
+	Rconnection con = convertToAddress(rConnAddrObj);
+	Rboolean success = con->open(con);
+	return Rf_ScalarLogical(success);
+}
+
+/*
+ * This function is used as Java down call function to invoke the open function of a natively created connection.
+ * DO NOT CHANGE ITS SIGNATURE !
+ * If changing the signature is unavoidable, adapt it in class 'NativeConnections'.
+ */
+SEXP __CloseNativeConnection(SEXP rConnAddrObj) {
+	Rconnection con = convertToAddress(rConnAddrObj);
+	con->close(con);
+	return NULL;
+}
+
+/*
+ * This function is used as Java down call function to invoke the read function of a natively created connection.
+ * DO NOT CHANGE ITS SIGNATURE !
+ * If changing the signature is unavoidable, adapt it in class 'NativeConnections'.
+ */
+SEXP __ReadNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) {
+    JNIEnv *thisenv = getEnv();
+    int n = asInteger(nVec);
+	Rconnection con = convertToAddress(rConnAddrObj);
+	void *tmp_buf = (*thisenv)->GetByteArrayElements(thisenv, bufObj, NULL);
+	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);
+}
+
+/*
+ * This function is used as Java down call function to invoke the write function of a natively created connection.
+ * DO NOT CHANGE ITS SIGNATURE !
+ * If changing the signature is unavoidable, adapt it in class 'NativeConnections'.
+ */
+SEXP __WriteNativeConnection(SEXP rConnAddrObj, jbyteArray bufObj, SEXP nVec) {
+    JNIEnv *thisenv = getEnv();
+    int n = asInteger(nVec);
+	Rconnection con = convertToAddress(rConnAddrObj);
+	void *bytes = (*thisenv)->GetByteArrayElements(thisenv, bufObj, NULL);
+	size_t nwritten = con->write(bytes, 1, n, con);
+	// just release buffer
+	(*thisenv)->ReleaseByteArrayElements(thisenv, bufObj, bytes, JNI_ABORT);
+	return Rf_ScalarInteger(nwritten);
+}
+
+/*
+ * This function is used as Java down call function to invoke the seek function of a natively created connection.
+ * DO NOT CHANGE ITS SIGNATURE !
+ * If changing the signature is unavoidable, adapt it in class 'NativeConnections'.
+ */
+SEXP __SeekNativeConnection(SEXP rConnAddrObj, SEXP whereObj, SEXP originObj, SEXP rwObj) {
+	Rconnection con = convertToAddress(rConnAddrObj);
+    double where = adDouble(whereObj);
+    int origin = asInteger(originObj);
+    int rw = asInteger(rwObj);
+	double oldPos = con->seek(con, where, origin, rw);
+	return Rf_ScalarReal(oldPos);
 }
 
 size_t R_ReadConnection(Rconnection con, void *buf, size_t n) {
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 60d3b2f4a4..b6a7d89c68 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-15
+16
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index e8b5fdc22f..24a803191f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -515,7 +515,7 @@ public abstract class ConnectionFunctions {
             BaseRConnection baseCon = RConnection.fromIndex(object);
             Object[] data = new Object[NAMES.getLength()];
             data[0] = baseCon.getSummaryDescription();
-            data[1] = baseCon.getConnectionClass().getPrintName();
+            data[1] = baseCon.getConnectionClass();
             data[2] = baseCon.getOpenMode().summaryString();
             data[3] = baseCon.getSummaryText();
             data[4] = baseCon.isOpen() ? "opened" : "closed";
@@ -545,7 +545,6 @@ public abstract class ConnectionFunctions {
                 }
                 if (baseConn.isOpen()) {
                     warning(RError.Message.ALREADY_OPEN_CONNECTION);
-                    return RNull.instance;
                 }
                 baseConn.open(open);
             } catch (IOException ex) {
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 f16b3e1726..70bc2ec622 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
@@ -55,6 +55,8 @@ import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.InvalidConnection;
+import com.oracle.truffle.r.runtime.conn.NativeConnections.NativeRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -381,7 +383,10 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             case LGLSXP:
                 return RDataFactory.createLogicalVector(new byte[n], RDataFactory.COMPLETE_VECTOR);
             case STRSXP:
-                return RDataFactory.createStringVector(new String[n], RDataFactory.COMPLETE_VECTOR);
+                // fill list with empty strings
+                String[] data = new String[n];
+                Arrays.fill(data, "");
+                return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
             case CPLXSXP:
                 return RDataFactory.createComplexVector(new double[2 * n], RDataFactory.COMPLETE_VECTOR);
             case RAWSXP:
@@ -437,7 +442,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             case LGLSXP:
                 return RDataFactory.createLogicalVector(new byte[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims);
             case STRSXP:
-                return RDataFactory.createStringVector(new String[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims);
+                String[] data = new String[nrow * ncol];
+                Arrays.fill(data, "");
+                return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR, dims);
             case CPLXSXP:
                 return RDataFactory.createComplexVector(new double[2 * (nrow * ncol)], RDataFactory.COMPLETE_VECTOR, dims);
             default:
@@ -1196,6 +1203,19 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return RASTUtils.createLanguageElement(expr);
     }
 
+    @Override
+    public Object R_new_custom_connection(Object description, Object mode, Object className, long readAddr) {
+        // TODO handle encoding properly !
+        String strDescription = (String) description;
+        String strMode = (String) mode;
+        String strClassName = (String) className;
+        try {
+            return new NativeRConnection(strDescription, strMode, strClassName, readAddr).asVector();
+        } catch (IOException e) {
+            return InvalidConnection.instance.asVector();
+        }
+    }
+
     @Override
     public int R_ReadConnection(int fd, byte[] buf) {
 
@@ -1233,7 +1253,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     @Override
     public String getConnectionClassString(Object x) {
         BaseRConnection conn = guaranteeInstanceOf(x, BaseRConnection.class);
-        return conn.getConnectionClass().getPrintName();
+        return conn.getConnectionClass();
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index 3cb37d4a25..25d2f9f385 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -91,6 +91,7 @@ public enum RFFIUpCallMethod {
     R_isEqual("(object, object) : sint32"),
     R_isGlobal("(object) : sint32"),
     R_lsInternal3("(object, sint32, sint32) : object"),
+    R_new_custom_connection("(string, string, string, object) : object"),
     R_tryEval("(object, object, object) : object"),
     Rf_GetOption1("(object) : object"),
     Rf_PairToVectorList("(object) : object"),
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 c5ec109c8c..7cdfff95c3 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
@@ -741,6 +741,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.R_CHAR(x);
     }
 
+    @Override
+    public Object R_new_custom_connection(Object description, Object mode, Object className, long readAddr) {
+        RFFIUtils.traceUpCall("R_new_custom_connection", description, mode, className, readAddr);
+        return delegate.R_new_custom_connection(description, mode, className, readAddr);
+    }
+
     @Override
     public int R_ReadConnection(int fd, byte[] buf) {
         RFFIUtils.traceUpCall("R_ReadConnection", fd, buf);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 46a93b40dc..825aa4cd44 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -335,7 +335,9 @@ public class ConnectionSupport {
         Internal("internal"),
         PIPE("pipe"),
         FIFO("fifo"),
-        CHANNEL("Java Channel");
+        CHANNEL("Java Channel"),
+        NATIVE("custom"),
+        INVALID("invalid");
 
         private final String printName;
 
@@ -358,7 +360,11 @@ public class ConnectionSupport {
         }
     }
 
-    public static final class InvalidConnection implements RConnection {
+    public static final class InvalidConnection extends BaseRConnection {
+
+        protected InvalidConnection() {
+            super(ConnectionClass.INVALID, null);
+        }
 
         public static final InvalidConnection instance = new InvalidConnection();
 
@@ -395,7 +401,7 @@ public class ConnectionSupport {
         }
 
         @Override
-        public RConnection forceOpen(String modeString) throws IOException {
+        public BaseRConnection forceOpen(String modeString) throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
@@ -470,22 +476,27 @@ public class ConnectionSupport {
         }
 
         @Override
-        public void pushBack(RAbstractStringVector lines, boolean addNewLine) {
+        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
         @Override
-        public long seek(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+        public ByteChannel getChannel() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
         @Override
-        public ByteChannel getChannel() throws IOException {
+        public void truncate() throws IOException {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
 
         @Override
-        public void truncate() throws IOException {
+        protected void createDelegateConnection() throws IOException {
+            throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
+        }
+
+        @Override
+        public String getSummaryDescription() {
             throw RInternalError.shouldNotReachHere("INVALID CONNECTION");
         }
     }
@@ -639,8 +650,8 @@ public class ConnectionSupport {
             this.openMode = mode;
         }
 
-        public final ConnectionClass getConnectionClass() {
-            return conClass;
+        public String getConnectionClass() {
+            return conClass.getPrintName();
         }
 
         /**
@@ -730,11 +741,10 @@ public class ConnectionSupport {
          * This is used exclusively by the {@code open} builtin.
          */
         public void open(String modeString) throws IOException {
-            if (openMode.abstractOpenMode == AbstractOpenMode.Lazy) {
-                // modeString may override the default
-                openMode = new OpenMode(modeString == null ? openMode.modeString : modeString);
+            openMode = new OpenMode(modeString == null ? openMode.modeString : modeString);
+            if (!isOpen()) {
+                createDelegateConnection();
             }
-            createDelegateConnection();
         }
 
         protected void checkOpen() {
@@ -1067,7 +1077,7 @@ public class ConnectionSupport {
         }
 
         public final RAbstractIntVector asVector() {
-            String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass().getPrintName(), "connection"};
+            String[] classes = new String[]{ConnectionSupport.getBaseConnection(this).getConnectionClass(), "connection"};
 
             RAbstractIntVector result = RDataFactory.createIntVector(new int[]{getDescriptor()}, true);
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index e31aaa0bd5..74bc8391a0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -549,7 +549,8 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
 
     @Override
     public int readBin(ByteBuffer buffer) throws IOException {
-        return read(buffer);
+        int read = read(buffer);
+        return read < 0 ? 0 : read;
     }
 
     /**
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
new file mode 100644
index 0000000000..531455c3a2
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
@@ -0,0 +1,250 @@
+package com.oracle.truffle.r.runtime.conn;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+
+/**
+ * Represents a custom connection created in native code and having its own native read and write
+ * functions.
+ */
+public class NativeConnections {
+
+    private static final String OPEN_NATIVE_CONNECTION = "__OpenNativeConnection";
+    private static final String CLOSE_NATIVE_CONNECTION = "__CloseNativeConnection";
+    private static final String READ_NATIVE_CONNECTION = "__ReadNativeConnection";
+    private static final String WRITE_NATIVE_CONNECTION = "__WriteNativeConnection";
+    private static final String GET_FLAG_NATIVE_CONNECTION = "__GetFlagNativeConnection";
+    private static final String SEEK_NATIVE_CONNECTION = "__SeekNativeConnection";
+
+    private static final Map<String, NativeCallInfo> callInfoTable = new HashMap<>(4);
+
+    private static NativeCallInfo getNativeFunctionInfo(String name) {
+        NativeCallInfo nativeCallInfo = callInfoTable.get(name);
+        if (nativeCallInfo == null) {
+            DLLInfo findLibraryContainingSymbol = DLL.findLibraryContainingSymbol(name);
+            SymbolHandle findSymbol = DLL.findSymbol(name, findLibraryContainingSymbol);
+            nativeCallInfo = new NativeCallInfo(name, findSymbol, findLibraryContainingSymbol);
+            callInfoTable.put(name, nativeCallInfo);
+        }
+        return nativeCallInfo;
+    }
+
+    public static class NativeRConnection extends BaseRConnection {
+        private final String customConClass;
+        private final String description;
+        private final long addr;
+
+        public NativeRConnection(String description, String modeString, String customConClass, long addr) throws IOException {
+            super(ConnectionClass.NATIVE, modeString, AbstractOpenMode.Read);
+            this.customConClass = Objects.requireNonNull(customConClass);
+            this.description = Objects.requireNonNull(description);
+            this.addr = addr;
+        }
+
+        @Override
+        protected void createDelegateConnection() throws IOException {
+            DelegateRConnection delegate = null;
+            switch (getOpenMode().abstractOpenMode) {
+                case Read:
+                case ReadBinary:
+                    delegate = new ReadNativeConnection(this);
+                    break;
+                case Write:
+                case WriteBinary:
+                    delegate = new WriteNativeConnection(this);
+                    break;
+            }
+            setDelegate(delegate);
+        }
+
+        @Override
+        public String getSummaryDescription() {
+            return description;
+        }
+
+        @Override
+        public String getConnectionClass() {
+            return customConClass;
+        }
+
+        public long getNativeAddress() {
+            return addr;
+        }
+
+        public boolean getFlag(String name) {
+            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});
+            if (result instanceof RLogicalVector) {
+                return ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE;
+            }
+            throw new RInternalError("could not get value of flag " + name);
+        }
+    }
+
+    static class ReadNativeConnection extends DelegateReadRConnection {
+
+        private final ByteChannel ch;
+
+        protected ReadNativeConnection(NativeRConnection base) throws IOException {
+            super(base, 4096);
+            ch = new NativeChannel(base);
+            NativeConnections.openNative(base.addr);
+        }
+
+        @Override
+        public ByteChannel getChannel() throws IOException {
+            return ch;
+        }
+
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            RDoubleVector where = RDataFactory.createDoubleVectorFromScalar(offset);
+            RIntVector seekCode;
+            switch (seekMode) {
+                case CURRENT:
+                    seekCode = RDataFactory.createIntVectorFromScalar(1);
+                    break;
+                case END:
+                    seekCode = RDataFactory.createIntVectorFromScalar(2);
+                    break;
+                case START:
+                    seekCode = RDataFactory.createIntVectorFromScalar(0);
+                    break;
+                default:
+                    seekCode = RDataFactory.createIntVectorFromScalar(-1);
+                    break;
+            }
+            RIntVector rwCode = RDataFactory.createIntVectorFromScalar(1);
+
+            NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(SEEK_NATIVE_CONNECTION);
+            RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
+            RIntVector addrVec = convertAddrToIntVec(((NativeRConnection) base).addr);
+            Object result = nativeCallTarget.call(ni, new Object[]{addrVec, where, seekCode, rwCode});
+            if (result instanceof RDoubleVector) {
+                return (long) ((RDoubleVector) result).getDataAt(0);
+            }
+            throw RInternalError.shouldNotReachHere("unexpected result type");
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return ((NativeRConnection) base).getFlag("canseek");
+        }
+    }
+
+    static class WriteNativeConnection extends DelegateWriteRConnection {
+
+        private final ByteChannel ch;
+
+        protected WriteNativeConnection(NativeRConnection base) throws IOException {
+            super(base);
+            ch = new NativeChannel(base);
+            NativeConnections.openNative(base.addr);
+        }
+
+        @Override
+        public ByteChannel getChannel() throws IOException {
+            return ch;
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return ((NativeRConnection) base).getFlag("canseek");
+        }
+    }
+
+    private static void openNative(long 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});
+        if (!(result instanceof RLogicalVector && ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE)) {
+            throw new IOException("could not open connection");
+        }
+    }
+
+    private static class NativeChannel implements ByteChannel {
+
+        private final NativeRConnection base;
+
+        public NativeChannel(NativeRConnection base) {
+            this.base = base;
+        }
+
+        @Override
+        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()});
+
+            if (call instanceof RIntVector) {
+                int nread = ((RIntVector) call).getDataAt(0);
+                // update buffer's position !
+                dst.position(nread);
+                return nread;
+            }
+
+            throw RInternalError.shouldNotReachHere("unexpected result type");
+        }
+
+        @Override
+        public boolean isOpen() {
+            return true;
+        }
+
+        @Override
+        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});
+        }
+
+        @Override
+        public int write(ByteBuffer src) throws IOException {
+            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()});
+
+            if (result instanceof RIntVector) {
+                return ((RIntVector) result).getDataAt(0);
+            }
+
+            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 86f784db14..82a1e81ff4 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,6 +254,8 @@ public interface StdUpCallsRFFI {
 
     Object R_CHAR(Object x);
 
+    Object R_new_custom_connection(@RFFICstring Object description, @RFFICstring Object mode, @RFFICstring Object className, long readAddr);
+
     int R_ReadConnection(int fd, byte[] buf);
 
     int R_WriteConnection(int fd, byte[] buf);
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 ec06e4b77c..eeaec0855d 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
@@ -77831,6 +77831,12 @@ In readLines(zz, 2, warn = T, skipNul = F) :
 #{ zz <- file('',"w+b", blocking=T); writeBin(as.raw(c(97,98,99,100,0,101,10,65,66,67,10)), zz, useBytes=T); seek(zz, 0); res <- readLines(zz, 2, warn=T, skipNul=T); close(zz); res }
 [1] "abcde" "ABC"
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testReopen#
+#{ con <- rawConnection(charToRaw('hello\nworld\n')); readLines(con, 1); open(con, 'rb'); bin <- readBin(con, raw(), 999); close(con); rawToChar(bin) }
+[1] "world\n"
+Warning message:
+In open.connection(con, "rb") : connection is already open
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testSeekTextConnection#
 #{ zz <- textConnection("Hello, World!"); res <- isSeekable(zz); close(zz); res }
 [1] FALSE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index d96b63d0c3..7b8806d22c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -176,6 +176,11 @@ public class TestConnections extends TestRBase {
         assertEval("zz <- file('', 'w+'); summary(zz); close(zz)");
     }
 
+    @Test
+    public void testReopen() {
+        assertEval("{ con <- rawConnection(charToRaw('hello\\nworld\\n')); readLines(con, 1); open(con, 'rb'); bin <- readBin(con, raw(), 999); close(con); rawToChar(bin) }");
+    }
+
     @Test
     public void testFileOpenRaw() {
         Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip));
-- 
GitLab


From 390de8c0c265026f6f8e5a5b63d4b4ff83cd1920 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 24 Mar 2017 15:30:49 +0100
Subject: [PATCH 185/402] Fix: Package 'jsonlite' expected CHAR(x) to return
 the same pointer on subsequent calls if x is the same. Now, strings are
 cached.

---
 .../fficall/src/jni/Connections.c             |  17 +-
 .../fficall/src/jni/Rinternals.c              |  23 +--
 .../fficall/src/jni/rffiutils.c               |  35 +++-
 .../fficall/src/jni/rffiutils.h               |   2 +
 .../r/runtime/conn/NativeConnections.java     | 168 +++++++++++++++---
 5 files changed, 180 insertions(+), 65 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 907e9a08e0..5b2f516c15 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
@@ -46,18 +46,14 @@ static jbyteArray wrap(JNIEnv *thisenv, void* buf, size_t n) {
  * Otherwise an error is issued.
  */
 static int getFd(Rconnection con) {
-	if(strstr(con->class, "file") != NULL ) {
-		return *((int*)(con->private));
-	}
-	error(_("cannot get file descriptor for non-file connection"));
-	return -1;
+	return con->id;
 }
 
 /*
  * Sets the file descriptor for the connection.
  */
 static void setFd(Rconnection con, jint fd) {
-	*((int*)(con->private)) = fd;
+	con->id = fd;
 }
 
 
@@ -194,9 +190,7 @@ 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);
-	printf("New conn addr = %llx\n", (jlong)new);
 	ans = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, newCustomConnectionMethodID, jsDescription, jsMode, jsClassName, (jlong)new);
-	printf("native fd = %d\n", asInteger(ans));
 	if (ans) {
 
 		new->class = (char *) malloc(strlen(class_name) + 1);
@@ -421,13 +415,6 @@ Rconnection R_GetConnection(SEXP sConn) {
 	new->class = sConnClass;
 	new->canseek = seekable;
 
-	/* The private field is forbidden to be used by any user. So we can use it to store the file descriptor. However, we should also use Rfileconn in future. */
-	new->private = (void *) malloc(sizeof(int));
-	if (!new->private) {
-		free(new);
-		error(_("allocation of file connection failed"));
-		/* for Solaris 12.5 */new = NULL;
-	}
 	setFd(new, fd);
 
 // TODO implement up-call functions and set them
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 00d867ef64..9efedd0f00 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -87,6 +87,7 @@ jmethodID RAW_MethodID;
 jmethodID INTEGER_MethodID;
 jmethodID REAL_MethodID;
 jmethodID LOGICAL_MethodID;
+jmethodID logNotCharSXPWrapperMethodID;
 static jmethodID STRING_ELT_MethodID;
 static jmethodID VECTOR_ELT_MethodID;
 static jmethodID LENGTH_MethodID;
@@ -104,7 +105,6 @@ static jmethodID TYPEOF_MethodID;
 static jmethodID OBJECT_MethodID;
 static jmethodID DUPLICATE_ATTRIB_MethodID;
 static jmethodID IS_S4_OBJECTMethodID;
-static jmethodID logNotCharSXPWrapperMethodID;
 static jmethodID R_tryEvalMethodID;
 static jmethodID RDEBUGMethodID;
 static jmethodID SET_RDEBUGMethodID;
@@ -137,7 +137,6 @@ static jmethodID Rf_nrowsMethodID;
 static jmethodID Rf_ncolsMethodID;
 
 static jclass CharSXPWrapperClass;
-static jfieldID CharSXPWrapperContentsFieldID;
 jclass JNIUpCallsRFFIImplClass;
 
 jmethodID setCompleteMethodID;
@@ -238,9 +237,6 @@ void init_internals(JNIEnv *env) {
 	R_SetExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrTag", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 	R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProt", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 
-	CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/CharSXPWrapper");
-	CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0);
-
     R_computeIdenticalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_computeIdentical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0);
     Rf_copyListMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyListMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0);
     Rf_copyMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0);
@@ -249,21 +245,9 @@ void init_internals(JNIEnv *env) {
 
     // static JNI-specific methods
 	JNIUpCallsRFFIImplClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl");
-	logNotCharSXPWrapperMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1);
 	restoreHandlerStacksMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1);
     setCompleteMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "setComplete", "(Ljava/lang/Object;Z)V", 1);
-}
-
-static jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) {
-#if VALIDATE_REFS
-	validateRef(thisenv, charsxp, "stringFromCharSXP");
-	if (!(*thisenv)->IsInstanceOf(thisenv, charsxp, CharSXPWrapperClass)) {
-
-	    (*thisenv)->CallStaticVoidMethod(thisenv, JNIUpCallsRFFIImplClass, logNotCharSXPWrapperMethodID, charsxp);
-	    fatalError("only CharSXPWrapper expected in stringFromCharSXP");
-	}
-#endif
-	return (*thisenv)->GetObjectField(thisenv, charsxp, CharSXPWrapperContentsFieldID);
+	logNotCharSXPWrapperMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1);
 }
 
 SEXP Rf_ScalarInteger(int value) {
@@ -1355,8 +1339,7 @@ char *dngettext(const char *domainname, const char *msgid, const char * msgid_pl
 const char *R_CHAR(SEXP charsxp) {
 	TRACE("%s(%p)", charsxp);
 	JNIEnv *thisenv = getEnv();
-	jstring string = stringFromCharSXP(thisenv, charsxp);
-	char *copyChars = (char *) stringToChars(thisenv, string);
+	const char *copyChars = (const char *) getNativeArray(thisenv, charsxp, CHARSXP);
 	TRACE(" %s(%s)\n", copyChars);
 	return copyChars;
 }
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 bec561670d..2e74a0498f 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -26,6 +26,7 @@
 #include <errno.h>
 #include <assert.h>
 
+
 /*
  * All calls pass through one of the call(N) methods in rfficall.c, which carry the JNIEnv value,
  * that needs to be saved for reuse in the many R functions such as Rf_allocVector.
@@ -73,6 +74,9 @@ static int nativeArrayTableLastIndex;
 static int nativeArrayTableLength;
 static void releaseNativeArray(JNIEnv *env, int index);
 
+static jfieldID CharSXPWrapperContentsFieldID;
+extern jmethodID logNotCharSXPWrapperMethodID;
+
 static int isEmbedded = 0;
 void setEmbedded() {
     isEmbedded = 1;
@@ -143,6 +147,9 @@ void init_utils(JNIEnv *env, jobject upCallsInstance) {
     nativeArrayTable = calloc(NATIVE_ARRAY_TABLE_INITIAL_SIZE, sizeof(NativeArrayElem));
     nativeArrayTableLength = NATIVE_ARRAY_TABLE_INITIAL_SIZE;
     nativeArrayTableHwm = 0;
+
+	CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/CharSXPWrapper");
+	CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0);
 }
 
 const char *stringToChars(JNIEnv *jniEnv, jstring string) {
@@ -296,7 +303,7 @@ void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
         }
 
         case LGLSXP: {
-            // Special treatment becuase R FFI wants int* and FastR represents using byte[]
+            // Special treatment because R FFI wants int* and FastR represents using byte[]
             jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x);
             int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
             jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
@@ -311,6 +318,13 @@ void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
             break;
         }
 
+        case CHARSXP: {
+        	jstring string = stringFromCharSXP(thisenv, x);
+        	data = (void *) stringToChars(thisenv, string);
+            jArray = string;
+            break;
+        }
+
         default:
             fatalError("getNativeArray: unexpected type");
 
@@ -369,6 +383,13 @@ static void releaseNativeArray(JNIEnv *env, int i) {
             (*env)->ReleaseByteArrayElements(env, byteArray, (jbyte *)cv.data, 0);
             break;
 
+        }
+
+        case CHARSXP: {
+            jstring string = (jstring) cv.jArray;
+            (*env)->ReleaseStringUTFChars(env, string, (const char *)cv.data);
+            break;
+
         }
         default:
             fatalError("releaseNativeArray type");
@@ -536,3 +557,15 @@ jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char
     }
     return fieldID;
 }
+
+jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) {
+#if VALIDATE_REFS
+	validateRef(thisenv, charsxp, "stringFromCharSXP");
+	if (!(*thisenv)->IsInstanceOf(thisenv, charsxp, CharSXPWrapperClass)) {
+
+	    (*thisenv)->CallStaticVoidMethod(thisenv, JNIUpCallsRFFIImplClass, logNotCharSXPWrapperMethodID, charsxp);
+	    fatalError("only CharSXPWrapper expected in stringFromCharSXP");
+	}
+#endif
+	return (*thisenv)->GetObjectField(thisenv, charsxp, CharSXPWrapperContentsFieldID);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index fbd3a26f1c..2af57ebd82 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -123,8 +123,10 @@ extern FILE *traceFile;
 #define _(Source) (Source)
 
 // convert a string into a char*
+jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp);
 const char *stringToChars(JNIEnv *jniEnv, jstring string);
 
+
 extern jmethodID INTEGER_MethodID;
 extern jmethodID LOGICAL_MethodID;
 extern jmethodID REAL_MethodID;
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 531455c3a2..cb0f5f655d 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
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.conn;
 
 import java.io.IOException;
@@ -13,6 +35,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 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.RIntVector;
@@ -73,6 +96,13 @@ public class NativeConnections {
                 case WriteBinary:
                     delegate = new WriteNativeConnection(this);
                     break;
+                case ReadWrite:
+                case ReadWriteBinary:
+                case ReadWriteTrunc:
+                case ReadWriteTruncBinary:
+                    delegate = new ReadWriteNativeConnection(this);
+                    break;
+
             }
             setDelegate(delegate);
         }
@@ -91,6 +121,16 @@ public class NativeConnections {
             return addr;
         }
 
+        @Override
+        public boolean canRead() {
+            return getFlag("canread");
+        }
+
+        @Override
+        public boolean canWrite() {
+            return getFlag("canwrite");
+        }
+
         public boolean getFlag(String name) {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(GET_FLAG_NATIVE_CONNECTION);
             RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
@@ -104,14 +144,54 @@ public class NativeConnections {
         }
     }
 
+    /**
+     * @param addr Native address of the Rconnection data structure.
+     * @param offset seek offset
+     * @param seekMode seek anchor
+     * @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) {
+        RDoubleVector where = RDataFactory.createDoubleVectorFromScalar(offset);
+        RIntVector seekCode;
+        switch (seekMode) {
+            case CURRENT:
+                seekCode = RDataFactory.createIntVectorFromScalar(1);
+                break;
+            case END:
+                seekCode = RDataFactory.createIntVectorFromScalar(2);
+                break;
+            case START:
+                seekCode = RDataFactory.createIntVectorFromScalar(0);
+                break;
+            default:
+                seekCode = RDataFactory.createIntVectorFromScalar(-1);
+                break;
+        }
+        RIntVector rwCode = RDataFactory.createIntVectorFromScalar(rw);
+
+        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});
+        if (result instanceof RDoubleVector) {
+            return (long) ((RDoubleVector) result).getDataAt(0);
+        }
+        throw RInternalError.shouldNotReachHere("unexpected result type");
+    }
+
     static class ReadNativeConnection extends DelegateReadRConnection {
 
         private final ByteChannel ch;
+        private final boolean seekable;
 
         protected ReadNativeConnection(NativeRConnection base) throws IOException {
             super(base, 4096);
             ch = new NativeChannel(base);
             NativeConnections.openNative(base.addr);
+
+            // In theory, the flag could change any time, but this makes no sense.
+            seekable = base.getFlag("canseek");
         }
 
         @Override
@@ -121,48 +201,60 @@ public class NativeConnections {
 
         @Override
         protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
-            RDoubleVector where = RDataFactory.createDoubleVectorFromScalar(offset);
-            RIntVector seekCode;
-            switch (seekMode) {
-                case CURRENT:
-                    seekCode = RDataFactory.createIntVectorFromScalar(1);
-                    break;
-                case END:
-                    seekCode = RDataFactory.createIntVectorFromScalar(2);
-                    break;
-                case START:
-                    seekCode = RDataFactory.createIntVectorFromScalar(0);
-                    break;
-                default:
-                    seekCode = RDataFactory.createIntVectorFromScalar(-1);
-                    break;
-            }
-            RIntVector rwCode = RDataFactory.createIntVectorFromScalar(1);
-
-            NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(SEEK_NATIVE_CONNECTION);
-            RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
-            RIntVector addrVec = convertAddrToIntVec(((NativeRConnection) base).addr);
-            Object result = nativeCallTarget.call(ni, new Object[]{addrVec, where, seekCode, rwCode});
-            if (result instanceof RDoubleVector) {
-                return (long) ((RDoubleVector) result).getDataAt(0);
-            }
-            throw RInternalError.shouldNotReachHere("unexpected result type");
+            // seek mode read -> rw = 1
+            return seekSingleMode(((NativeRConnection) base).addr, offset, seekMode, 1);
         }
 
         @Override
         public boolean isSeekable() {
-            return ((NativeRConnection) base).getFlag("canseek");
+            return seekable;
         }
     }
 
     static class WriteNativeConnection extends DelegateWriteRConnection {
 
         private final ByteChannel ch;
+        private final boolean seekable;
 
         protected WriteNativeConnection(NativeRConnection base) throws IOException {
             super(base);
             ch = new NativeChannel(base);
             NativeConnections.openNative(base.addr);
+
+            // In theory, the flag could change any time, but this makes no sense.
+            seekable = base.getFlag("canseek");
+        }
+
+        @Override
+        public ByteChannel getChannel() throws IOException {
+            return ch;
+        }
+
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            // seek mode write -> rw = 2
+            return seekSingleMode(((NativeRConnection) base).addr, offset, seekMode, 2);
+        }
+
+        @Override
+        public boolean isSeekable() {
+            return seekable;
+        }
+    }
+
+    static class ReadWriteNativeConnection extends DelegateWriteRConnection {
+
+        private final ByteChannel ch;
+        private final boolean seekable;
+        private int lastSeekMode = 1;
+
+        protected ReadWriteNativeConnection(NativeRConnection base) throws IOException {
+            super(base);
+            ch = new NativeChannel(base);
+            NativeConnections.openNative(base.addr);
+
+            // In theory, the flag could change any time, but this makes no sense.
+            seekable = base.getFlag("canseek");
         }
 
         @Override
@@ -170,9 +262,27 @@ public class NativeConnections {
             return ch;
         }
 
+        @Override
+        protected long seekInternal(long offset, SeekMode seekMode, SeekRWMode seekRWMode) throws IOException {
+            int rwMode;
+            switch (seekRWMode) {
+                case READ:
+                    rwMode = 1;
+                    break;
+                case WRITE:
+                    rwMode = 2;
+                    break;
+                default:
+                    rwMode = lastSeekMode;
+
+            }
+            lastSeekMode = rwMode;
+            return seekSingleMode(((NativeRConnection) base).addr, offset, seekMode, rwMode);
+        }
+
         @Override
         public boolean isSeekable() {
-            return ((NativeRConnection) base).getFlag("canseek");
+            return seekable;
         }
     }
 
@@ -191,7 +301,7 @@ public class NativeConnections {
 
         private final NativeRConnection base;
 
-        public NativeChannel(NativeRConnection base) {
+        NativeChannel(NativeRConnection base) {
             this.base = base;
         }
 
-- 
GitLab


From 101a13b610aa2d72e77ef0086116d30646f8fc37 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 24 Mar 2017 10:42:20 -0700
Subject: [PATCH 186/402] =?UTF-8?q?pkgtest:=20allow=20user=20specified=20r?=
 =?UTF-8?q?epos=20with=20=E2=80=94repos=20arg?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../r/install.packages.R                      | 58 +++++++++++--------
 documentation/dev/testing.md                  |  8 ++-
 2 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/com.oracle.truffle.r.test.packages/r/install.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R
index 798ee89b0e..01facbd88a 100644
--- a/com.oracle.truffle.r.test.packages/r/install.packages.R
+++ b/com.oracle.truffle.r.test.packages/r/install.packages.R
@@ -42,8 +42,10 @@
 
 # BioConductor has it's own install mechanism but it is layered on the CRAN model.
 
-# By default, we use the CRAN mirror specified by --cran-mirror or env var CRAN_MIRROR.
-# If unset, it defaults to "http://cran.cnr.berkeley.edu/"
+# A list of repos can be provided  with the --repos argument, which ia comma separated string of name=value pairs.
+# The names "CRAN", "BIOC" and "FASTR" are understood and have default values.
+# By default, we use the CRAN mirror specified in the --repos argument or env var CRAN_MIRROR.
+# The default value for --repos is "CRAN=http://cran.cnr.berkeley.edu"
 
 # Packages are installed into the directory specified by the --lib arg (or R_LIBS_USER env var)
 
@@ -102,7 +104,8 @@
 args <- commandArgs(TRUE)
 
 usage <- function() {
-	cat(paste("usage: Rscript [--cran-mirror url] ",
+	cat(paste("usage: Rscript ",
+					  "[--repos name=value,...]",
                       "[--verbose | -v] [-V] [--dryrun]",
                       "[--no-install | -n] ",
 				      "[--create-blacklist] [--blacklist-file file] [--ignore-blacklist]",
@@ -258,26 +261,35 @@ set.repos <- function() {
 	# Based on the value of repos.list we set the "repos" option
 	# which is used by available.packages etc.
 	repos <- character()
-	needCran <- F
-	if ("BIOC" %in% repo.list) {
-		# source("http://bioconductor.org/biocLite.R")
-		# repos["BIOC"] <- biocinstallRepos()[1]
-		# above is correct but provokes bug:
-		# Error in read.table():  more columns than column names
-		repos["BIOC"] <- "https://bioconductor.org/packages/3.4/bioc"
-		needCran <- T
-	}
-	if (needCran || "CRAN" %in% repo.list) {
-		# set from the cran-mirror value
-		if (is.na(cran.mirror)) {
-			# not set on command line
-			cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/")
+	for (repo in repo.list) {
+		parts <- strsplit(repo, "=", fixed=T)[[1]]
+		name <- parts[[1]]
+		if (length(parts) > 1) {
+			uri <- parts[[2]]
+		} else {
+			uri <- NA_character_
+		}
+		if (name == "BIOC") {
+			# source("http://bioconductor.org/biocLite.R")
+			# repos["BIOC"] <- biocinstallRepos()[1]
+			# above is correct but provokes bug:
+			# Error in read.table():  more columns than column names
+			repos[["BIOC"]] <- "https://bioconductor.org/packages/3.4/bioc"
+		} else if (name == "CRAN") {
+			if (is.na(uri)) {
+				# not set on command line
+				cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/")
+			} else {
+				cran.mirror <- uri
+			}
+			repos[["CRAN"]] <- cran.mirror
+		} else if (name == "FASTR") {
+			# set the FastR internal repo
+			repos[["FASTR"]] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo"))
+		} else {
+			# User defined
+			repos[[name]] <- uri
 		}
-		repos["CRAN"] <- cran.mirror
-	}
-	if ("FASTR" %in% repo.list) {
-		# set the FastR internal repo
-		repos["FASTR"] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo"))
 	}
 	options(repos = repos)
 }
@@ -833,8 +845,6 @@ parse.args <- function() {
 			initial.blacklist.file <<- get.argvalue()
 		} else if (a == "--repos") {
 			repo.list <<- strsplit(get.argvalue(), ",")[[1]]
-		} else if (a == "--cran-mirror") {
-			cran.mirror <<- get.argvalue()
 		} else if (a == "--random") {
 			random.count <<- as.integer(get.argvalue())
 			if (is.na(random.count)) {
diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index 9d7e514bda..45c3893fa8 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -63,7 +63,7 @@ The command has a rather daunting set of options but, for normal use, most of th
 
 ##### Usage
 
-    mx installpkgs [--repos list] [--cran-mirror url]
+    mx installpkgs [--repos list]
                    [--verbose | -v] [-V]
                    [--dryrun]
                    [--no-install | -n]
@@ -100,7 +100,7 @@ There are many packages that cannot be installed due to either missing functiona
 3. TODO
 
 ##### CRAN Mirror
-Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with the command line argument `--cran-mirror` or the environment variable `CRAN_MIRROR`.  The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. It also implies `CRAN`.
+Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list of `name[=value]` pairs, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with `CRAN=url` or the environment variable `CRAN_MIRROR`.  The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. User defined repos can be specified by `USERNAME=url`. N.B. For file system paths this must be a `file:` URL.
 
 ##### Installation Directory
 The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation (the testing system does not honor the `--lib` argument).
@@ -160,6 +160,10 @@ Testing packages requires that they are first installed, so all of the above is
 
 Install the `A3` package (and its dependents) in `$R_LIBS_USER`, creating the `package.blacklist` file first if it does not exist. The dependents (`xtable`, `pbapply`) will be installed implicitly by the  underlying R install.packages function
 
+    $ mx installpkgs --repos CRAN=file://path-to-local-cran-mirror --pkg-pattern '^A3$'
+
+Similar to above but uses a local CRAN mirror stored in `path-to-local-cran-mirror`.
+
     $ mx installpkgs --install-dependents-first--pkg-pattern '^A3$'
 
 Similar to the above but the dependents of A3 are explicitly installed first. This is equivalent to using `--pkg-filelist` file, where file would contain xtable, pbapply and A3 in that order.
-- 
GitLab


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 187/402] 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


From 7fff661945737238f773fb5ce30ac92413028a36 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 24 Mar 2017 16:30:21 +0100
Subject: [PATCH 188/402] remove RAbstractContainer.getElementClass

---
 .../truffle/r/nodes/builtin/base/Attr.java    |  12 +-
 .../truffle/r/nodes/builtin/base/Format.java  |   4 +-
 .../truffle/r/nodes/builtin/base/Match.java   |  10 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |  92 ++++++-------
 .../r/nodes/builtin/base/UpdateDim.java       |   4 +-
 .../r/nodes/builtin/base/UpdateOldClass.java  |   7 +-
 .../r/nodes/builtin/base/UpdateSubstr.java    |  34 ++---
 .../base/printer/ValuePrinterNode.java        |   5 -
 .../SpecialAttributesFunctions.java           |  17 +--
 .../function/opt/ReuseNonSharedNode.java      |  63 ++++++---
 .../com/oracle/truffle/r/runtime/RError.java  |   1 +
 .../truffle/r/runtime/data/RLanguage.java     |   5 -
 .../truffle/r/runtime/data/RListBase.java     |   7 +-
 .../truffle/r/runtime/data/RPairList.java     |   5 -
 .../truffle/r/runtime/data/RVector.java       |   9 +-
 .../r/runtime/data/closures/RClosures.java    |  35 +++--
 .../data/model/RAbstractComplexVector.java    |   5 -
 .../data/model/RAbstractContainer.java        |   2 -
 .../data/model/RAbstractDoubleVector.java     |   6 -
 .../data/model/RAbstractIntVector.java        |   6 -
 .../data/model/RAbstractListBaseVector.java   |  15 +--
 .../data/model/RAbstractLogicalVector.java    |   6 -
 .../data/model/RAbstractRawVector.java        |   5 -
 .../data/model/RAbstractStringVector.java     |   6 -
 .../truffle/r/test/ExpectedTestOutput.test    | 126 +++++++++++++++++-
 .../builtins/TestBuiltin_substrassign.java    |  24 +++-
 .../builtins/TestBuiltin_substrassign_.java   |  30 -----
 mx.fastr/copyrights/overrides                 |   1 -
 28 files changed, 285 insertions(+), 257 deletions(-)
 delete mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
index e566319c45..4583b8b627 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
@@ -48,12 +48,10 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "attr", kind = PRIMITIVE, parameterNames = {"x", "which", "exact"}, behavior = PURE)
 public abstract class Attr extends RBuiltinNode {
@@ -147,9 +145,13 @@ public abstract class Attr extends RBuiltinNode {
         if (a == RNull.instance) {
             return RNull.instance;
         } else {
-            RAbstractVector rowNames = (RAbstractVector) a;
-            return rowNames.getElementClass() == RInteger.class && rowNames.getLength() == 2 && RRuntime.isNA(((RAbstractIntVector) rowNames).getDataAt(0)) ? RDataFactory.createIntSequence(1, 1,
-                            Math.abs(((RAbstractIntVector) rowNames).getDataAt(1))) : a;
+            if (a instanceof RAbstractIntVector) {
+                RAbstractIntVector rowNames = (RAbstractIntVector) a;
+                if (rowNames.getLength() == 2 && RRuntime.isNA(rowNames.getDataAt(0))) {
+                    return RDataFactory.createIntSequence(1, 1, Math.abs(rowNames.getDataAt(1)));
+                }
+            }
+            return a;
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index 05b94d6661..1ef9642089 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -21,7 +21,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.printer.AnyVectorToStringVectorWriter;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode;
@@ -31,7 +30,6 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -119,7 +117,7 @@ public abstract class Format extends RBuiltinNode {
         assert sciVec.getLength() > 0;
         int tmp = castInteger(sciVec).getDataAt(0);
         int ret;
-        if (sciVec.getElementClass() == RLogical.class) {
+        if (sciVec instanceof RAbstractLogicalVector) {
             if (RRuntime.isNA(tmp)) {
                 ret = tmp;
             } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index 11e4b0d23b..e8ba5a9eed 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -34,7 +34,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -59,6 +58,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
 /*
@@ -158,7 +158,7 @@ public abstract class Match extends RBuiltinNode {
         throw error(MATCH_VECTOR_ARGS);
     }
 
-    protected abstract static class MatchInternalNode extends Node {
+    protected abstract static class MatchInternalNode extends RBaseNode {
 
         private static final int TABLE_SIZE_FACTOR = 10;
 
@@ -467,7 +467,7 @@ public abstract class Match extends RBuiltinNode {
             return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
 
-        @Specialization(guards = "!isStringVectorTable(table)")
+        @Specialization(guards = "!isRAbstractStringVector(table)")
         protected RIntVector match(RAbstractStringVector x, RAbstractVector table, int nomatch) {
             int[] result = initResult(x.getLength(), nomatch);
             boolean matchAll = true;
@@ -523,10 +523,6 @@ public abstract class Match extends RBuiltinNode {
             return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
         }
 
-        protected boolean isStringVectorTable(RAbstractVector table) {
-            return table.getElementClass() == String.class;
-        }
-
         private static int[] initResult(int length, int nomatch) {
             int[] result = new int[length];
             Arrays.fill(result, nomatch);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 9bd7d7eff3..dcc06718fd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -44,16 +44,10 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -506,53 +500,45 @@ public abstract class Scan extends RBuiltinNode {
     }
 
     private static Object extractItem(RAbstractVector what, String buffer, LocalData data) {
-        if (what.getElementClass() == RLogical.class) {
-            if (isNaString(buffer, 0, data)) {
-                return RRuntime.LOGICAL_NA;
-            } else {
-                return RRuntime.string2logicalNoCheck(buffer);
-            }
-        }
-        if (what.getElementClass() == RInteger.class) {
-            if (isNaString(buffer, 0, data)) {
-                return RRuntime.INT_NA;
-            } else {
-                return RRuntime.string2intNoCheck(buffer);
-            }
-        }
-
-        if (what.getElementClass() == RDouble.class) {
-            if (isNaString(buffer, 0, data)) {
-                return RRuntime.DOUBLE_NA;
-            } else {
-                return RRuntime.string2doubleNoCheck(buffer);
-            }
-        }
-
-        if (what.getElementClass() == RComplex.class) {
-            if (isNaString(buffer, 0, data)) {
-                return RRuntime.createComplexNA();
-            } else {
-                return RRuntime.string2complexNoCheck(buffer);
-            }
-        }
-
-        if (what.getElementClass() == RString.class) {
-            if (isNaString(buffer, 1, data)) {
-                return RRuntime.STRING_NA;
-            } else {
-                return buffer;
-            }
-        }
-
-        if (what.getElementClass() == RRaw.class) {
-            if (isNaString(buffer, 0, data)) {
-                return RDataFactory.createRaw((byte) 0);
-            } else {
-                return RRuntime.string2raw(buffer);
-            }
+        switch (what.getRType()) {
+            case Logical:
+                if (isNaString(buffer, 0, data)) {
+                    return RRuntime.LOGICAL_NA;
+                } else {
+                    return RRuntime.string2logicalNoCheck(buffer);
+                }
+            case Integer:
+                if (isNaString(buffer, 0, data)) {
+                    return RRuntime.INT_NA;
+                } else {
+                    return RRuntime.string2intNoCheck(buffer);
+                }
+            case Double:
+                if (isNaString(buffer, 0, data)) {
+                    return RRuntime.DOUBLE_NA;
+                } else {
+                    return RRuntime.string2doubleNoCheck(buffer);
+                }
+            case Complex:
+                if (isNaString(buffer, 0, data)) {
+                    return RRuntime.createComplexNA();
+                } else {
+                    return RRuntime.string2complexNoCheck(buffer);
+                }
+            case Character:
+                if (isNaString(buffer, 1, data)) {
+                    return RRuntime.STRING_NA;
+                } else {
+                    return buffer;
+                }
+            case Raw:
+                if (isNaString(buffer, 0, data)) {
+                    return RDataFactory.createRaw((byte) 0);
+                } else {
+                    return RRuntime.string2raw(buffer);
+                }
+            default:
+                throw RInternalError.shouldNotReachHere();
         }
-
-        throw RInternalError.shouldNotReachHere();
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
index 867c09bfd9..c59b1b8d54 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
@@ -56,7 +56,7 @@ public abstract class UpdateDim extends RBuiltinNode {
 
     @Specialization
     protected RAbstractVector updateDim(RAbstractVector vector, @SuppressWarnings("unused") RNull dimensions) {
-        RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize();
+        RVector<?> result = reuse.execute(vector);
         result.resetDimensions(null);
         return result;
     }
@@ -69,7 +69,7 @@ public abstract class UpdateDim extends RBuiltinNode {
         RIntVector dimensionsMaterialized = dimensions.materialize();
         int[] dimsData = dimensionsMaterialized.getDataCopy();
         RVector.verifyDimensions(vector.getLength(), dimsData, this);
-        RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize();
+        RVector<?> result = reuse.execute(vector);
         removeNames.execute(result);
 
         DynamicObject attrs = result.getAttributes();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index 0ba6831d05..c0286bb860 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -52,7 +51,7 @@ public abstract class UpdateOldClass extends RBuiltinNode {
         Casts.noCasts(UpdateOldClass.class);
     }
 
-    @Specialization(guards = "!isStringVector(className)")
+    @Specialization(guards = "!isRAbstractStringVector(className)")
     protected Object setOldClass(RAbstractContainer arg, RAbstractVector className) {
         if (className.getLength() == 0) {
             return setOldClass(arg, RNull.instance);
@@ -90,8 +89,4 @@ public abstract class UpdateOldClass extends RBuiltinNode {
         setClassAttributeNode.reset(result);
         return result;
     }
-
-    protected boolean isStringVector(RAbstractVector className) {
-        return className.getElementClass() == RString.class;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
index c986eecf12..21a620a4a8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -75,15 +74,18 @@ public abstract class UpdateSubstr extends RBuiltinNode {
         int actualStop = stop;
         if (!rangeOk(x, start, stop)) {
             everSeenIllegalRange.enter();
-            if (start > stop || (start <= 0 && stop <= 0) || (start > x.length() && stop > x.length())) {
+            if (start > x.length()) {
                 return x;
             }
-            if (start <= 0) {
+            if (start < 1) {
                 actualStart = 1;
             }
-            if (stop > x.length()) {
+            if (stop > x.length() || stop < 0) {
                 actualStop = x.length();
             }
+            if (actualStart > actualStop) {
+                return x;
+            }
         }
         int replacementLength = actualStop - (actualStart - 1);
         if (replacementLength > value.length()) {
@@ -116,30 +118,26 @@ public abstract class UpdateSubstr extends RBuiltinNode {
     }
 
     @SuppressWarnings("unused")
-    @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "wrongValue(value)"})
+    @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "!isRAbstractStringVector(value) || value.getLength() == 0"})
     protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RAbstractVector value) {
         CompilerDirectives.transferToInterpreter();
         throw error(RError.Message.INVALID_UNNAMED_VALUE);
     }
 
-    @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "!wrongValue(value)"})
+    @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)", "value.getLength() > 0"})
     @TruffleBoundary
     protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop, RAbstractStringVector value) {
-        int argLength = arg.getLength();
-        String[] res = new String[argLength];
+        String[] res = new String[arg.getLength()];
         na.enable(arg);
         na.enable(start);
         na.enable(stop);
         int startLength = start.getLength();
         int stopLength = stop.getLength();
         int valueLength = value.getLength();
-        int j;
-        int k;
-        int l;
-        for (int i = 0; i < argLength; i++) {
-            j = i % startLength;
-            k = i % stopLength;
-            l = i % valueLength;
+        for (int i = 0; i < res.length; i++) {
+            int j = i % startLength;
+            int k = i % stopLength;
+            int l = i % valueLength;
             res[i] = substr0(arg.getDataAt(i), start.getDataAt(j), stop.getDataAt(k), value.getDataAt(l));
         }
         return RDataFactory.createStringVector(res, na.neverSeenNA());
@@ -156,8 +154,4 @@ public abstract class UpdateSubstr extends RBuiltinNode {
         }
         return false;
     }
-
-    protected boolean wrongValue(RAbstractVector value) {
-        return value.getElementClass() != RString.class || value.getLength() == 0;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index 0282196c31..f1212c7fd3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -514,11 +514,6 @@ public final class ValuePrinterNode extends RBaseNode {
             throw RInternalError.shouldNotReachHere();
         }
 
-        @Override
-        public Class<?> getElementClass() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
         @Override
         public RTypedValue getNonShared() {
             throw RInternalError.shouldNotReachHere();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
index cab5bc6f2b..0cdf97146b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -1063,20 +1062,8 @@ public final class SpecialAttributesFunctions {
                 for (int i = 0; i < classAttr.getLength(); i++) {
                     String attr = classAttr.getDataAt(i);
                     if (RRuntime.CLASS_FACTOR.equals(attr)) {
-                        // TODO: Isn't this redundant when the same operation is done after the
-                        // loop?
-                        if (!initializeAttrs) {
-                            super.setAttrInAttributable(vector, classAttr, nullAttrProfile, attrStorageProfile, xTypeProfile, updateRefCountNode);
-                        }
-                        if (vector.getElementClass() != RInteger.class) {
-                            // N.B. there used to be conversion to integer under certain
-                            // circumstances.
-                            // However, it seems that it was dead/obsolete code so it was removed.
-                            // Notes: this can only happen if the class is set by hand to some
-                            // non-integral vector, i.e. attr(doubles, 'class') <- 'factor'. GnuR
-                            // also
-                            // does not update the 'class' attr with other, possibly
-                            // valid classes when it reaches this error.
+                        if (!(vector instanceof RAbstractIntVector)) {
+                            CompilerDirectives.transferToInterpreter();
                             throw error(RError.Message.ADDING_INVALID_CLASS, "factor");
                         }
                     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
index d1166630d4..09ef7a3fc5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/ReuseNonSharedNode.java
@@ -22,47 +22,74 @@
  */
 package com.oracle.truffle.r.nodes.function.opt;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
+import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * Internal node that should be used whenever you want to alter some data: if the data is shared,
  * then it creates a copy, otherwise it returns the data. It does not increment the reference count
  * of the result in either case, but that is typically handled by write variable node, put container
  * element node or by put attribute node.
+ *
+ * This node also makes sure that the returned value is an actual RVector in which individual
+ * elements can be modified (as opposed to sequences, etc.) by calling materialize.
  */
 public abstract class ReuseNonSharedNode extends Node {
 
+    protected static final int LIMIT = 5;
+
     public static ReuseNonSharedNode create() {
         return ReuseNonSharedNodeGen.create();
     }
 
-    public abstract Object execute(Object value);
-
-    @Specialization(guards = "!value.isShared()")
-    protected RShareable reuseNonShared(RSharingAttributeStorage value) {
-        return value;
-    }
-
-    @Specialization(guards = {"value.isShared()", "value.getClass() == valueClass"})
-    protected RSharingAttributeStorage reuseShared(RSharingAttributeStorage value,
-                    @Cached("value.getClass()") Class<? extends RSharingAttributeStorage> valueClass) {
-        RSharingAttributeStorage res = valueClass.cast(value).copy();
-        assert res.isTemporary();
-        return res;
-    }
+    public abstract RVector<?> execute(RAbstractVector value);
 
-    protected static boolean isRShareable(Object value) {
-        return value instanceof RSharingAttributeStorage;
+    @Specialization(limit = "LIMIT", guards = "value.getClass() == valueClass")
+    protected RVector<?> reuseNonShareable(RAbstractVector value,
+                    @Cached("value.getClass()") Class<? extends RAbstractVector> valueClass,
+                    @Cached("createBinaryProfile()") ConditionProfile isSharedProfile) {
+        RAbstractVector profiledValue = valueClass.cast(value);
+        if (RShareable.class.isAssignableFrom(valueClass)) {
+            RShareable shareable = (RShareable) profiledValue;
+            if (isSharedProfile.profile(shareable.isShared())) {
+                RShareable res = shareable.copy();
+                assert res.isTemporary();
+                return (RVector<?>) res;
+            } else {
+                return (RVector<?>) profiledValue;
+            }
+        } else {
+            RVector<?> res = profiledValue.materialize();
+            assert res.isTemporary();
+            return res;
+        }
     }
 
     @Fallback
-    protected static Object getNonShareable(Object value) {
+    @TruffleBoundary
+    public static RVector<?> reuseSlow(RAbstractVector value) {
         RSharingAttributeStorage.verify(value);
-        return value;
+        if (value instanceof RSharingAttributeStorage) {
+            RShareable shareable = (RShareable) value;
+            if (shareable.isShared()) {
+                RShareable res = shareable.copy();
+                assert res.isTemporary();
+                return (RVector<?>) res;
+            } else {
+                return (RVector<?>) value;
+            }
+        } else {
+            RVector<?> res = value.materialize();
+            assert res.isTemporary();
+            return res;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 38f80bcd6a..ae1752dba7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -865,6 +865,7 @@ public final class RError extends RuntimeException {
         SYMBOL_HAS_REGULAR_BINDING("symbol already has a regular binding"),
         CANNOT_CHANGE_LOCKED_ACTIVE_BINDING("cannot change active binding if binding is locked"),
         NO_BINDING_FOR("no binding for \"%s\""),
+        INVALID_SUBSTRING_ARGS("invalid substring arguments"),
         REPLACING_IN_NON_CHAR_OBJ("replacing substrings in a non-character object");
 
         public final String message;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index a4eb4d6a40..d58525dcf8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -159,11 +159,6 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         throw RInternalError.unimplemented();
     }
 
-    @Override
-    public Class<?> getElementClass() {
-        return RLanguage.class;
-    }
-
     @Override
     public RLanguage materialize() {
         // TODO is copy necessary?
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
index 537d54d730..b4abaf3bbe 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -139,11 +139,6 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
         data[toIndex] = other.getDataAtAsObject(fromIndex);
     }
 
-    @Override
-    public final Class<?> getElementClass() {
-        return Object.class;
-    }
-
     @TruffleBoundary
     public final Object getNameAt(int index) {
         RStringVector names = getNamesFromAttrs();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index 32d4e88818..35f18166cb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -261,11 +261,6 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         throw RInternalError.shouldNotReachHere();
     }
 
-    @Override
-    public Class<?> getElementClass() {
-        return null;
-    }
-
     @Override
     public RSharingAttributeStorage copy() {
         RPairList result = new RPairList();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index e0d3de6980..0b84bc51a2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -513,14 +513,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
             for (int i = 0; i < classAttr.getLength(); i++) {
                 String attr = classAttr.getDataAt(i);
                 if (RRuntime.CLASS_FACTOR.equals(attr)) {
-                    vector.putAttribute(RRuntime.CLASS_ATTR_KEY, classAttr);
-                    if (vector.getElementClass() != RInteger.class) {
-                        // N.B. there used to be conversion to integer under certain circumstances.
-                        // However, it seems that it was dead/obsolete code so it was removed.
-                        // Notes: this can only happen if the class is set by hand to some
-                        // non-integral vector, i.e. attr(doubles, 'class') <- 'factor'. GnuR also
-                        // does not update the 'class' attr with other, possibly
-                        // valid classes when it reaches this error.
+                    if (!(vector instanceof RAbstractIntVector)) {
                         throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor");
                     }
                 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
index 8260e9b21a..d16147af06 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
@@ -22,12 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDouble;
-import com.oracle.truffle.r.runtime.data.RInteger;
-import com.oracle.truffle.r.runtime.data.RLogical;
-import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RString;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -122,19 +117,21 @@ public class RClosures {
         if (levels == null) {
             return new RFactorToStringVectorClosure(factor, null, withNames);
         } else {
-            if (levels.getElementClass() == RInteger.class) {
-                return new RFactorToIntVectorClosure(factor, (RAbstractIntVector) levels, withNames);
-            } else if (levels.getElementClass() == RDouble.class) {
-                return new RFactorToDoubleVectorClosure(factor, (RAbstractDoubleVector) levels, withNames);
-            } else if (levels.getElementClass() == RLogical.class) {
-                return new RFactorToIntVectorClosure(factor, createLogicalToIntVector((RAbstractLogicalVector) levels), withNames);
-            } else if (levels.getElementClass() == RComplex.class) {
-                return new RFactorToComplexVectorClosure(factor, (RAbstractComplexVector) levels, withNames);
-            } else if (levels.getElementClass() == RString.class) {
-                return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames);
-            } else {
-                assert levels.getElementClass() == RRaw.class;
-                return new RFactorToIntVectorClosure(factor, createRawToIntVector((RAbstractRawVector) levels), withNames);
+            switch (levels.getRType()) {
+                case Integer:
+                    return new RFactorToIntVectorClosure(factor, (RAbstractIntVector) levels, withNames);
+                case Double:
+                    return new RFactorToDoubleVectorClosure(factor, (RAbstractDoubleVector) levels, withNames);
+                case Logical:
+                    return new RFactorToIntVectorClosure(factor, createLogicalToIntVector((RAbstractLogicalVector) levels), withNames);
+                case Complex:
+                    return new RFactorToComplexVectorClosure(factor, (RAbstractComplexVector) levels, withNames);
+                case Character:
+                    return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames);
+                case Raw:
+                    return new RFactorToIntVectorClosure(factor, createRawToIntVector((RAbstractRawVector) levels), withNames);
+                default:
+                    throw RInternalError.shouldNotReachHere();
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java
index 3ad93d63f6..b2d9e6cd06 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java
@@ -62,9 +62,4 @@ public interface RAbstractComplexVector extends RAbstractAtomicVector {
     default RType getRType() {
         return RType.Complex;
     }
-
-    @Override
-    default Class<?> getElementClass() {
-        return RComplex.class;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
index f03140b082..5afbae3729 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
@@ -43,8 +43,6 @@ public interface RAbstractContainer extends RAttributable, RTypedValue {
 
     void setDimensions(int[] newDimensions);
 
-    Class<?> getElementClass();
-
     RTypedValue getNonShared();
 
     RAbstractContainer materialize();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java
index 8bfd157307..ab8c782a3f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data.model;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 
 public interface RAbstractDoubleVector extends RAbstractAtomicVector {
@@ -62,9 +61,4 @@ public interface RAbstractDoubleVector extends RAbstractAtomicVector {
     default RType getRType() {
         return RType.Double;
     }
-
-    @Override
-    default Class<?> getElementClass() {
-        return RDouble.class;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java
index bc64990d61..92401aea21 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.data.model;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RInteger;
 
 public interface RAbstractIntVector extends RAbstractAtomicVector {
 
@@ -62,9 +61,4 @@ public interface RAbstractIntVector extends RAbstractAtomicVector {
     default RType getRType() {
         return RType.Integer;
     }
-
-    @Override
-    default Class<?> getElementClass() {
-        return RInteger.class;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java
index edd08c2347..31ceb50816 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListBaseVector.java
@@ -34,18 +34,13 @@ public interface RAbstractListBaseVector extends RAbstractVector {
 
     Object getDataAt(int index);
 
-    @Override
-    default boolean checkCompleteness() {
-        return true;
-    }
-
-    @Override
-    default Class<?> getElementClass() {
-        return Object.class;
-    }
-
     @SuppressWarnings("unused")
     default void setDataAt(Object store, int index, Object value) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    default boolean checkCompleteness() {
+        return true;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java
index abb58b0adb..2a1c503de5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data.model;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 
 public interface RAbstractLogicalVector extends RAbstractAtomicVector {
@@ -62,9 +61,4 @@ public interface RAbstractLogicalVector extends RAbstractAtomicVector {
     default RType getRType() {
         return RType.Logical;
     }
-
-    @Override
-    default Class<?> getElementClass() {
-        return RLogical.class;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java
index 38441f5fb1..202f841cd2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java
@@ -58,9 +58,4 @@ public interface RAbstractRawVector extends RAbstractAtomicVector {
     default RType getRType() {
         return RType.Raw;
     }
-
-    @Override
-    default Class<?> getElementClass() {
-        return RRaw.class;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java
index 032c8bed11..af93f141e0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data.model;
 
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 
 public interface RAbstractStringVector extends RAbstractAtomicVector {
@@ -62,9 +61,4 @@ public interface RAbstractStringVector extends RAbstractAtomicVector {
     default RType getRType() {
         return RType.Character;
     }
-
-    @Override
-    default Class<?> getElementClass() {
-        return RString.class;
-    }
 }
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 ec06e4b77c..b8fb83303e 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
@@ -67557,6 +67557,128 @@ model.frame     predict   residuals
 #argv <- list('> ### R code from vignette source \'parallel.Rnw\'\n> \n> ###################################################\n> ### code chunk number 1: parallel.Rnw:474-475 (eval = FALSE)\n> ###################################################\n> ## library(parallel)\n> \n> \n> ###################################################\n> ### code chunk number 2: parallel.Rnw:500-507 (eval = FALSE)\n> ###################################################\n> ## library(boot)\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## cd4.boot <- boot(cd4, corr, R = 999, sim = \'parametric\',\n> ##                  ran.gen = cd4.rg, mle = cd4.mle)\n> ## boot.ci(cd4.boot,  type = c(\'norm\', \'basic\', \'perc\'),\n> ##         conf = 0.9, h = atanh, hinv = tanh)\n> \n> \n> ###################################################\n> ### code chunk number 3: parallel.Rnw:512-522 (eval = FALSE)\n> ###################################################\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## run1 <- function(...) boot(cd4, corr, R = 500, sim = \'parametric\',\n> ##                            ran.gen = cd4.rg, mle = cd4.mle)\n> ## mc <- 2 # set as appropriate for your hardware\n> ## ## To make this reproducible:\n> ## set.seed(123, \'L\'Ecuyer\')\n> ## cd4.boot <- do.call(c, mclapply(seq_len(mc), run1) )\n> ## boot.ci(cd4.boot,  type = c(\'norm\', \'basic\', \'perc\'),\n> ##         conf = 0.9, h = atanh, hinv = tanh)\n> \n> \n> ###################################################\n> ### code chunk number 4: parallel.Rnw:527-528 (eval = FALSE)\n> ###################################################\n> ## do.call(c, lapply(seq_len(mc), run1))\n> \n> \n> ###################################################\n> ### code chunk number 5: parallel.Rnw:532-547 (eval = FALSE)\n> ###################################################\n> ## run1 <- function(...) {\n> ##    library(boot)\n> ##    cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ##    cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ##    boot(cd4, corr, R = 500, sim = \'parametric\',\n> ##         ran.gen = cd4.rg, mle = cd4.mle)\n> ## }\n> ## cl <- makeCluster(mc)\n> ## ## make this reproducible\n> ## clusterSetRNGStream(cl, 123)\n> ## library(boot) # needed for c() method on master\n> ## cd4.boot <- do.call(c, parLapply(cl, seq_len(mc), run1) )\n> ## boot.ci(cd4.boot,  type = c(\'norm\', \'basic\', \'perc\'),\n> ##         conf = 0.9, h = atanh, hinv = tanh)\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 6: parallel.Rnw:557-570 (eval = FALSE)\n> ###################################################\n> ## cl <- makeCluster(mc)\n> ## cd4.rg <- function(data, mle) MASS::mvrnorm(nrow(data), mle$m, mle$v)\n> ## cd4.mle <- list(m = colMeans(cd4), v = var(cd4))\n> ## clusterExport(cl, c(\'cd4.rg\', \'cd4.mle\'))\n> ## junk <- clusterEvalQ(cl, library(boot)) # discard result\n> ## clusterSetRNGStream(cl, 123)\n> ## res <- clusterEvalQ(cl, boot(cd4, corr, R = 500,\n> ##                     sim = \'parametric\', ran.gen = cd4.rg, mle = cd4.mle))\n> ## library(boot) # needed for c() method on master\n> ## cd4.boot <- do.call(c, res)\n> ## boot.ci(cd4.boot,  type = c(\'norm\', \'basic\', \'perc\'),\n> ##         conf = 0.9, h = atanh, hinv = tanh)\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 7: parallel.Rnw:575-589 (eval = FALSE)\n> ###################################################\n> ## R <- 999; M <- 999 ## we would like at least 999 each\n> ## cd4.nest <- boot(cd4, nested.corr, R=R, stype=\'w\', t0=corr(cd4), M=M)\n> ## ## nested.corr is a function in package boot\n> ## op <- par(pty = \'s\', xaxs = \'i\', yaxs = \'i\')\n> ## qqplot((1:R)/(R+1), cd4.nest$t[, 2], pch = \'.\', asp = 1,\n> ##         xlab = \'nominal\', ylab = \'estimated\')\n> ## abline(a = 0, b = 1, col = \'grey\')\n> ## abline(h = 0.05, col = \'grey\')\n> ## abline(h = 0.95, col = \'grey\')\n> ## par(op)\n> ## \n> ## nominal <- (1:R)/(R+1)\n> ## actual <- cd4.nest$t[, 2]\n> ## 100*nominal[c(sum(actual <= 0.05), sum(actual < 0.95))]\n> \n> \n> ###################################################\n> ### code chunk number 8: parallel.Rnw:594-602 (eval = FALSE)\n> ###################################################\n> ## mc <- 9\n> ## R <- 999; M <- 999; RR <- floor(R/mc)\n> ## run2 <- function(...)\n> ##     cd4.nest <- boot(cd4, nested.corr, R=RR, stype=\'w\', t0=corr(cd4), M=M)\n> ## cd4.nest <- do.call(c, mclapply(seq_len(mc), run2, mc.cores = mc) )\n> ## nominal <- (1:R)/(R+1)\n> ## actual <- cd4.nest$t[, 2]\n> ## 100*nominal[c(sum(actual <= 0.05), sum(actual < 0.95))]\n> \n> \n> ###################################################\n> ### code chunk number 9: parallel.Rnw:616-627 (eval = FALSE)\n> ###################################################\n> ## library(spatial)\n> ## towns <- ppinit(\'towns.dat\')\n> ## tget <- function(x, r=3.5) sum(dist(cbind(x$x, x$y)) < r)\n> ## t0 <- tget(towns)\n> ## R <- 1000\n> ## c <- seq(0, 1, 0.1)\n> ## ## res[1] = 0\n> ## res <- c(0, sapply(c[-1], function(c)\n> ##     mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))))\n> ## plot(c, res, type=\'l\', ylab=\'E t\')\n> ## abline(h=t0, col=\'grey\')\n> \n> \n> ###################################################\n> ### code chunk number 10: parallel.Rnw:631-640 (eval = FALSE)\n> ###################################################\n> ## run3 <- function(c) {\n> ##     library(spatial)\n> ##     towns <- ppinit(\'towns.dat\') # has side effects\n> ##     mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))\n> ## }\n> ## cl <- makeCluster(10, methods = FALSE)\n> ## clusterExport(cl, c(\'R\', \'towns\', \'tget\'))\n> ## res <- c(0, parSapply(cl, c[-1], run3)) # 10 tasks\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 11: parallel.Rnw:644-648 (eval = FALSE)\n> ###################################################\n> ## cl <- makeForkCluster(10)  # fork after the variables have been set up\n> ## run4 <- function(c)  mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))\n> ## res <- c(0, parSapply(cl, c[-1], run4))\n> ## stopCluster(cl)\n> \n> \n> ###################################################\n> ### code chunk number 12: parallel.Rnw:651-653 (eval = FALSE)\n> ###################################################\n> ## run4 <- function(c)  mean(replicate(R, tget(Strauss(69, c=c, r=3.5))))\n> ## res <- c(0, unlist(mclapply(c[-1], run4, mc.cores = 10)))\n> \n> \n> ###################################################\n> ### code chunk number 13: parallel.Rnw:684-718 (eval = FALSE)\n> ###################################################\n> ## pkgs <- \'<names of packages to be installed>\'\n> ## M <- 20 # number of parallel installs\n> ## M <- min(M, length(pkgs))\n> ## library(parallel)\n> ## unlink(\'install_log\')\n> ## cl <- makeCluster(M, outfile = \'install_log\')\n> ## clusterExport(cl, c(\'tars\', \'fakes\', \'gcc\')) # variables needed by do_one\n> ## \n> ## ## set up available via a call to available.packages() for\n> ## ## repositories containing all the packages involved and all their\n> ## ## dependencies.\n> ## DL <- utils:::.make_dependency_list(pkgs, available, recursive = TRUE)\n> ## DL <- lapply(DL, function(x) x[x %in% pkgs])\n> ## lens <- sapply(DL, length)\n> ## ready <- names(DL[lens == 0L])\n> ## done <- character() # packages already installed\n> ## n <- length(ready)\n> ## submit <- function(node, pkg)\n> ##     parallel:::sendCall(cl[[node]], do_one, list(pkg), tag = pkg)\n> ## for (i in 1:min(n, M)) submit(i, ready[i])\n> ## DL <- DL[!names(DL) %in% ready[1:min(n, M)]]\n> ## av <- if(n < M) (n+1L):M else integer() # available workers\n> ## while(length(done) < length(pkgs)) {\n> ##     d <- parallel:::recvOneResult(cl)\n> ##     av <- c(av, d$node)\n> ##     done <- c(done, d$tag)\n> ##     OK <- unlist(lapply(DL, function(x) all(x %in% done) ))\n> ##     if (!any(OK)) next\n> ##     p <- names(DL)[OK]\n> ##     m <- min(length(p), length(av)) # >= 1\n> ##     for (i in 1:m) submit(av[i], p[i])\n> ##     av <- av[-(1:m)]\n> ##     DL <- DL[!names(DL) %in% p[1:m]]\n> ## }\n> \n> \n> ###################################################\n> ### code chunk number 14: parallel.Rnw:731-748 (eval = FALSE)\n> ###################################################\n> ##     fn <- function(r) statistic(data, i[r, ], ...)\n> ##     RR <- sum(R)\n> ##     res <- if (ncpus > 1L && (have_mc || have_snow)) {\n> ##         if (have_mc) {\n> ##             parallel::mclapply(seq_len(RR), fn, mc.cores = ncpus)\n> ##         } else if (have_snow) {\n> ##             list(...) # evaluate any promises\n> ##             if (is.null(cl)) {\n> ##                 cl <- parallel::makePSOCKcluster(rep(\'localhost\', ncpus))\n> ##                 if(RNGkind()[1L] == \'L\'Ecuyer-CMRG\')\n> ##                     parallel::clusterSetRNGStream(cl)\n> ##                 res <- parallel::parLapply(cl, seq_len(RR), fn)\n> ##                 parallel::stopCluster(cl)\n> ##                 res\n> ##             } else parallel::parLapply(cl, seq_len(RR), fn)\n> ##         }\n> ##     } else lapply(seq_len(RR), fn)\n> \n> \n> ###################################################\n> ### code chunk number 15: parallel.Rnw:751-752 (eval = FALSE)\n> ###################################################\n> ##             list(...) # evaluate any promises\n> \n> ', 1L, 150L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
 [1] "> ### R code from vignette source 'parallel.Rnw'\n> \n> ###################################################\n> ### code chunk number 1: parallel.Rnw:474-"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -1L, -1L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -1L, -2L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -1L, 0L, 'xyz')
+[1] "ffff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -1L, 1L, 'xyz')
+[1] "xfff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -1L, 2L, 'xyz')
+[1] "xyff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -2L, -1L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -2L, -2L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -2L, 0L, 'xyz')
+[1] "ffff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -2L, 1L, 'xyz')
+[1] "xfff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', -2L, 2L, 'xyz')
+[1] "xyff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 0L, -1L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 0L, -2L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 0L, 0L, 'xyz')
+[1] "ffff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 0L, 1L, 'xyz')
+[1] "xfff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 0L, 2L, 'xyz')
+[1] "xyff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 1L, -1L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 1L, -2L, 'xyz')
+[1] "xyzf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 1L, 0L, 'xyz')
+[1] "ffff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 1L, 1L, 'xyz')
+[1] "xfff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 1L, 2L, 'xyz')
+[1] "xyff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 2L, -1L, 'xyz')
+[1] "fxyz"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 2L, -2L, 'xyz')
+[1] "fxyz"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 2L, 0L, 'xyz')
+[1] "ffff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 2L, 1L, 'xyz')
+[1] "ffff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`('ffff', 2L, 2L, 'xyz')
+[1] "fxff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, 1)
+Error in `substr<-`(c("asdfasdf", "jfjfjf", "ffff"), 2, 5, 1) :
+  invalid value
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, NULL)
+Error in `substr<-`(c("asdfasdf", "jfjfjf", "ffff"), 2, 5, NULL) :
+  invalid value
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, c('a', 'asdf'))
+[1] "aadfasdf" "jasdff"   "faff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, c(5,15,-6), c('a', 'asdf'))
+[1] "aadfasdf" "jasdff"   "faff"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign#
+#`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), c(1,10,-6), 5, c('a', 'asdf'))
+[1] "asdfasdf" "jfjfjf"   "afff"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign1#
 #argv <- list('(0,5]', 1L, 1L, '['); .Internal(`substr<-`(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] "[0,5]"
@@ -67566,11 +67688,11 @@ model.frame     predict   residuals
 [1] "a..ef"           "q+++ty"          "y..op["          "b"
 [5] "s..ff.blah.yech"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign_.testsubstrassign_1#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign_1#
 #argv <- structure(list(x = c('NA', NA, 'BANANA'), start = 1,     stop = 2, value = 'na'), .Names = c('x', 'start', 'stop',     'value'));do.call('substr<-', argv)
 [1] "na"     NA       "naNANA"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign_.testsubstrassign_2#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substrassign.testsubstrassign_2#
 #argv <- structure(list(x = 'abcde', start = NA, stop = 3, value = 'abc'),     .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)
 [1] NA
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java
index a0a36c9829..a5e1bdc822 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -26,4 +26,26 @@ public class TestBuiltin_substrassign extends TestBase {
     public void testsubstrassign2() {
         assertEval("argv <- list(c('asfef', 'qwerty', 'yuiop[', 'b', 'stuff.blah.yech'), 2L, 1000000L, c('..', '+++')); .Internal(`substr<-`(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
+
+    @Test
+    public void testsubstrassign_1() {
+        assertEval("argv <- structure(list(x = c('NA', NA, 'BANANA'), start = 1,     stop = 2, value = 'na'), .Names = c('x', 'start', 'stop',     'value'));do.call('substr<-', argv)");
+    }
+
+    @Test
+    public void testsubstrassign_2() {
+        assertEval("argv <- structure(list(x = 'abcde', start = NA, stop = 3, value = 'abc'),     .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)");
+    }
+
+    @Test
+    public void testsubstrassign() {
+        assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, c('a', 'asdf'))");
+        assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), c(1,10,-6), 5, c('a', 'asdf'))");
+        assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, c(5,15,-6), c('a', 'asdf'))");
+        assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, NULL)");
+        assertEval("`substr<-`(c('asdfasdf', 'jfjfjf', 'ffff'), 2, 5, 1)");
+
+        String[] values = new String[]{"-2L", "-1L", "0L", "1L", "2L"};
+        assertEval(template("`substr<-`('ffff', %0, %1, 'xyz')", values, values));
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java
deleted file mode 100644
index 2573d8eefb..0000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.test.builtins;
-
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
-
-// Checkstyle: stop line length check
-
-public class TestBuiltin_substrassign_ extends TestBase {
-
-    @Test
-    public void testsubstrassign_1() {
-        assertEval("argv <- structure(list(x = c('NA', NA, 'BANANA'), start = 1,     stop = 2, value = 'na'), .Names = c('x', 'start', 'stop',     'value'));do.call('substr<-', argv)");
-    }
-
-    @Test
-    public void testsubstrassign_2() {
-        assertEval("argv <- structure(list(x = 'abcde', start = NA, stop = 3, value = 'abc'),     .Names = c('x', 'start', 'stop', 'value'));do.call('substr<-', argv)");
-    }
-}
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index d3c6075238..eaa941e25e 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -658,7 +658,6 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sub
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_subset2.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign_.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substrassign.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substring.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum.java,purdue.copyright
-- 
GitLab


From bd227f9d2f9a8b7cb16354c45571e733b1df596d Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 27 Mar 2017 14:05:09 -0700
Subject: [PATCH 189/402] RGraphics: get correct library for InitGraphics C
 function

---
 .../src/com/oracle/truffle/r/library/graphics/RGraphics.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
index 7e9d763981..4f635579bc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
@@ -35,7 +35,7 @@ public class RGraphics {
             if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
                 RGridGraphicsAdapter.initialize();
             } else {
-                DLL.DLLInfo dllInfo = DLL.findLibrary("graphics");
+                DLL.DLLInfo dllInfo = DLL.findLibraryContainingSymbol("InitGraphics");
                 DLL.SymbolHandle symbolHandle = DLL.findSymbol("InitGraphics", dllInfo);
                 assert symbolHandle != DLL.SYMBOL_NOT_FOUND;
                 CallRFFI.InvokeVoidCallRootNode.create().getCallTarget().call(new NativeCallInfo("InitGraphics", symbolHandle, dllInfo), new Object[0]);
-- 
GitLab


From c6642ac7edae16337da5e76255f3b542222fd1e0 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 27 Mar 2017 16:50:06 -0700
Subject: [PATCH 190/402] =?UTF-8?q?pkgtest:=20ensure=20path=20to=20?=
 =?UTF-8?q?=E2=80=98R=E2=80=99=20is=20on=20PATH?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 mx.fastr/mx_fastr_pkgs.py | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index f45348f89c..9a489fd72b 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -106,6 +106,13 @@ def _packages_test_project():
 def _packages_test_project_dir():
     return mx.project(_packages_test_project()).dir
 
+def _ensure_R_on_PATH(env, bindir):
+    '''
+    Some packages (e.g. stringi) require that 'R' is actually on the PATH
+    '''
+    env['PATH'] = join(bindir) + os.pathsep + os.environ['PATH']
+
+
 def installpkgs(args):
     _installpkgs(args)
 
@@ -120,10 +127,18 @@ def _installpkgs(args, **kwargs):
     by the FASTR_GRAALVM environment variable, we can't use mx to invoke
     FastR, but instead have to invoke the command directly.
     '''
+    if kwargs.has_key('env'):
+        env = kwargs['env']
+    else:
+        env = os.environ.copy()
+        kwargs['env'] = env
+
     script = _installpkgs_script()
     if _graalvm() is None:
+        _ensure_R_on_PATH(env, join(_fastr_suite_dir(), 'bin'))
         return mx_fastr.rscript([script] + args, **kwargs)
     else:
+        _ensure_R_on_PATH(env, os.path.dirname(_graalvm_rscript()))
         return mx.run([_graalvm_rscript(), script] + args, **kwargs)
 
 
@@ -352,8 +367,10 @@ def _gnur_install_test(forwarded_args, pkgs, gnur_libinstall, gnur_install_tmp):
     args += ['--testdir', 'test.gnur']
     _log_step('BEGIN', 'install/test', 'GnuR')
     if _graalvm():
+        _ensure_R_on_PATH(env, os.path.dirname(_gnur_rscript()))
         mx.run(args, nonZeroIsFatal=False, env=env)
     else:
+        _ensure_R_on_PATH(env, mx_fastr._gnur_path())
         mx_fastr.gnu_rscript(args, env=env)
     _log_step('END', 'install/test', 'GnuR')
 
-- 
GitLab


From 637173fa36f1b9b9a13716980bd1a99e65dfb228 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Mon, 27 Mar 2017 10:05:15 +0200
Subject: [PATCH 191/402] FastR Grid: savePlot, dev.cur, .Device and .Devices
 support

---
 .../fastrGrid/FastRGridExternalLookup.java    |  6 ++
 .../r/library/fastrGrid/GridContext.java      | 42 +++++++++-
 .../r/library/fastrGrid/GridState.java        |  6 +-
 .../r/library/fastrGrid/LGridDirty.java       | 31 ++++---
 .../r/library/fastrGrid/LInitGrid.java        |  2 +-
 .../truffle/r/library/fastrGrid/ViewPort.java |  1 +
 .../device/BufferedJFrameDevice.java          | 80 ++++++++++++-------
 .../library/fastrGrid/device/ImageSaver.java  | 33 ++++++++
 .../fastrGrid/device/JFrameDevice.java        | 26 +++---
 .../library/fastrGrid/grDevices/DevCurr.java  | 43 ++++++++++
 .../grDevices/InitWindowedDevice.java         | 11 +--
 .../fastrGrid/grDevices/R/fastrGridDevices.R  | 16 ++++
 .../library/fastrGrid/grDevices/SavePlot.java | 62 ++++++++++++++
 .../graphics/RGridGraphicsAdapter.java        | 34 +++++++-
 14 files changed, 325 insertions(+), 68 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index f77ddeb6c5..b42bda2ff1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -22,8 +22,10 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice;
+import com.oracle.truffle.r.library.fastrGrid.grDevices.SavePlot;
 import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
@@ -48,6 +50,8 @@ public final class FastRGridExternalLookup {
         switch (name) {
             case "devholdflush":
                 return DevHoldFlush.create();
+            case "devcur":
+                return new DevCurr();
             case "PDF":
                 return new IgnoredGridExternal(RNull.instance);
             default:
@@ -59,6 +63,8 @@ public final class FastRGridExternalLookup {
         switch (name) {
             case "C_par":
                 return new CPar();
+            case "savePlot":
+                return SavePlot.create();
             case "X11":
                 return new InitWindowedDevice();
             default:
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index ec68fcff20..14f87028cc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -22,9 +22,14 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import java.util.ArrayList;
+
 import com.oracle.truffle.r.library.fastrGrid.device.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 
 /**
  * Encapsulated the acces to the global grid state.
@@ -32,7 +37,16 @@ import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
 public final class GridContext {
     private static final GridContext INSTANCE = new GridContext();
     private final GridState gridState = new GridState();
-    private GridDevice currentDevice;
+
+    /**
+     * This list should correspond to the names inside {@code .Devices} variable in R.
+     */
+    private final ArrayList<GridDevice> devices = new ArrayList<>(2);
+    private int currentDeviceIdx = 0;
+
+    private GridContext() {
+        devices.add(null);
+    }
 
     public static GridContext getContext() {
         return INSTANCE;
@@ -42,10 +56,30 @@ public final class GridContext {
         return gridState;
     }
 
+    public int getCurrentDeviceIndex() {
+        return currentDeviceIdx;
+    }
+
     public GridDevice getCurrentDevice() {
-        if (currentDevice == null) {
-            currentDevice = new BufferedJFrameDevice(new JFrameDevice());
+        assert currentDeviceIdx >= 0 : "accessing devices before they were initialized";
+        return devices.get(currentDeviceIdx);
+    }
+
+    public void setCurrentDevice(String name, GridDevice currentDevice) {
+        RGridGraphicsAdapter.setCurrentDevice(name);
+        currentDeviceIdx = this.devices.size();
+        this.devices.add(currentDevice);
+        assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
+    }
+
+    public void openDefaultDevice() {
+        String defaultDev = RGridGraphicsAdapter.getDefaultDevice();
+        if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) {
+            BufferedJFrameDevice result = new BufferedJFrameDevice(new JFrameDevice());
+            setCurrentDevice(defaultDev, result);
+        } else {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'.");
         }
-        return currentDevice;
+        assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 6774a7b722..9cab0c14d7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -42,10 +42,9 @@ public final class GridState {
         return devHoldCount;
     }
 
-    public void init(REnvironment gridEnv, GridDevice currentDevice) {
+    public void init(REnvironment gridEnv) {
         this.gridEnv = gridEnv;
         this.currentGrob = RNull.instance;
-        initGPar(currentDevice);
     }
 
     void initGPar(GridDevice currentDevice) {
@@ -70,6 +69,9 @@ public final class GridState {
         this.gpar = gpar;
     }
 
+    /**
+     * Has the current device been initialized for use by grid?
+     */
     public boolean isDeviceInitialized() {
         return deviceInitialized;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index 2fe0e336c3..fd9abe3ff0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -13,15 +13,14 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.InitViewPortNode;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 final class LGridDirty extends RExternalBuiltinNode {
     @Child private InitViewPortNode initViewPort = new InitViewPortNode();
-    private final ConditionProfile initViewPortProfile = ConditionProfile.createCountingProfile();
 
     static {
         Casts.noCasts(LGridDirty.class);
@@ -30,16 +29,30 @@ final class LGridDirty extends RExternalBuiltinNode {
     @Override
     public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
         GridState gridState = GridContext.getContext().getGridState();
-        if (!gridState.isDeviceInitialized()) {
-            CompilerDirectives.transferToInterpreter();
-            GridContext.getContext().getCurrentDevice().openNewPage();
-            gridState.setDeviceInitialized();
+        if (gridState.isDeviceInitialized()) {
+            return RNull.instance;
         }
-        if (initViewPortProfile.profile(gridState.getViewPort() == null)) {
-            // this rarely happens, but we do not have a slow-path implementation (yet)
-            CompilerDirectives.transferToInterpreter();
+
+        // the rest only takes place if the device has been changed since the last time
+        CompilerDirectives.transferToInterpreter();
+
+        // if no device has been opened yet, open the default one and make it current
+        if (GridContext.getContext().getCurrentDevice() == null) {
+            GridContext.getContext().openDefaultDevice();
+        }
+
+        // the current device has not been initialized yet...
+        GridDevice device = GridContext.getContext().getCurrentDevice();
+        device.openNewPage();
+        gridState.setViewPort(initViewPort.execute(frame));
+        gridState.setDeviceInitialized();
+        if (gridState.getGpar() == null) {
+            gridState.initGPar(device);
+        }
+        if (gridState.getViewPort() == null) {
             gridState.setViewPort(initViewPort.execute(frame));
         }
+
         return RNull.instance;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
index 885ace9762..74aa2a0b0d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java
@@ -31,7 +31,7 @@ public abstract class LInitGrid extends RExternalBuiltinNode.Arg1 {
     @TruffleBoundary
     public Object doEnv(REnvironment gridEnv) {
         GridContext context = GridContext.getContext();
-        context.getGridState().init(gridEnv, context.getCurrentDevice());
+        context.getGridState().init(gridEnv);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 2a694a69f9..80e93f6270 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -153,6 +153,7 @@ final class ViewPort {
         public RList execute(VirtualFrame frame) {
             RFunction gridTopLevel = (RFunction) readGridTopLevel.execute(frame);
             RList topVP = (RList) callNode.execute(frame, gridTopLevel, RArgsValuesAndNames.EMPTY);
+            topVP.makeSharedPermanent();
 
             GridDevice device = GridContext.getContext().getCurrentDevice();
             // TODO: properly set the scale according to the current device
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
index 131165f954..e6cc073d1b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
@@ -22,20 +22,36 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.device;
 
+import static com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice.POINTS_IN_INCH;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
 import java.awt.image.BufferStrategy;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 
+import javax.imageio.ImageIO;
+
 /**
- * Decorator for {@link JFrameDevice} that implements {@link #hold()} and {@link #flush()}. Those
- * methods open/draw a 2D graphics buffer, while the buffer is open, any drawing is done in the
- * buffer not on the screen and we also record any drawing code to be able to replay it if the
- * buffer happens to loose contents, which is a possibility mentioned in the documentation. Note: we
- * rely on the fact that {@link DrawingContext} is immutable.
+ * Decorator for {@link JFrameDevice} that implements {@link #hold()} and {@link #flush()}
+ * functionality and implements the {@link ImageSaver} device.
+ *
+ * Methods {@link #hold()} and {@link #flush()} open/draw a 2D graphics buffer, while the buffer is
+ * open, any drawing is done in the buffer not on the screen and the buffer is dumped to the sceen
+ * once {@link #flush()} is called.
+ *
+ * We also record any drawing code to be able to replay it if the buffer happens to loose its
+ * contents, which is a possibility mentioned in the documentation. Moreover, this record of drawing
+ * can be used in {@link #save(String, String)} to replay the drawing in a {@code BufferedImage}.
+ * Note: here we rely on the fact that {@link DrawingContext} is immutable.
  */
-public final class BufferedJFrameDevice implements GridDevice {
+public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
     private final JFrameDevice inner;
+    private final ArrayList<Runnable> drawActions = new ArrayList<>(200);
     private BufferStrategy buffer;
-    private ArrayList<Runnable> drawActions;
 
     public BufferedJFrameDevice(JFrameDevice inner) {
         this.inner = inner;
@@ -44,6 +60,14 @@ public final class BufferedJFrameDevice implements GridDevice {
     @Override
     public void openNewPage() {
         inner.openNewPage();
+        drawActions.clear();
+        if (buffer != null) {
+            // if new page is opened while we are on hold, we should throw away current buffer. In
+            // other words that is like starting new hold without previous flush.
+            buffer.dispose();
+            buffer = null;
+            hold();
+        }
     }
 
     @Override
@@ -56,11 +80,7 @@ public final class BufferedJFrameDevice implements GridDevice {
             inner.getCurrentFrame().createBufferStrategy(2);
             buffer = inner.getCurrentFrame().getBufferStrategy();
         }
-        if (drawActions == null) {
-            drawActions = new ArrayList<>();
-        } else {
-            drawActions.clear();
-        }
+        drawActions.clear();
         inner.initGraphics(buffer.getDrawGraphics());
     }
 
@@ -88,41 +108,31 @@ public final class BufferedJFrameDevice implements GridDevice {
     @Override
     public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise) {
         inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise);
-        if (buffer != null) {
-            drawActions.add(() -> inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise));
-        }
+        drawActions.add(() -> inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise));
     }
 
     @Override
     public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
         inner.drawPolyLines(ctx, x, y, startIndex, length);
-        if (buffer != null) {
-            drawActions.add(() -> inner.drawPolyLines(ctx, x, y, startIndex, length));
-        }
+        drawActions.add(() -> inner.drawPolyLines(ctx, x, y, startIndex, length));
     }
 
     @Override
     public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
         inner.drawPolygon(ctx, x, y, startIndex, length);
-        if (buffer != null) {
-            drawActions.add(() -> inner.drawPolygon(ctx, x, y, startIndex, length));
-        }
+        drawActions.add(() -> inner.drawPolygon(ctx, x, y, startIndex, length));
     }
 
     @Override
     public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
         inner.drawCircle(ctx, centerX, centerY, radius);
-        if (buffer != null) {
-            drawActions.add(() -> inner.drawCircle(ctx, centerX, centerY, radius));
-        }
+        drawActions.add(() -> inner.drawCircle(ctx, centerX, centerY, radius));
     }
 
     @Override
     public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
         inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text);
-        if (buffer != null) {
-            drawActions.add(() -> inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text));
-        }
+        drawActions.add(() -> inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text));
     }
 
     @Override
@@ -144,4 +154,20 @@ public final class BufferedJFrameDevice implements GridDevice {
     public double getStringHeight(DrawingContext ctx, String text) {
         return inner.getStringHeight(ctx, text);
     }
+
+    @Override
+    public void save(String path, String fileType) throws IOException {
+        int realWidth = (int) (getWidth() * POINTS_IN_INCH);
+        int readHeight = (int) (getHeight() * POINTS_IN_INCH);
+        BufferedImage image = new BufferedImage(realWidth, readHeight, TYPE_INT_RGB);
+        Graphics2D imageGraphics = (Graphics2D) image.getGraphics();
+        imageGraphics.setBackground(new Color(255, 255, 255));
+        imageGraphics.clearRect(0, 0, realWidth, readHeight);
+        inner.initGraphics(imageGraphics);
+        for (Runnable drawAction : drawActions) {
+            drawAction.run();
+        }
+        ImageIO.write(image, fileType, new File(path));
+        inner.initGraphics(inner.getCurrentFrame().getGraphics());
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java
new file mode 100644
index 0000000000..c89d1cb667
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+import java.io.IOException;
+
+/**
+ * Devices that support saving their current state into a file should implement this inteface. Note:
+ * this only makes sense for interactive devices. Devices like SVG are already saving into a file.
+ */
+public interface ImageSaver {
+    void save(String path, String fileType) throws IOException;
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
index 6ee2268766..0f5f839ddd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
@@ -59,27 +59,27 @@ public final class JFrameDevice implements GridDevice {
     // coordinate system to the grid one. However, in the case of text rendering, we cannot simply
     // turn upside down the y-axis, because the text would be upside down too, so for text rendering
     // only, we reset the transformation completely and transform the coordinates ourselves
-    private static final double POINTS_IN_INCH = 72.;
+    static final double POINTS_IN_INCH = 72.;
 
     private static BasicStroke solidStroke;
     private static BasicStroke blankStroke;
 
-    private FastRFrame currentFrame;
+    private final FastRFrame currentFrame;
     private Graphics2D graphics;
 
+    public JFrameDevice() {
+        initStrokes();
+        currentFrame = new FastRFrame();
+        currentFrame.setVisible(true);
+        initGraphics(currentFrame.getGraphics());
+    }
+
     @Override
     public void openNewPage() {
-        initStrokes();
-        if (currentFrame == null) {
-            currentFrame = new FastRFrame();
-            currentFrame.setVisible(true);
-            initGraphics(currentFrame.getGraphics());
-        } else {
-            noTransform(() -> {
-                graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
-                return null;
-            });
-        }
+        noTransform(() -> {
+            graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
+            return null;
+        });
     }
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java
new file mode 100644
index 0000000000..5c9046e35d
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCurr.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+
+public final class DevCurr extends RExternalBuiltinNode.Arg0 {
+    static {
+        Casts.noCasts(DevCurr.class);
+    }
+
+    @Override
+    public RAbstractIntVector execute() {
+        int index = GridContext.getContext().getCurrentDeviceIndex();
+        RStringVector names = RDataFactory.createStringVectorFromScalar(RGridGraphicsAdapter.getDeviceName(index));
+        return RDataFactory.createIntVector(new int[]{index + 1}, RDataFactory.COMPLETE_VECTOR, names);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index d6314346b2..157212f385 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -24,8 +24,8 @@ package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
-import com.oracle.truffle.r.library.fastrGrid.GridState;
-import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
+import com.oracle.truffle.r.library.fastrGrid.device.BufferedJFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -43,12 +43,7 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
     @Override
     @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
-        GridState gridState = GridContext.getContext().getGridState();
-        if (!gridState.isDeviceInitialized()) {
-            GridContext.getContext().getCurrentDevice().openNewPage();
-            gridState.setDeviceInitialized();
-        }
-        RGridGraphicsAdapter.setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo");
+        GridContext.getContext().setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo", new BufferedJFrameDevice(new JFrameDevice()));
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
index 16a15ce9b2..390bdacd81 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
@@ -27,4 +27,20 @@ eval(expression({
     awt <- function(...) {
         .External2(grDevices:::C_X11)
     }
+    # GnuR version only works with "X11cairo" device. Our version of savePlot
+    # works with "awt" device and "X11cairo", which is for us only alias for
+    # "awt". Moreover, we only support formats that awt supports.
+    savePlot <- function (filename = paste("Rplot", type, sep = "."), type = c("png", "jpeg", "bmp"), device = dev.cur()) {
+        type <- match.arg(type)
+        devlist <- dev.list()
+        devcur <- match(device, devlist, NA)
+        if (is.na(devcur)) {
+            stop("no such device")
+        }
+        devname <- names(devlist)[devcur]
+        if (devname != "X11cairo" && devname != "awt") {
+            stop("can only copy from 'X11(type=\"*cairo\")' or 'awt' devices")
+        }
+        invisible(.External2(C_savePlot, filename, type, device))
+    }
 }), asNamespace("grDevices"))
\ No newline at end of file
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java
new file mode 100644
index 0000000000..c42a0e33b9
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/SavePlot.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import java.io.IOException;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.ImageSaver;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public abstract class SavePlot extends RExternalBuiltinNode.Arg3 {
+    static {
+        Casts casts = new Casts(SavePlot.class);
+        casts.arg(0).asStringVector().findFirst();
+        casts.arg(1).asStringVector().findFirst();
+    }
+
+    public static SavePlot create() {
+        return SavePlotNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object savePlot(String filename, String type) {
+        GridDevice device = GridContext.getContext().getCurrentDevice();
+        if (!(device instanceof ImageSaver)) {
+            throw error(Message.GENERIC, "Current device does not support plot saving. " +
+                            "Note that FastR savePlot function ignores the device argument and always uses the current device.");
+        }
+        try {
+            ((ImageSaver) device).save(filename, type);
+        } catch (IOException e) {
+            throw error(Message.GENERIC, "I/O error occured when saving the image.");
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
index 2bb5adf63c..2482fb35e3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
@@ -19,6 +19,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.ROptions;
 import com.oracle.truffle.r.runtime.ROptions.OptionsException;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -38,8 +39,14 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  * tries to open the default device it uses 'awt'. If the future this should be either 'awt' for
  * interactive sessions, or some image format device for batch sessions. We should also honor the
  * R_INTERACTIVE_DEVICE and R_DEFAULT_DEVICE environment variables.
+ *
+ * The responsibility of this class if to provide convenient access to those R-level variables. The
+ * actual devices instances are maintained in
+ * {@link com.oracle.truffle.r.library.fastrGrid.GridContext} since we only have grid devices and no
+ * generic graphics devices.
  */
 public final class RGridGraphicsAdapter {
+    private static final String DEFAULT_DEVICE_OPTION = "device";
     private static final String NULL_DEVICE = "null device";
     /**
      * The graphics devices system maintains two variables .Device and .Devices in the base
@@ -58,7 +65,7 @@ public final class RGridGraphicsAdapter {
         setCurrentDevice(NULL_DEVICE);
         ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
         try {
-            options.setValue("device", "awt");
+            options.setValue(DEFAULT_DEVICE_OPTION, "awt");
         } catch (OptionsException e) {
             RError.warning(RError.NO_CALLER, Message.GENERIC, "FastR could not set the 'device' options to awt.");
         }
@@ -67,11 +74,30 @@ public final class RGridGraphicsAdapter {
     public static void setCurrentDevice(String name) {
         REnvironment baseEnv = REnvironment.baseEnv();
         baseEnv.safePut(DOT_DEVICE, name);
-        Object devices = baseEnv.get(DOT_DEVICES);
-        if (devices instanceof RPairList) {
-            ((RPairList) devices).appendToEnd(RDataFactory.createPairList(name));
+        Object dotDevices = baseEnv.get(DOT_DEVICES);
+        if (dotDevices instanceof RPairList) {
+            ((RPairList) dotDevices).appendToEnd(RDataFactory.createPairList(name));
         } else {
             baseEnv.safePut(DOT_DEVICES, RDataFactory.createPairList(name));
         }
     }
+
+    public static String getDefaultDevice() {
+        ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
+        String defaultDev = RRuntime.asString(options.getValue(DEFAULT_DEVICE_OPTION));
+        if (RRuntime.isNA(defaultDev)) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does only supports character value as the default 'device' option");
+        }
+        return defaultDev;
+    }
+
+    public static int getDevicesCount() {
+        Object dotDevices = REnvironment.baseEnv().get(DOT_DEVICES);
+        return dotDevices instanceof RPairList ? ((RPairList) dotDevices).getLength() : 0;
+    }
+
+    public static String getDeviceName(int index) {
+        RPairList dotDevices = (RPairList) REnvironment.baseEnv().get(DOT_DEVICES);
+        return RRuntime.asString(dotDevices.getDataAtAsObject(index));
+    }
 }
-- 
GitLab


From d28aa024dc0f0e2dbaad932a06f3c8940039f6ca Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 28 Mar 2017 11:22:48 +0200
Subject: [PATCH 192/402] Fix: grep problem causing package loading to issue a
 warning. Restructured code in GrepFunctions to use cast pipeline for argument
 checking.

---
 .../r/nodes/builtin/base/GrepFunctions.java   | 184 ++++++++++--------
 .../truffle/r/test/ExpectedTestOutput.test    |   4 +
 .../r/test/builtins/TestBuiltin_grep.java     |   6 +
 3 files changed, 112 insertions(+), 82 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 88717774e1..f5ee34bcfe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -15,6 +15,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -74,32 +76,38 @@ public class GrepFunctions {
                             "pattern");
         }
 
+        protected static void castPatternSingle(Casts casts) {
+            // with default error message, NO_CALLER does not work
+            casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT,
+                            "pattern").shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "pattern").findFirst();
+        }
+
         protected static void castText(Casts casts, String textId) {
             casts.arg(textId).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, textId);
         }
 
         protected static void castIgnoreCase(Casts casts) {
-            casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+            casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
 
         protected static void castPerl(Casts casts) {
-            casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+            casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
 
         protected static void castFixed(Casts casts, byte defaultValue) {
-            casts.arg("fixed").asLogicalVector().findFirst(defaultValue);
+            casts.arg("fixed").asLogicalVector().findFirst(defaultValue).map(toBoolean());
         }
 
         protected static void castValue(Casts casts) {
-            casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+            casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
 
         protected static void castUseBytes(Casts casts) {
-            casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+            casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
 
         protected static void castInvert(Casts casts) {
-            casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+            casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
         }
 
         protected static void castCosts(Casts casts) {
@@ -116,13 +124,13 @@ public class GrepFunctions {
          * then an NYI error will be thrown (in the first one). If any of the arguments do not
          * apply, pass {@link RRuntime#LOGICAL_FALSE}.
          */
-        protected void checkExtraArgs(byte ignoreCase, byte perl, byte fixed, @SuppressWarnings("unused") byte useBytes, byte invert) {
-            checkNotImplemented(RRuntime.fromLogical(ignoreCase), "ignoreCase", true);
-            checkNotImplemented(RRuntime.fromLogical(perl), "perl", true);
-            checkNotImplemented(RRuntime.fromLogical(fixed), "fixed", true);
+        protected void checkExtraArgs(boolean ignoreCase, boolean perl, boolean fixed, @SuppressWarnings("unused") boolean useBytes, boolean invert) {
+            checkNotImplemented(ignoreCase, "ignoreCase", true);
+            checkNotImplemented(perl, "perl", true);
+            checkNotImplemented(fixed, "fixed", true);
             // We just ignore useBytes
             // checkNotImplemented(RRuntime.fromLogical(useBytes), "useBytes", true);
-            checkNotImplemented(RRuntime.fromLogical(invert), "invert", true);
+            checkNotImplemented(invert, "invert", true);
         }
 
         protected void checkCaseFixed(boolean ignoreCase, boolean fixed) {
@@ -140,23 +148,14 @@ public class GrepFunctions {
             }
         }
 
-        protected String checkLength(RAbstractStringVector arg, String name) {
-            if (arg.getLength() < 1) {
-                throw error(RError.Message.INVALID_ARGUMENT, name);
-            } else if (arg.getLength() > 1) {
-                warning(RError.Message.ARGUMENT_ONLY_FIRST, name);
-            }
-            return arg.getDataAt(0);
-        }
-
         /**
          * Temporary check for the {@code value} argument, which is only applicable to {@code grep}
          * and {@code agrep} (so not included in {@code checkExtraArgs}.
          *
          * @param value
          */
-        protected void valueCheck(byte value) {
-            if (RRuntime.fromLogical(value)) {
+        protected void valueCheck(boolean value) {
+            if (value) {
                 throw RError.nyi(this, "value == true");
             }
         }
@@ -182,10 +181,6 @@ public class GrepFunctions {
             }
         }
 
-        protected boolean isTrue(byte fixed) {
-            return RRuntime.fromLogical(fixed);
-        }
-
         protected RStringVector allStringNAResult(int len) {
             String[] naData = new String[len];
             for (int i = 0; i < len; i++) {
@@ -217,25 +212,21 @@ public class GrepFunctions {
     private abstract static class GrepAdapter extends CommonCodeAdapter {
         @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
 
-        protected Object doGrep(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical,
-                        @SuppressWarnings("unused") byte useBytes, byte invertLogical, boolean grepl) {
-            boolean value = RRuntime.fromLogical(valueLogical);
-            boolean invert = RRuntime.fromLogical(invertLogical);
-            boolean perl = RRuntime.fromLogical(perlLogical);
-            boolean ignoreCase = RRuntime.fromLogical(ignoreCaseLogical);
-            boolean fixed = RRuntime.fromLogical(fixedLogical);
-            perl = checkPerlFixed(RRuntime.fromLogical(perlLogical), fixed);
+        protected Object doGrep(String patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean value, boolean perlPar, boolean fixed,
+                        @SuppressWarnings("unused") boolean useBytes, boolean invert, boolean grepl) {
+            boolean perl = perlPar;
+            perl = checkPerlFixed(perlPar, fixed);
             checkCaseFixed(ignoreCase, fixed);
 
-            String pattern = checkLength(patternArgVec, "pattern");
+            String pattern = patternArg;
             int len = vector.getLength();
             if (RRuntime.isNA(pattern)) {
                 return value ? allStringNAResult(len) : allIntNAResult(len);
             }
             boolean[] matches = new boolean[len];
-            if (fixed && !perl) {
+            if (!perl) {
                 // TODO case
-                if (fixed) {
+                if (!fixed) {
                     pattern = RegExp.checkPreDefinedClasses(pattern);
                 }
                 findAllMatches(matches, pattern, vector, fixed, ignoreCase);
@@ -325,7 +316,7 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(Grep.class);
-            castPattern(casts);
+            castPatternSingle(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
             castValue(casts);
@@ -335,10 +326,39 @@ public class GrepFunctions {
             castInvert(casts);
         }
 
+        protected boolean checkContains(boolean value, boolean perl, boolean fixed, boolean useBytes) {
+            return fixed && !useBytes && !value && !perl;
+        }
+
+        @Specialization(guards = {"checkContains(value, perl, fixed, useBytes)"})
+        @TruffleBoundary
+        protected Object grepValueFixed(String patternPar, RAbstractStringVector vector, boolean ignoreCase, @SuppressWarnings("unused") boolean value,
+                        @SuppressWarnings("unused") boolean perl,
+                        @SuppressWarnings("unused") boolean fixed, @SuppressWarnings("unused") boolean useBytes, boolean invert) {
+
+            String pattern = ignoreCase ? patternPar.toLowerCase() : patternPar;
+
+            int[] matchIndices = new int[vector.getLength()];
+            int matches = 0;
+            for (int i = 0; i < vector.getLength(); i++) {
+                String s = vector.getDataAt(i);
+                if (ignoreCase) {
+                    s = s.toLowerCase();
+                }
+
+                if (s.contains(pattern) == !invert) {
+                    // don't forget: R indices are 1-based
+                    matchIndices[matches++] = i + 1;
+                }
+            }
+
+            return RDataFactory.createIntVector(Arrays.copyOf(matchIndices, matches), true);
+        }
+
         @Specialization
         @TruffleBoundary
-        protected Object grepValueFalse(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical,
-                        byte useBytes, byte invertLogical) {
+        protected Object grepValueFalse(String patternArgVec, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical,
+                        boolean useBytes, boolean invertLogical) {
             return doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, false);
         }
     }
@@ -348,7 +368,7 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(GrepL.class);
-            castPattern(casts);
+            castPatternSingle(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
             castValue(casts);
@@ -360,10 +380,10 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object grepl(RAbstractStringVector patternArgVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte valueLogical, byte perlLogical, byte fixedLogical, byte useBytes,
-                        byte invertLogical) {
+        protected Object grepl(String pattern, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical,
+                        boolean useBytes, boolean invertLogical) {
             // invert is passed but is always FALSE
-            return doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, true);
+            return doGrep(pattern, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, true);
         }
     }
 
@@ -372,20 +392,20 @@ public class GrepFunctions {
 
         protected static void castReplacement(Casts casts) {
             // with default error message, NO_CALLER does not work
-            casts.arg("replacement").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, "replacement");
+            casts.arg("replacement").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, "replacement").shouldBe(
+                            singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "replacement").findFirst();
         }
 
-        protected RStringVector doSub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector vector, byte ignoreCaseLogical, byte perlLogical,
-                        byte fixedLogical, @SuppressWarnings("unused") byte useBytes, boolean gsub) {
+        protected RStringVector doSub(String patternArg, String replacementArg, RAbstractStringVector vector, boolean ignoreCase, boolean perlPar,
+                        boolean fixedPar, @SuppressWarnings("unused") boolean useBytes, boolean gsub) {
             try {
-                boolean perl = RRuntime.fromLogical(perlLogical);
-                boolean fixed = RRuntime.fromLogical(fixedLogical);
-                boolean ignoreCase = RRuntime.fromLogical(ignoreCaseLogical);
+                boolean perl = perlPar;
+                boolean fixed = fixedPar;
                 checkNotImplemented(!(perl || fixed) && ignoreCase, "ignoreCase", true);
                 checkCaseFixed(ignoreCase, fixed);
                 perl = checkPerlFixed(perl, fixed);
-                String pattern = checkLength(patternArgVec, "pattern");
-                String replacement = checkLength(replacementVec, "replacement");
+                String pattern = patternArg;
+                String replacement = replacementArg;
 
                 int len = vector.getLength();
                 if (RRuntime.isNA(pattern)) {
@@ -647,7 +667,7 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(Sub.class);
-            castPattern(casts);
+            castPatternSingle(casts);
             castReplacement(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -658,8 +678,8 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RStringVector subRegexp(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector x, byte ignoreCaseLogical, byte perlLogical,
-                        byte fixedLogical, byte useBytes) {
+        protected RStringVector subRegexp(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical,
+                        boolean fixedLogical, boolean useBytes) {
             return doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, false);
         }
     }
@@ -669,7 +689,7 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(GSub.class);
-            castPattern(casts);
+            castPatternSingle(casts);
             castReplacement(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -680,8 +700,8 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RStringVector gsub(RAbstractStringVector patternArgVec, RAbstractStringVector replacementVec, RAbstractStringVector x, byte ignoreCaseLogical, byte perlLogical, byte fixedLogical,
-                        byte useBytes) {
+        protected RStringVector gsub(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical,
+                        boolean fixedLogical, boolean useBytes) {
             return doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, true);
         }
     }
@@ -736,11 +756,11 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCaseL, byte perlL, byte fixedL, byte useBytesL) {
-            checkExtraArgs(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytesL, RRuntime.LOGICAL_FALSE);
-            boolean ignoreCase = RRuntime.fromLogical(ignoreCaseL);
-            boolean fixed = RRuntime.fromLogical(fixedL);
-            boolean perl = RRuntime.fromLogical(perlL);
+        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL) {
+            checkExtraArgs(false, false, false, useBytesL, false);
+            boolean ignoreCase = ignoreCaseL;
+            boolean fixed = fixedL;
+            boolean perl = perlL;
             if (patternArg.getLength() > 1) {
                 throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
             }
@@ -915,11 +935,11 @@ public class GrepFunctions {
         @Specialization
         @TruffleBoundary
         @Override
-        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCaseL, byte perlL, byte fixedL, byte useBytesL) {
-            checkExtraArgs(RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytesL, RRuntime.LOGICAL_FALSE);
-            boolean ignoreCase = RRuntime.fromLogical(ignoreCaseL);
-            boolean fixed = RRuntime.fromLogical(fixedL);
-            boolean perl = RRuntime.fromLogical(perlL);
+        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL) {
+            checkExtraArgs(false, false, false, useBytesL, false);
+            boolean ignoreCase = ignoreCaseL;
+            boolean fixed = fixedL;
+            boolean perl = perlL;
             if (patternArg.getLength() > 1) {
                 throw RInternalError.unimplemented("multi-element patterns in gregexpr not implemented yet");
             }
@@ -1028,7 +1048,7 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(AGrep.class);
-            castPattern(casts);
+            castPatternSingle(casts);
             castText(casts, "x");
             castIgnoreCase(casts);
             castValue(casts);
@@ -1041,15 +1061,15 @@ public class GrepFunctions {
         @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
-        protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RAbstractIntVector costs, RAbstractDoubleVector bounds, byte useBytes,
-                        byte fixed) {
+        protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds,
+                        boolean useBytes,
+                        boolean fixed) {
             // TODO implement completely; this is a very basic implementation for fixed=TRUE only.
-            checkExtraArgs(ignoreCase, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytes, RRuntime.LOGICAL_FALSE);
+            checkExtraArgs(ignoreCase, false, false, useBytes, false);
             valueCheck(value);
-            checkNotImplemented(!RRuntime.fromLogical(fixed), "fixed", false);
+            checkNotImplemented(!fixed, "fixed", false);
             int[] tmp = new int[vector.getLength()];
             int numMatches = 0;
-            String pattern = patternArg.getDataAt(0);
             long maxDistance = Math.round(pattern.length() * bounds.getDataAt(0));
             for (int i = 0; i < vector.getLength(); i++) {
                 int ld = ld(pattern, vector.getDataAt(i));
@@ -1144,7 +1164,7 @@ public class GrepFunctions {
 
         static {
             Casts casts = new Casts(AGrepL.class);
-            castPattern(casts);
+            castPatternSingle(casts);
             castText(casts, "x");
             castIgnoreCase(casts);
             castValue(casts);
@@ -1157,12 +1177,12 @@ public class GrepFunctions {
         @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
-        protected Object aGrep(RAbstractStringVector patternArg, RAbstractStringVector vector, byte ignoreCase, byte value, RAbstractIntVector costs, RAbstractDoubleVector bounds, byte useBytes,
-                        byte fixed) {
+        protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds,
+                        boolean useBytes,
+                        boolean fixed) {
             // TODO implement properly, this only supports strict equality!
-            checkExtraArgs(ignoreCase, RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, useBytes, RRuntime.LOGICAL_FALSE);
+            checkExtraArgs(ignoreCase, false, false, useBytes, false);
             byte[] data = new byte[vector.getLength()];
-            String pattern = patternArg.getDataAt(0);
             for (int i = 0; i < vector.getLength(); i++) {
                 data[i] = RRuntime.asLogical(pattern.equals(vector.getDataAt(i)));
             }
@@ -1187,9 +1207,9 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RList split(RAbstractStringVector x, RAbstractStringVector splitArg, byte fixedLogical, byte perlLogical, @SuppressWarnings("unused") byte useBytes) {
-            boolean fixed = RRuntime.fromLogical(fixedLogical);
-            boolean perl = checkPerlFixed(RRuntime.fromLogical(perlLogical), fixed);
+        protected RList split(RAbstractStringVector x, RAbstractStringVector splitArg, boolean fixedLogical, boolean perlLogical, @SuppressWarnings("unused") boolean useBytes) {
+            boolean fixed = fixedLogical;
+            boolean perl = checkPerlFixed(perlLogical, fixed);
             RStringVector[] result = new RStringVector[x.getLength()];
             // treat split = NULL as split = ""
             RAbstractStringVector split = splitArg.getLength() == 0 ? RDataFactory.createStringVectorFromScalar("") : splitArg;
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 b436da3e9b..8e341d3b4c 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
@@ -25362,6 +25362,10 @@ integer(0)
 #argv <- list('^[[:blank:]]*$', 'mtext(\'«Latin-1 accented chars»: éè øØ å<Å æ<Æ\', side = 3)', FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testgrep13#
+#argv <- list('.__T__[[<-:', '.__T__[[<-:base', FALSE, FALSE, FALSE, TRUE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testgrep2#
 #argv <- list('éè', '«Latin-1 accented chars»: éè øØ å<Å æ<Æ é éè', TRUE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java
index 29f31b22de..83f201d7b1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java
@@ -76,6 +76,12 @@ public class TestBuiltin_grep extends TestBase {
         assertEval("argv <- list('^[[:blank:]]*$', 'mtext(\\\'«Latin-1 accented chars»: éè øØ å<Å æ<Æ\\\', side = 3)', FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))");
     }
 
+    @Test
+    public void testgrep13() {
+        // grep('.__T__[[<-:', data, fixed = TRUE)
+        assertEval("argv <- list('.__T__[[<-:', '.__T__[[<-:base', FALSE, FALSE, FALSE, TRUE, FALSE, FALSE); .Internal(grep(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))");
+    }
+
     @Test
     public void testGrep() {
         assertEval("{ txt<-c(\"arm\",\"foot\",\"lefroo\", \"bafoobar\"); grep(\"foo\", txt) }");
-- 
GitLab


From 35adb408b2bf6379b7f079af83f2b60d4e17848b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Mon, 27 Mar 2017 11:49:22 +0200
Subject: [PATCH 193/402] FastR Grid: generic Graphics2D device + png, jpeg,
 and bmp support

---
 .../r/library/fastrGrid/DoSetViewPort.java    |   2 +-
 .../fastrGrid/FastRGridExternalLookup.java    |   3 +
 .../r/library/fastrGrid/GridContext.java      |  24 +-
 .../r/library/fastrGrid/GridLinesNode.java    |   2 +-
 .../fastrGrid/IgnoredGridExternal.java        |   4 +-
 .../truffle/r/library/fastrGrid/Unit.java     |   2 +-
 .../library/fastrGrid/device/GridDevice.java  |  34 ++-
 .../library/fastrGrid/device/ImageSaver.java  |   5 +-
 .../device/awt/BufferedImageDevice.java       |  84 ++++++
 .../{ => awt}/BufferedJFrameDevice.java       |  48 ++--
 .../Graphics2DDevice.java}                    | 248 ++++++++----------
 .../fastrGrid/device/awt/JFrameDevice.java    | 119 +++++++++
 .../r/library/fastrGrid/grDevices/DevOff.java |  59 +++++
 .../grDevices/InitWindowedDevice.java         |  37 ++-
 .../graphics/RGridGraphicsAdapter.java        |  30 +++
 15 files changed, 528 insertions(+), 173 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
 rename com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/{ => awt}/BufferedJFrameDevice.java (75%)
 rename com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/{JFrameDevice.java => awt/Graphics2DDevice.java} (54%)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 9d35941ac8..f61ea60f85 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -355,7 +355,7 @@ final class DoSetViewPort extends RBaseNode {
         }
     }
 
-    // Note: unlike the GnuR conterpart of this method, we expect the LayoutPos to have the NULL
+    // Note: unlike the GnuR counterpart of this method, we expect the LayoutPos to have the NULL
     // positions replaced with nrow/ncol already.
     private ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) {
         // unlike in GnuR, we maintain parent viewport widths/heights in inches like anything else
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index b42bda2ff1..354cc20747 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
+import com.oracle.truffle.r.library.fastrGrid.grDevices.DevOff;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.InitWindowedDevice;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.SavePlot;
 import com.oracle.truffle.r.library.fastrGrid.graphics.CPar;
@@ -52,6 +53,8 @@ public final class FastRGridExternalLookup {
                 return DevHoldFlush.create();
             case "devcur":
                 return new DevCurr();
+            case "devoff":
+                return DevOff.create();
             case "PDF":
                 return new IgnoredGridExternal(RNull.instance);
             default:
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 14f87028cc..d16589172b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -24,15 +24,16 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import java.util.ArrayList;
 
-import com.oracle.truffle.r.library.fastrGrid.device.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 
 /**
- * Encapsulated the acces to the global grid state.
+ * Encapsulated the access to the global grid state.
  */
 public final class GridContext {
     private static final GridContext INSTANCE = new GridContext();
@@ -60,12 +61,17 @@ public final class GridContext {
         return currentDeviceIdx;
     }
 
+    public int getDevicesSize() {
+        return devices.size();
+    }
+
     public GridDevice getCurrentDevice() {
         assert currentDeviceIdx >= 0 : "accessing devices before they were initialized";
         return devices.get(currentDeviceIdx);
     }
 
     public void setCurrentDevice(String name, GridDevice currentDevice) {
+        RGridGraphicsAdapter.addDevice(name);
         RGridGraphicsAdapter.setCurrentDevice(name);
         currentDeviceIdx = this.devices.size();
         this.devices.add(currentDevice);
@@ -75,11 +81,21 @@ public final class GridContext {
     public void openDefaultDevice() {
         String defaultDev = RGridGraphicsAdapter.getDefaultDevice();
         if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) {
-            BufferedJFrameDevice result = new BufferedJFrameDevice(new JFrameDevice());
+            BufferedJFrameDevice result = new BufferedJFrameDevice(JFrameDevice.create());
             setCurrentDevice(defaultDev, result);
         } else {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'.");
         }
         assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
     }
+
+    public void closeDevice(int which) throws DeviceCloseException {
+        assert which >= 0 && which < devices.size();
+        devices.get(which).close();
+        RGridGraphicsAdapter.removeDevice(which);
+        devices.remove(which);
+        if (currentDeviceIdx >= which) {
+            currentDeviceIdx--;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index ba1b404e0d..8db8ff46c3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -76,7 +76,7 @@ public abstract class GridLinesNode extends Node {
             // following loop finds series of valid points (finite x and y values) and draws each
             // such series as a polyline
             for (int i = 0; i < unitIndexesLen; i++) {
-                int unitIndex = unitIndexes.getDataAt(i) - 1;   // coverting R's 1-based index
+                int unitIndex = unitIndexes.getDataAt(i) - 1;   // converting R's 1-based index
                 Point origLoc = Point.fromUnits(unitToInches, x, y, unitIndex, conversionCtx);
                 Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
                 xx[i] = loc.x;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
index 37090901e1..17e5e85dae 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/IgnoredGridExternal.java
@@ -26,8 +26,8 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 
 /**
- * A node for externals that we ignore, becuase we do not need to implement them or because they
- * support functionallity we do not implement yet, especially record/replay.
+ * A node for externals that we ignore, because we do not need to implement them or because they
+ * support features we do not implement yet, especially record/replay.
  */
 final class IgnoredGridExternal extends RExternalBuiltinNode {
     private final Object result;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 04165ca174..8d8dd780d0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -56,7 +56,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Note: internally in FastR Grid everything is in inches. However, some lists that are exposed to
- * the R code should contain values in centimeters, we convert such values immediatelly once they
+ * the R code should contain values in centimeters, we convert such values immediately once they
  * enter our system.
  */
 public final class Unit {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index afe759f3f0..53f08304db 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -46,15 +46,25 @@ public interface GridDevice {
     default void flush() {
     }
 
+    /**
+     * Gets called when the device is closed from R. This is the point where non-interactive devices
+     * should save their output into a file.
+     *
+     * @throws DeviceCloseException if the closing was not successful e.g. because the file could
+     *             not be written.
+     */
+    default void close() throws DeviceCloseException {
+    }
+
     /**
      * Draws a rectangle at given position, the center of the rotation should be the center of the
      * rectangle. The rotation is given in radians.
      */
-    void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise);
+    void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise);
 
     /**
      * Connects given points with a line, there has to be at least two points in order to actually
-     * draw somethig.
+     * draw something.
      */
     void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length);
 
@@ -100,7 +110,25 @@ public interface GridDevice {
      * parameters from the drawing context, but we allow the device to override this calculation
      * with something more precise.
      */
-    default double getStringHeight(DrawingContext ctx, @SuppressWarnings("unused") String text) {
+    default double getStringHeight(DrawingContext ctx, String text) {
         return (ctx.getLineHeight() * ctx.getFontSize()) / INCH_TO_POINTS_FACTOR;
     }
+
+    final class DeviceCloseException extends Exception {
+        private static final long serialVersionUID = 1182697755931636214L;
+
+        public DeviceCloseException(Throwable cause) {
+            super(cause);
+        }
+
+        @Override
+        public String getMessage() {
+            return getCause().getMessage();
+        }
+
+        @Override
+        public synchronized Throwable fillInStackTrace() {
+            return this;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java
index c89d1cb667..7377c90be2 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/ImageSaver.java
@@ -25,8 +25,9 @@ package com.oracle.truffle.r.library.fastrGrid.device;
 import java.io.IOException;
 
 /**
- * Devices that support saving their current state into a file should implement this inteface. Note:
- * this only makes sense for interactive devices. Devices like SVG are already saving into a file.
+ * Devices that support saving their current state into a file should implement this interface.
+ * Note: this only makes sense for interactive devices. Devices like SVG are already saving into a
+ * file.
  */
 public interface ImageSaver {
     void save(String path, String fileType) throws IOException;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
new file mode 100644
index 0000000000..485ad25161
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device.awt;
+
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+public final class BufferedImageDevice extends Graphics2DDevice {
+    private final BufferedImage image;
+    private final String filename;
+    private final String fileType;
+
+    private BufferedImageDevice(String filename, String fileType, BufferedImage image, Graphics2D graphics, int width, int height) {
+        super(graphics, width, height, true);
+        this.filename = filename;
+        this.fileType = fileType;
+        this.image = image;
+        graphics.setBackground(new Color(255, 255, 255));
+        graphics.clearRect(0, 0, width, height);
+    }
+
+    public static BufferedImageDevice open(String filename, String fileType, int width, int height) throws NotSupportedImageFormatException {
+        if (!isSupportedFormat(fileType)) {
+            throw new NotSupportedImageFormatException();
+        }
+        BufferedImage image = new BufferedImage(width, height, TYPE_INT_RGB);
+        return new BufferedImageDevice(filename, fileType, image, (Graphics2D) image.getGraphics(), width, height);
+    }
+
+    @Override
+    public void close() throws DeviceCloseException {
+        try {
+            ImageIO.write(image, fileType, new File(filename));
+        } catch (IOException e) {
+            throw new DeviceCloseException(e);
+        }
+    }
+
+    private static boolean isSupportedFormat(String formatName) {
+        String[] formatNames = ImageIO.getWriterFormatNames();
+        for (String n : formatNames) {
+            if (n.equals(formatName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static class NotSupportedImageFormatException extends Exception {
+        private static final long serialVersionUID = 1182697755931636217L;
+
+        @Override
+        public synchronized Throwable fillInStackTrace() {
+            return this;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
similarity index 75%
rename from com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
index e6cc073d1b..d6a7270acd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
@@ -20,12 +20,12 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.library.fastrGrid.device;
+package com.oracle.truffle.r.library.fastrGrid.device.awt;
 
-import static com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice.POINTS_IN_INCH;
 import static java.awt.image.BufferedImage.TYPE_INT_RGB;
 
 import java.awt.Color;
+import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.image.BufferStrategy;
 import java.awt.image.BufferedImage;
@@ -35,12 +35,16 @@ import java.util.ArrayList;
 
 import javax.imageio.ImageIO;
 
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.ImageSaver;
+
 /**
  * Decorator for {@link JFrameDevice} that implements {@link #hold()} and {@link #flush()}
  * functionality and implements the {@link ImageSaver} device.
  *
  * Methods {@link #hold()} and {@link #flush()} open/draw a 2D graphics buffer, while the buffer is
- * open, any drawing is done in the buffer not on the screen and the buffer is dumped to the sceen
+ * open, any drawing is done in the buffer not on the screen and the buffer is dumped to the screen
  * once {@link #flush()} is called.
  *
  * We also record any drawing code to be able to replay it if the buffer happens to loose its
@@ -81,7 +85,7 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
             buffer = inner.getCurrentFrame().getBufferStrategy();
         }
         drawActions.clear();
-        inner.initGraphics(buffer.getDrawGraphics());
+        setGraphics(buffer.getDrawGraphics());
     }
 
     @Override
@@ -93,34 +97,42 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
         buffer.show();
         // re-draw the buffer if the contents were lost
         while (buffer.contentsLost()) {
-            inner.initGraphics(buffer.getDrawGraphics());
+            setGraphics(buffer.getDrawGraphics());
             for (Runnable drawAction : drawActions) {
                 drawAction.run();
             }
             buffer.show();
         }
 
-        inner.initGraphics(inner.getCurrentFrame().getGraphics());
+        setGraphics(inner.getCurrentFrame().getGraphics());
         buffer.dispose();
         buffer = null;
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise) {
-        inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise);
-        drawActions.add(() -> inner.drawRect(ctx, leftX, topY, width, height, rotationAnticlockWise));
+    public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) {
+        inner.drawRect(ctx, leftX, bottomY, width, height, rotationAnticlockWise);
+        drawActions.add(() -> inner.drawRect(ctx, leftX, bottomY, width, height, rotationAnticlockWise));
     }
 
     @Override
     public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
         inner.drawPolyLines(ctx, x, y, startIndex, length);
-        drawActions.add(() -> inner.drawPolyLines(ctx, x, y, startIndex, length));
+        double[] xCopy = new double[x.length];
+        double[] yCopy = new double[y.length];
+        System.arraycopy(x, 0, xCopy, 0, x.length);
+        System.arraycopy(y, 0, yCopy, 0, y.length);
+        drawActions.add(() -> inner.drawPolyLines(ctx, xCopy, yCopy, startIndex, length));
     }
 
     @Override
     public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
         inner.drawPolygon(ctx, x, y, startIndex, length);
-        drawActions.add(() -> inner.drawPolygon(ctx, x, y, startIndex, length));
+        double[] xCopy = new double[x.length];
+        double[] yCopy = new double[y.length];
+        System.arraycopy(x, 0, xCopy, 0, x.length);
+        System.arraycopy(y, 0, yCopy, 0, y.length);
+        drawActions.add(() -> inner.drawPolygon(ctx, xCopy, yCopy, startIndex, length));
     }
 
     @Override
@@ -157,17 +169,23 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
 
     @Override
     public void save(String path, String fileType) throws IOException {
-        int realWidth = (int) (getWidth() * POINTS_IN_INCH);
-        int readHeight = (int) (getHeight() * POINTS_IN_INCH);
+        int realWidth = (int) (getWidth() * JFrameDevice.AWT_POINTS_IN_INCH);
+        int readHeight = (int) (getHeight() * JFrameDevice.AWT_POINTS_IN_INCH);
         BufferedImage image = new BufferedImage(realWidth, readHeight, TYPE_INT_RGB);
         Graphics2D imageGraphics = (Graphics2D) image.getGraphics();
         imageGraphics.setBackground(new Color(255, 255, 255));
         imageGraphics.clearRect(0, 0, realWidth, readHeight);
-        inner.initGraphics(imageGraphics);
+        setGraphics(imageGraphics);
         for (Runnable drawAction : drawActions) {
             drawAction.run();
         }
         ImageIO.write(image, fileType, new File(path));
-        inner.initGraphics(inner.getCurrentFrame().getGraphics());
+        setGraphics(inner.getCurrentFrame().getGraphics());
+    }
+
+    private void setGraphics(Graphics graphics) {
+        JFrameDevice.defaultInitGraphics((Graphics2D) graphics);
+        inner.getGraphics2D().dispose();
+        inner.setGraphics2D((Graphics2D) graphics);
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
similarity index 54%
rename from com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
index 0f5f839ddd..74540e4d11 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
@@ -20,82 +20,85 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.library.fastrGrid.device;
+package com.oracle.truffle.r.library.fastrGrid.device.awt;
 
 import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
 import static java.awt.geom.Path2D.WIND_EVEN_ODD;
 
 import java.awt.BasicStroke;
-import java.awt.BorderLayout;
 import java.awt.Color;
-import java.awt.Dimension;
 import java.awt.Font;
-import java.awt.Graphics;
 import java.awt.Graphics2D;
-import java.awt.HeadlessException;
 import java.awt.Paint;
-import java.awt.RenderingHints;
 import java.awt.Shape;
-import java.awt.Toolkit;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
-import java.util.function.Supplier;
-
-import javax.swing.JFrame;
-import javax.swing.JPanel;
 
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin;
+import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.RInternalError;
 
-public final class JFrameDevice implements GridDevice {
+/**
+ * A device that draws to given {@code Graphics2D} object regardless of whether it was created for
+ * e.g. an image, or window. This device only used by other devices and not exposed at the R level.
+ * Note: it is responsibility of the use to handle resources management, i.e. calling
+ * {@code dispose} on the graphics object once it is not needed anymore.
+ */
+public class Graphics2DDevice implements GridDevice {
     // Grid's coordinate system has origin in left bottom corner and y axis grows from bottom to
-    // top. Moreover, the grid system uses inches as units. We use transformation to adjust the java
-    // coordinate system to the grid one. However, in the case of text rendering, we cannot simply
-    // turn upside down the y-axis, because the text would be upside down too, so for text rendering
-    // only, we reset the transformation completely and transform the coordinates ourselves
-    static final double POINTS_IN_INCH = 72.;
+    // top. Moreover, the grid system uses inches as units. We do not use builtin transformations,
+    // because (a) text rendering gets affected badly (upside down text), (b) the user of this call
+    // may wish to apply his/her own transformations to the graphics object and we should not
+    // interfere with these. In cases we do use transformation, we make sure to set back the
+    // original one after we're done.
+    static final double AWT_POINTS_IN_INCH = 72.;
 
-    private static BasicStroke solidStroke;
     private static BasicStroke blankStroke;
 
-    private final FastRFrame currentFrame;
+    private final int width;
+    private final int height;
     private Graphics2D graphics;
-
-    public JFrameDevice() {
+    private final boolean graphicsIsExclusive;
+    private DrawingContext cachedContext;
+
+    /**
+     * @param graphics Object that should be used for the drawing.
+     * @param width Width of the drawing area in AWT units.
+     * @param height Height of the drawing area in AWT units.
+     * @param graphicsIsExclusive If the graphics object is exclusively used for drawing only by
+     *            this class, then it can optimize some things.
+     */
+    Graphics2DDevice(Graphics2D graphics, int width, int height, boolean graphicsIsExclusive) {
         initStrokes();
-        currentFrame = new FastRFrame();
-        currentFrame.setVisible(true);
-        initGraphics(currentFrame.getGraphics());
+        setGraphics2D(graphics);
+        this.width = width;
+        this.height = height;
+        this.graphicsIsExclusive = graphicsIsExclusive;
     }
 
     @Override
     public void openNewPage() {
-        noTransform(() -> {
-            graphics.clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
-            return null;
-        });
+        graphics.clearRect(0, 0, width, height);
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double topY, double width, double height, double rotationAnticlockWise) {
+    public void drawRect(DrawingContext ctx, double leftXIn, double bottomYIn, double widthIn, double heightIn, double rotationAnticlockWise) {
+        int leftX = transX(leftXIn);
+        int topY = transY(bottomYIn + heightIn);
+        int width = transDim(widthIn);
+        int height = transDim(heightIn);
         setContext(ctx);
         if (rotationAnticlockWise == 0.) {
             drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height));
             return;
         }
-        AffineTransform oldTr = graphics.getTransform();
-        AffineTransform newTr = new AffineTransform(oldTr);
-        newTr.translate(leftX + width / 2, topY + height / 2);
-        newTr.rotate(rotationAnticlockWise);
-        graphics.setTransform(newTr);
-        drawShape(ctx, new Rectangle2D.Double(-(width / 2), -(height / 2), width, height));
-        graphics.setTransform(oldTr);
+        transformed(leftX + width / 2, topY + height / 2, rotationAnticlockWise, () -> drawShape(ctx, new Rectangle2D.Double(-(width / 2), -(height / 2), width, height)));
     }
 
     @Override
@@ -113,78 +116,91 @@ public final class JFrameDevice implements GridDevice {
     }
 
     @Override
-    public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
+    public void drawCircle(DrawingContext ctx, double centerXIn, double centerYIn, double radiusIn) {
         setContext(ctx);
+        int centerX = transX(centerXIn);
+        int centerY = transY(centerYIn);
+        int radius = transDim(radiusIn);
         drawShape(ctx, new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2d, radius * 2d));
     }
 
     @Override
-    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
-        setContext(ctx);
-        noTransform(() -> {
-            AffineTransform tr = graphics.getTransform();
-            tr.translate((float) (leftX * POINTS_IN_INCH), (float) (currentFrame.getContentPane().getHeight() - bottomY * POINTS_IN_INCH));
-            tr.rotate(-rotationAnticlockWise);
-            graphics.setTransform(tr);
-            setFont(ctx);
-            graphics.drawString(text, 0, 0);
-            return null;
-        });
+    public void drawString(DrawingContext ctx, double leftXIn, double bottomYIn, double rotationAnticlockWise, String text) {
+        setContextAndFont(ctx);
+        int leftX = transX(leftXIn);
+        int bottomY = transY(bottomYIn);
+        transformed(leftX, bottomY, rotationAnticlockWise, () -> graphics.drawString(text, 0, 0));
     }
 
     @Override
     public double getWidth() {
-        return currentFrame.getContentPane().getWidth() / POINTS_IN_INCH;
+        return width / AWT_POINTS_IN_INCH;
     }
 
     @Override
     public double getHeight() {
-        return currentFrame.getContentPane().getHeight() / POINTS_IN_INCH;
+        return height / AWT_POINTS_IN_INCH;
     }
 
     @Override
     public double getStringWidth(DrawingContext ctx, String text) {
-        setContext(ctx);
-        return noTransform(() -> {
-            setFont(ctx);
-            int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
-            return swingUnits / POINTS_IN_INCH;
-        });
+        setContextAndFont(ctx);
+        int swingUnits = graphics.getFontMetrics(graphics.getFont()).stringWidth(text);
+        return swingUnits / AWT_POINTS_IN_INCH;
     }
 
     @Override
     public double getStringHeight(DrawingContext ctx, String text) {
-        setContext(ctx);
-        return noTransform(() -> {
-            setFont(ctx);
-            int swingUnits = graphics.getFont().getSize();
-            return swingUnits / POINTS_IN_INCH;
-        });
+        setContextAndFont(ctx);
+        int swingUnits = graphics.getFont().getSize();
+        return swingUnits / AWT_POINTS_IN_INCH;
+    }
+
+    void setGraphics2D(Graphics2D newGraphics) {
+        assert newGraphics != null;
+        graphics = newGraphics;
+    }
+
+    public Graphics2D getGraphics2D() {
+        return graphics;
+    }
+
+    private int transY(double y) {
+        return height - (int) (y * AWT_POINTS_IN_INCH);
     }
 
-    FastRFrame getCurrentFrame() {
-        return currentFrame;
+    private static int transX(double x) {
+        return (int) (x * AWT_POINTS_IN_INCH);
     }
 
-    void initGraphics(Graphics newGraphics) {
-        if (graphics != null) {
-            graphics.dispose();
+    private static int transDim(double widthOrHeight) {
+        return (int) (widthOrHeight * AWT_POINTS_IN_INCH);
+    }
+
+    private static void initStrokes() {
+        if (blankStroke != null) {
+            return;
         }
-        graphics = (Graphics2D) newGraphics;
-        graphics.translate(0, currentFrame.getHeight());
-        graphics.scale(POINTS_IN_INCH, -POINTS_IN_INCH);
-        graphics.setStroke(new BasicStroke((float) (1d / POINTS_IN_INCH)));
-        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-        graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+        blankStroke = new BasicStroke(0f);
+    }
+
+    private void transformed(int centreX, int centreY, double radiansAnticlockwise, Runnable action) {
+        AffineTransform oldTransform = graphics.getTransform();
+        AffineTransform newTr = new AffineTransform(oldTransform);
+        newTr.translate(centreX, centreY);
+        newTr.rotate(-radiansAnticlockwise);
+        graphics.setTransform(newTr);
+        action.run();
+        graphics.setTransform(oldTransform);
     }
 
     private Path2D.Double getPath2D(double[] x, double[] y, int startIndex, int length) {
         assert startIndex >= 0 && startIndex < x.length && startIndex < y.length : "startIndex out of bounds";
         assert length > 0 && (startIndex + length) <= Math.min(x.length, y.length) : "length out of bounds";
         Path2D.Double path = new Path2D.Double(WIND_EVEN_ODD, x.length);
-        path.moveTo(x[startIndex], y[startIndex]);
+        path.moveTo(transX(x[startIndex]), transY(y[startIndex]));
         for (int i = startIndex + 1; i < length; i++) {
-            path.lineTo(x[i], y[i]);
+            path.lineTo(transX(x[i]), transY(y[i]));
         }
         return path;
     }
@@ -198,16 +214,26 @@ public final class JFrameDevice implements GridDevice {
     }
 
     private void setContext(DrawingContext ctx) {
+        if (graphicsIsExclusive && cachedContext == ctx) {
+            return;
+        }
         graphics.setColor(fromGridColor(ctx.getColor()));
         graphics.setStroke(getStrokeFromCtx(ctx));
+        cachedContext = ctx;
     }
 
-    private void setFont(DrawingContext ctx) {
-        float fontSize = (float) ((ctx.getFontSize() / INCH_TO_POINTS_FACTOR) * POINTS_IN_INCH);
+    private void setContextAndFont(DrawingContext ctx) {
+        if (graphicsIsExclusive && cachedContext == ctx) {
+            return;
+        }
+        setContext(ctx);
+        float fontSize = (float) ((ctx.getFontSize() / INCH_TO_POINTS_FACTOR) * AWT_POINTS_IN_INCH);
         Font font = new Font(getFontName(ctx.getFontFamily()), getAwtFontStyle(ctx.getFontStyle()), 1).deriveFont(fontSize);
         graphics.setFont(font);
     }
 
+    // Transformation of DrawingContext data types to AWT constants
+
     private String getFontName(String gridFontFamily) {
         if (gridFontFamily == null) {
             return null;
@@ -240,19 +266,11 @@ public final class JFrameDevice implements GridDevice {
         }
     }
 
-    private <T> T noTransform(Supplier<T> action) {
-        AffineTransform transform = graphics.getTransform();
-        graphics.setTransform(new AffineTransform());
-        T result = action.get();
-        graphics.setTransform(transform);
-        return result;
-    }
-
     private static Color fromGridColor(GridColor color) {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
 
-    private static BasicStroke getStrokeFromCtx(DrawingContext ctx) {
+    private BasicStroke getStrokeFromCtx(DrawingContext ctx) {
         byte[] type = ctx.getLineType();
         double width = ctx.getLineWidth();
         int lineJoin = fromGridLineJoin(ctx.getLineJoin());
@@ -261,16 +279,13 @@ public final class JFrameDevice implements GridDevice {
         if (type == DrawingContext.GRID_LINE_BLANK) {
             return blankStroke;
         } else if (type == DrawingContext.GRID_LINE_SOLID) {
-            if (width == 1. && solidStroke.getLineJoin() == lineJoin && solidStroke.getMiterLimit() == lineMitre && solidStroke.getEndCap() == endCap) {
-                return solidStroke;
-            }
-            return new BasicStroke((float) (width / POINTS_IN_INCH), endCap, lineJoin, lineMitre);
+            return new BasicStroke((float) (width), endCap, lineJoin, lineMitre);
         }
         float[] pattern = new float[type.length];
         for (int i = 0; i < pattern.length; i++) {
-            pattern[i] = (float) (type[i] / POINTS_IN_INCH);
+            pattern[i] = (float) (type[i]);
         }
-        return new BasicStroke((float) (width / POINTS_IN_INCH), endCap, lineJoin, lineMitre, pattern, 0f);
+        return new BasicStroke((float) (width), endCap, lineJoin, lineMitre, pattern, 0f);
     }
 
     private static int fromGridLineEnd(GridLineEnd lineEnd) {
@@ -298,49 +313,4 @@ public final class JFrameDevice implements GridDevice {
                 throw RInternalError.shouldNotReachHere("unexpected value of GridLineJoin enum");
         }
     }
-
-    private static void initStrokes() {
-        if (solidStroke != null) {
-            return;
-        }
-        solidStroke = new BasicStroke((float) (1f / POINTS_IN_INCH));
-        blankStroke = new BasicStroke(0f);
-    }
-
-    static class FastRFrame extends JFrame {
-        private static final long serialVersionUID = 1L;
-        private final Dimension framePreferredSize = new Dimension(720, 720);
-        private final JPanel fastRComponent = new JPanel();
-
-        FastRFrame() throws HeadlessException {
-            super("FastR");
-            addCloseListener();
-            createUI();
-            center();
-        }
-
-        private void createUI() {
-            setLayout(new BorderLayout());
-            setSize(framePreferredSize);
-            add(fastRComponent, BorderLayout.CENTER);
-            fastRComponent.setPreferredSize(getSize());
-        }
-
-        private void addCloseListener() {
-            addWindowFocusListener(new WindowAdapter() {
-                @Override
-                public void windowClosing(WindowEvent e) {
-                    dispose();
-                }
-            });
-        }
-
-        private void center() {
-            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
-            Dimension frameSize = getSize();
-            int x = (screenSize.width - frameSize.width) / 2;
-            int y = (screenSize.height - frameSize.height) / 2;
-            setLocation(x, y);
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
new file mode 100644
index 0000000000..6e31f1f417
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device.awt;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.HeadlessException;
+import java.awt.RenderingHints;
+import java.awt.Toolkit;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+public final class JFrameDevice extends Graphics2DDevice {
+    private final JFrame currentFrame;
+    private final boolean disposeResources;
+
+    /**
+     * @param frame The frame that should be used for drawing.
+     * @param graphics The graphics object that should be used for drawing. This constructor
+     *            overload allows to initialize the graphics object.
+     * @param disposeResources Should the frame and graphics objects be disposed at {@link #close()}
+     *            .
+     */
+    private JFrameDevice(JFrame frame, Graphics2D graphics, boolean disposeResources) {
+        super(graphics, frame.getContentPane().getWidth(), frame.getContentPane().getHeight(), true);
+        currentFrame = frame;
+        this.disposeResources = disposeResources;
+    }
+
+    /**
+     * Creates a standalone device that manages the window itself and closes it once
+     * {@link #close()} gets called.
+     */
+    public static JFrameDevice create() {
+        FastRFrame frame = new FastRFrame();
+        frame.setVisible(true);
+        Graphics2D graphics = (Graphics2D) frame.getGraphics();
+        defaultInitGraphics(graphics);
+        return new JFrameDevice(frame, graphics, true);
+    }
+
+    @Override
+    public void close() throws DeviceCloseException {
+        if (disposeResources) {
+            getGraphics2D().dispose();
+            currentFrame.dispose();
+        }
+    }
+
+    JFrame getCurrentFrame() {
+        return currentFrame;
+    }
+
+    static void defaultInitGraphics(Graphics2D graphics) {
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+    }
+
+    static class FastRFrame extends JFrame {
+        private static final long serialVersionUID = 1L;
+        private final Dimension framePreferredSize = new Dimension(720, 720);
+        private final JPanel fastRComponent = new JPanel();
+
+        FastRFrame() throws HeadlessException {
+            super("FastR");
+            addCloseListener();
+            createUI();
+            center();
+        }
+
+        private void createUI() {
+            setLayout(new BorderLayout());
+            setSize(framePreferredSize);
+            add(fastRComponent, BorderLayout.CENTER);
+            fastRComponent.setPreferredSize(getSize());
+        }
+
+        private void addCloseListener() {
+            addWindowFocusListener(new WindowAdapter() {
+                @Override
+                public void windowClosing(WindowEvent e) {
+                    dispose();
+                }
+            });
+        }
+
+        private void center() {
+            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+            Dimension frameSize = getSize();
+            int x = (screenSize.width - frameSize.width) / 2;
+            int y = (screenSize.height - frameSize.height) / 2;
+            setLocation(x, y);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
new file mode 100644
index 0000000000..e0d57b606a
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public abstract class DevOff extends RExternalBuiltinNode.Arg1 {
+    static {
+        Casts casts = new Casts(DevOff.class);
+        casts.arg(0).asIntegerVector().findFirst();
+    }
+
+    public static DevOff create() {
+        return DevOffNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    public Object devOff(int whichR) {
+        GridContext ctx = GridContext.getContext();
+        int which = whichR - 1; // convert to Java index
+        if (which < 0 || which >= ctx.getDevicesSize()) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "Wrong device number.");
+        }
+        try {
+            ctx.closeDevice(which);
+        } catch (DeviceCloseException e) {
+            throw error(Message.GENERIC, "Cannot close the device. Details: " + e.getMessage());
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 157212f385..f1fab85632 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -22,18 +22,24 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
+import java.io.IOException;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
-import com.oracle.truffle.r.library.fastrGrid.device.BufferedJFrameDevice;
-import com.oracle.truffle.r.library.fastrGrid.device.JFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 /**
  * Node that handles the {@code C_X11} external calls. Those calls may be initiated from either the
- * {@code X11} function or FastR specific {@code awt} function. In either case the result is that
- * the AWT window is opened and ready for drawing.
+ * {@code X11}, {@code jpeg}, {@code bmp}, {@code png} functions and from FastR specific {@code awt}
+ * . The arguments determine which device should be opened.
  */
 public final class InitWindowedDevice extends RExternalBuiltinNode {
     static {
@@ -43,7 +49,28 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
     @Override
     @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
-        GridContext.getContext().setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo", new BufferedJFrameDevice(new JFrameDevice()));
+        // if the first argument is a String, then it may describes the image format and filename to
+        // use, the format is e.g. "jpeg::quality:filename"
+        if (args.getLength() >= 1) {
+            String name = RRuntime.asString(args.getArgument(0));
+            if (!RRuntime.isNA(name) && name.contains("::")) {
+                return openImageDevice(name);
+            }
+        }
+        // otherwise the
+        GridContext.getContext().setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo", new BufferedJFrameDevice(JFrameDevice.create()));
+        return RNull.instance;
+    }
+
+    private Object openImageDevice(String name) {
+        String formatName = name.substring(0, name.indexOf("::"));
+        String filename = name.substring(name.lastIndexOf(':') + 1);
+        try {
+            BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, 700, 700);
+            GridContext.getContext().setCurrentDevice(formatName, device);
+        } catch (NotSupportedImageFormatException e) {
+            throw error(Message.GENERIC, String.format("Format '%s' is not supported.", formatName));
+        }
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
index 2482fb35e3..f99012e978 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
@@ -62,6 +62,7 @@ public final class RGridGraphicsAdapter {
     }
 
     public static void initialize() {
+        addDevice(NULL_DEVICE);
         setCurrentDevice(NULL_DEVICE);
         ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
         try {
@@ -71,7 +72,27 @@ public final class RGridGraphicsAdapter {
         }
     }
 
+    public static void removeDevice(int index) {
+        assert index > 0 : "cannot remove null device";
+        REnvironment baseEnv = REnvironment.baseEnv();
+        RPairList devices = (RPairList) baseEnv.get(DOT_DEVICES);
+        assert index < devices.getLength() : "wrong index in removeDevice";
+        RPairList prev = devices;
+        for (int i = 0; i < index - 1; ++i) {
+            prev = (RPairList) prev.cdr();
+        }
+        RPairList toRemove = (RPairList) prev.cdr();
+        prev.setCdr(toRemove.cdr());
+        setCurrentDevice((String) prev.car());
+    }
+
     public static void setCurrentDevice(String name) {
+        REnvironment baseEnv = REnvironment.baseEnv();
+        assert contains((RPairList) baseEnv.get(DOT_DEVICES), name) : "setCurrentDevice can be invoked only after the device is added with addDevice";
+        baseEnv.safePut(DOT_DEVICE, name);
+    }
+
+    public static void addDevice(String name) {
         REnvironment baseEnv = REnvironment.baseEnv();
         baseEnv.safePut(DOT_DEVICE, name);
         Object dotDevices = baseEnv.get(DOT_DEVICES);
@@ -100,4 +121,13 @@ public final class RGridGraphicsAdapter {
         RPairList dotDevices = (RPairList) REnvironment.baseEnv().get(DOT_DEVICES);
         return RRuntime.asString(dotDevices.getDataAtAsObject(index));
     }
+
+    private static boolean contains(RPairList devices, String name) {
+        for (RPairList dev : devices) {
+            if (dev.car().equals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
-- 
GitLab


From 87516f039427b89399f609dc1969e19764f07723 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 28 Mar 2017 11:48:07 +0200
Subject: [PATCH 194/402] FastR Grid: more complete dev.* functions support

* support for closing and re-opening the devices including the windowed AWT based device
---
 .../r/library/fastrGrid/GridContext.java      | 23 ++++++++---
 .../r/library/fastrGrid/GridState.java        | 41 +++++++++++--------
 .../r/library/fastrGrid/LGridDirty.java       |  2 +
 .../device/awt/BufferedJFrameDevice.java      |  5 +++
 4 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index d16589172b..356fc3173b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import java.util.ArrayList;
 
+import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
@@ -38,15 +39,14 @@ import com.oracle.truffle.r.runtime.RError.Message;
 public final class GridContext {
     private static final GridContext INSTANCE = new GridContext();
     private final GridState gridState = new GridState();
-
     /**
      * This list should correspond to the names inside {@code .Devices} variable in R.
      */
-    private final ArrayList<GridDevice> devices = new ArrayList<>(2);
+    private final ArrayList<DeviceAndState> devices = new ArrayList<>(2);
     private int currentDeviceIdx = 0;
 
     private GridContext() {
-        devices.add(null);
+        devices.add(new DeviceAndState(null));
     }
 
     public static GridContext getContext() {
@@ -54,6 +54,7 @@ public final class GridContext {
     }
 
     public GridState getGridState() {
+        gridState.setDeviceState(devices.get(currentDeviceIdx).state);
         return gridState;
     }
 
@@ -67,14 +68,14 @@ public final class GridContext {
 
     public GridDevice getCurrentDevice() {
         assert currentDeviceIdx >= 0 : "accessing devices before they were initialized";
-        return devices.get(currentDeviceIdx);
+        return devices.get(currentDeviceIdx).device;
     }
 
     public void setCurrentDevice(String name, GridDevice currentDevice) {
         RGridGraphicsAdapter.addDevice(name);
         RGridGraphicsAdapter.setCurrentDevice(name);
         currentDeviceIdx = this.devices.size();
-        this.devices.add(currentDevice);
+        this.devices.add(new DeviceAndState(currentDevice));
         assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
     }
 
@@ -91,11 +92,21 @@ public final class GridContext {
 
     public void closeDevice(int which) throws DeviceCloseException {
         assert which >= 0 && which < devices.size();
-        devices.get(which).close();
+        devices.get(which).device.close();
         RGridGraphicsAdapter.removeDevice(which);
         devices.remove(which);
         if (currentDeviceIdx >= which) {
             currentDeviceIdx--;
         }
     }
+
+    private static final class DeviceAndState {
+        final GridDevice device;
+        final GridDeviceState state;
+
+        DeviceAndState(GridDevice device) {
+            this.device = device;
+            this.state = new GridDeviceState();
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 9cab0c14d7..deab204f3b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -17,12 +17,8 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 public final class GridState {
-    private RList gpar;
-    private RList viewPort;
     private REnvironment gridEnv;
-    private double scale = 1;
-    private boolean deviceInitialized;
-    private int devHoldCount;
+    private GridDeviceState devState;
 
     /**
      * Current grob being drawn (for determining the list of grobs to search when evaluating a
@@ -33,12 +29,16 @@ public final class GridState {
     GridState() {
     }
 
+    void setDeviceState(GridDeviceState state) {
+        devState = state;
+    }
+
     public int getDevHoldCount() {
-        return devHoldCount;
+        return devState.devHoldCount;
     }
 
     public int setDevHoldCount(int devHoldCount) {
-        this.devHoldCount = devHoldCount;
+        devState.devHoldCount = devHoldCount;
         return devHoldCount;
     }
 
@@ -48,7 +48,7 @@ public final class GridState {
     }
 
     void initGPar(GridDevice currentDevice) {
-        gpar = GPar.createNew(currentDevice);
+        devState.gpar = GPar.createNew(currentDevice);
     }
 
     /**
@@ -61,31 +61,33 @@ public final class GridState {
 
     public RList getGpar() {
         assert gridEnv != null : "GridState not initialized";
-        return gpar;
+        return devState.gpar;
     }
 
     public void setGpar(RList gpar) {
         assert gridEnv != null : "GridState not initialized";
-        this.gpar = gpar;
+        devState.gpar = gpar;
     }
 
     /**
-     * Has the current device been initialized for use by grid?
+     * Has the current device been initialized for use by grid? Note: the null device should never
+     * get initialized. The code initializing device should check if any device is open and if not,
+     * it should open the default device and initialize it.
      */
     public boolean isDeviceInitialized() {
-        return deviceInitialized;
+        return devState.isDeviceInitialized;
     }
 
     public void setDeviceInitialized() {
-        this.deviceInitialized = true;
+        devState.isDeviceInitialized = true;
     }
 
     public RList getViewPort() {
-        return viewPort;
+        return devState.viewPort;
     }
 
     public void setViewPort(RList viewPort) {
-        this.viewPort = viewPort;
+        devState.viewPort = viewPort;
     }
 
     public REnvironment getGridEnv() {
@@ -101,7 +103,14 @@ public final class GridState {
     }
 
     public double getScale() {
-        return scale;
+        return devState.scale;
     }
 
+    static final class GridDeviceState {
+        private boolean isDeviceInitialized = false;
+        private RList gpar;
+        private RList viewPort;
+        private double scale = 1;
+        private int devHoldCount;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index fd9abe3ff0..a6314dff2c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -39,6 +39,8 @@ final class LGridDirty extends RExternalBuiltinNode {
         // if no device has been opened yet, open the default one and make it current
         if (GridContext.getContext().getCurrentDevice() == null) {
             GridContext.getContext().openDefaultDevice();
+            gridState = GridContext.getContext().getGridState();    // grid state is device
+                                                                    // dependent
         }
 
         // the current device has not been initialized yet...
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
index d6a7270acd..b94f4e39aa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
@@ -109,6 +109,11 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
         buffer = null;
     }
 
+    @Override
+    public void close() throws DeviceCloseException {
+        inner.close();
+    }
+
     @Override
     public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) {
         inner.drawRect(ctx, leftX, bottomY, width, height, rotationAnticlockWise);
-- 
GitLab


From a0b337e0b958a39382e8bd99ee50f799616506aa Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 28 Mar 2017 15:04:07 +0200
Subject: [PATCH 195/402] FastR Grid: more precise string height and text
 drawing

---
 .../truffle/r/library/fastrGrid/Unit.java       | 17 +++++++++++++++--
 .../r/library/fastrGrid/device/GridDevice.java  | 10 ++++------
 .../fastrGrid/device/awt/Graphics2DDevice.java  |  7 +++++--
 3 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 8d8dd780d0..f881cc7081 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -185,6 +185,9 @@ public final class Unit {
 
     private static double convertToInches(double value, int index, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
         double vpSize = ctx.getViewPortSize(axisOrDim);
+        String str;
+        String[] lines;
+        double result = 0;
         switch (unitId) {
             case INCHES:
                 return value;
@@ -207,10 +210,20 @@ public final class Unit {
                 return (value * ctx.gpar.getDrawingContext(index).getFontSize() * ctx.gpar.getDrawingContext(index).getLineHeight()) / INCH_TO_POINTS_FACTOR;
             case STRINGWIDTH:
             case MYSTRINGWIDTH:
-                return ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), RRuntime.asString(data.getDataAt(0)));
+                str = RRuntime.asString(data.getDataAt(0));
+                lines = str.split("\n");
+                for (int i = 0; i < lines.length; i++) {
+                    result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), lines[i]));
+                }
+                return result;
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
-                return ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), RRuntime.asString(data.getDataAt(0)));
+                str = RRuntime.asString(data.getDataAt(0));
+                lines = str.split("\n");
+                for (int i = 0; i < lines.length; i++) {
+                    result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), lines[i]);
+                }
+                return result;
             case NULL:
                 return evaluateNullUnit(value, vpSize, ctx.nullLayoutMode, ctx.nullArithmeticMode);
             default:
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 53f08304db..90a2dcd6e9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -106,13 +106,11 @@ public interface GridDevice {
     double getStringWidth(DrawingContext ctx, String text);
 
     /**
-     * Gets the height of a line of text in inches, the default implementation uses only the
-     * parameters from the drawing context, but we allow the device to override this calculation
-     * with something more precise.
+     * Gets the height of a line of text in inches. This should include ascent and descent, i.e.
+     * from the very bottom to the very top of the tallest letter(s). The text is guaranteed to not
+     * contain any new lines.
      */
-    default double getStringHeight(DrawingContext ctx, String text) {
-        return (ctx.getLineHeight() * ctx.getFontSize()) / INCH_TO_POINTS_FACTOR;
-    }
+    double getStringHeight(DrawingContext ctx, String text);
 
     final class DeviceCloseException extends Exception {
         private static final long serialVersionUID = 1182697755931636214L;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
index 74540e4d11..055084a451 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
@@ -28,6 +28,7 @@ import static java.awt.geom.Path2D.WIND_EVEN_ODD;
 import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Font;
+import java.awt.FontMetrics;
 import java.awt.Graphics2D;
 import java.awt.Paint;
 import java.awt.Shape;
@@ -128,7 +129,8 @@ public class Graphics2DDevice implements GridDevice {
     public void drawString(DrawingContext ctx, double leftXIn, double bottomYIn, double rotationAnticlockWise, String text) {
         setContextAndFont(ctx);
         int leftX = transX(leftXIn);
-        int bottomY = transY(bottomYIn);
+        FontMetrics fontMetrics = graphics.getFontMetrics(graphics.getFont());
+        int bottomY = transY(bottomYIn) - fontMetrics.getDescent();
         transformed(leftX, bottomY, rotationAnticlockWise, () -> graphics.drawString(text, 0, 0));
     }
 
@@ -152,7 +154,8 @@ public class Graphics2DDevice implements GridDevice {
     @Override
     public double getStringHeight(DrawingContext ctx, String text) {
         setContextAndFont(ctx);
-        int swingUnits = graphics.getFont().getSize();
+        FontMetrics fontMetrics = graphics.getFontMetrics(graphics.getFont());
+        double swingUnits = fontMetrics.getAscent() + fontMetrics.getDescent();
         return swingUnits / AWT_POINTS_IN_INCH;
     }
 
-- 
GitLab


From d8b2a2ef821d70daf58ea501636f0f6788949682 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Tue, 28 Mar 2017 17:52:09 +0200
Subject: [PATCH 196/402] Fixes made when integrating the checkpoint package

---
 .../truffle/r/library/utils/Download.java     | 76 +++++++++++++------
 .../r/nodes/builtin/base/Readline.java        |  3 +
 .../r/nodes/castsTests/CastBuilderTest.java   |  2 +
 .../analysis/ForwardedValuesAnalyser.java     |  2 +-
 .../r/nodes/function/ClassHierarchyNode.java  |  6 ++
 .../nodes/function/signature/MissingNode.java |  9 ++-
 .../truffle/r/test/ExpectedTestOutput.test    |  4 +
 .../r/test/builtins/TestBuiltin_missing.java  |  4 +-
 mx.fastr/copyrights/overrides                 |  1 +
 9 files changed, 81 insertions(+), 26 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
index b51d2be570..e3b26dca3d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
@@ -1,24 +1,13 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2013,  The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
  *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
+ * All rights reserved.
  */
 package com.oracle.truffle.r.library.utils;
 
@@ -30,7 +19,9 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLConnection;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
@@ -40,6 +31,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.conn.StdConnections;
 
 /**
  * Support for the "internal"method of "utils::download.file". TODO take note of "quiet", "mode" and
@@ -59,12 +51,52 @@ public abstract class Download extends RExternalBuiltinNode.Arg5 {
 
     @Specialization
     @TruffleBoundary
-    protected int download(String urlString, String destFile, @SuppressWarnings("unused") boolean quiet, @SuppressWarnings("unused") String mode, @SuppressWarnings("unused") boolean cacheOK) {
+    protected int download(String urlString, String destFile, boolean quiet, @SuppressWarnings("unused") String mode, @SuppressWarnings("unused") boolean cacheOK) {
         try {
-            try (InputStream in = new URL(urlString).openStream()) {
-                Files.copy(in, Paths.get(destFile), StandardCopyOption.REPLACE_EXISTING);
+            URLConnection con = new URL(urlString).openConnection();
+            try (InputStream in = con.getInputStream()) {
+                long len = Files.copy(in, Paths.get(destFile), StandardCopyOption.REPLACE_EXISTING);
+                if (!quiet) {
+
+                    String contentType = null;
+                    if (con instanceof HttpURLConnection) {
+                        HttpURLConnection httpCon = (HttpURLConnection) con;
+                        contentType = httpCon.getContentType();
+                    }
+
+                    // Transcribed from GnuR, src/modules/internet/internet.c
+
+                    StdConnections.getStderr().writeString(String.format("Content type '%s'", contentType != null ? contentType : "unknown"), false);
+                    if (len > 1024 * 1024) {
+                        StdConnections.getStderr().writeString(String.format(" length %0.0f bytes (%0.1f MB)", (double) len, len / 1024.0 / 1024.0), true);
+                    } else if (len > 10240) {
+                        StdConnections.getStderr().writeString(String.format(" length %d bytes (%d KB)", len, len / 1024), true);
+                    } else if (len >= 0) {
+                        StdConnections.getStderr().writeString(String.format(" length %d bytes", len), true);
+                    } else {
+                        StdConnections.getStderr().writeString(" length unknown", true);
+                    }
+                    StdConnections.getStderr().flush();
+                }
+
+                return 0;
+            } catch (IOException e) {
+                if (!quiet) {
+
+                    // Transcribed from GnuR, src/modules/internet/internet.c
+
+                    int responseCode = -1;
+                    String responseMsg = null;
+                    if (con instanceof HttpURLConnection) {
+                        HttpURLConnection httpCon = (HttpURLConnection) con;
+                        responseCode = httpCon.getResponseCode();
+                        responseMsg = httpCon.getResponseMessage();
+                    }
+
+                    warning(RError.Message.GENERIC, String.format("cannot open URL '%s': HTTP status was '%d %s'", urlString, responseCode, responseMsg != null ? responseMsg : ""));
+                }
+                throw e;
             }
-            return 0;
         } catch (IOException e) {
             throw error(RError.Message.GENERIC, e.getMessage());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
index bc5411859c..8f51dffb91 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
@@ -51,6 +51,9 @@ public abstract class Readline extends RBuiltinNode {
         String savedPrompt = consoleHandler.getPrompt();
         consoleHandler.setPrompt(prompt.getDataAt(0));
         String input = consoleHandler.readLine();
+        // The readLine method always appends the newline character, as opposed to the readline
+        // builtin. Therefore, the trailing newline must be cut off.
+        input = input.substring(0, input.length() - 1);
         consoleHandler.setPrompt(savedPrompt);
         return input;
     }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
index 5e36f005de..218c1393bd 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
@@ -565,6 +565,8 @@ public class CastBuilderTest {
     public void testMustBeSquareMatrix() {
         arg.asDoubleVector(true, true, true).mustBe(squareMatrix());
 
+        assertCastFail(1.0);
+
         RIntVector vec = RDataFactory.createIntVector(new int[]{0, 1, 2, 3}, true, new int[]{2, 2});
         Object res = cast(vec);
         assertTrue(res instanceof RAbstractDoubleVector);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
index e85a6f5363..4eb716c6cc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardedValuesAnalyser.java
@@ -260,7 +260,7 @@ public final class ForwardedValuesAnalyser implements PipelineStepVisitor<Forwar
 
             @Override
             public ForwardingAnalysisResult visit(MatrixFilter<?> filter, @SuppressWarnings("hiding") ForwardingAnalysisResult previous) {
-                return new ForwardingAnalysisResult().forwardAll();
+                return new ForwardingAnalysisResult().blockAll();
             }
 
             @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index dd4a98c595..b11b3c9f7f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -46,6 +46,7 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
@@ -110,6 +111,11 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return withImplicitTypes ? RNull.implicitClassHeader : null;
     }
 
+    @Specialization
+    protected RStringVector getClassHr(@SuppressWarnings("unused") REmpty arg) {
+        return withImplicitTypes ? RNull.implicitClassHeader : null;
+    }
+
     @Specialization
     protected RStringVector getClassHrAttributable(RAttributable arg,
                     @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
index abc8291e09..f7f09332ee 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
@@ -46,6 +46,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 
@@ -201,10 +202,14 @@ public final class MissingNode extends OperatorNode {
                 throw error(Message.ARGUMENTS_PASSED, args.length, "'missing'", 1);
             }
             RSyntaxElement arg = args[0];
-            if (!(arg instanceof RSyntaxLookup)) {
+            String identifier;
+            if (arg instanceof RSyntaxConstant && ((RSyntaxConstant) arg).getValue() instanceof String) {
+                identifier = (String) ((RSyntaxConstant) arg).getValue();
+            } else if (arg instanceof RSyntaxLookup) {
+                identifier = ((RSyntaxLookup) arg).getIdentifier();
+            } else {
                 throw error(Message.INVALID_USE, "missing");
             }
-            String identifier = ((RSyntaxLookup) arg).getIdentifier();
             if (ArgumentsSignature.VARARG_NAME.equals(identifier)) {
                 readVarArgs = insert(LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false));
             } else {
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 8e341d3b4c..8721518a96 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
@@ -36430,6 +36430,10 @@ Levels: A < B < C
 #{ f <- function(a) { g(a) } ; g <- function(b=2) { missing(b) } ; f() }
 [1] TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_missing.testMissing#
+#{ f <- function(a) { missing("a") };  f(); f(1) }
+[1] FALSE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_missing.testMissing#
 #{ f <- function(a,b,c) { missing(b) } ; f(1,,2) }
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java
index 2de37d13ee..b7558998d1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_missing.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -47,5 +47,7 @@ public class TestBuiltin_missing extends TestBase {
         assertEval("{ f <- function(x) { print(missing(x)); g(x) }; g <- function(y=3) { print(missing(y)); k(y) }; k <- function(l=4) { print(missing(l)); l }; f() }");
         assertEval("{ f <- function(x) { print(missing(x)) ; g(x) } ; g <- function(y=1) { print(missing(y)) ; h(y) } ; h <- function(z) { print(missing(z)) ; z } ; f() }");
         assertEval("{ f <- function(a,b,c,d,e,env) (length(objects(env, all.names = TRUE, pattern = \"^[.]__[CTA]_\"))); f2 <- function(env) (length(objects(env, all.names = TRUE, pattern = \"^[.]__[CTA]_\"))); f(); f2() }");
+
+        assertEval("{ f <- function(a) { missing(\"a\") };  f(); f(1) }");
     }
 }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index eaa941e25e..a09bd8bac8 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -767,3 +767,4 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java,gnu_r_gentleman_ihaka2.copyright
-- 
GitLab


From f2ead0358164ec518d036a26166456b611240600 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 28 Mar 2017 12:31:19 -0700
Subject: [PATCH 197/402] pkgtest: create test.diffs directory

---
 documentation/dev/testing.md |  4 +++-
 mx.fastr/mx_fastr_pkgs.py    | 44 +++++++++++-------------------------
 2 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index 45c3893fa8..a5a2718be1 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -186,7 +186,9 @@ Override the blacklist and attempt to install the `Rcpp` package. N.B. The regul
 
 #### The mx pkgtest command
 
-The `mx pkgtest` command is a wrapper on `mx installpkgs` that forces the `--run-tests` option and also executes the same tests under GnuR and compares the results. In order to run the tests under GnuR, the `gnur` suite must be installed as a sibling to `fastr`.
+The `mx pkgtest` command is a wrapper on `mx installpkgs` that forces the `--run-tests` option and also executes the same tests under GnuR and compares the results. The packages are installed into `lib.install.packages.fastr` and `lib.install.packages.gnur`, respectively and the test results are stored in `test.fastr` and `test.gnur`, respectively. The differences between the results, computed using `diff -r`,  are stored per package in the `test.diffs` directory. All these directories are cleaned and re-created at the start of the run.
+
+By default the local build of FastR and the internal GNU R that is built as part of the FastR build are used to run the tests. However, when `FASTR_GRAALVM` is set to the location of a `GraalVM` binary installation, that is used for FastR and the `gnur` suite must be installed and built as a sibling to `fastr`.
 
 #### Running/Debugging Tests Locally
 
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index 9a489fd72b..0e7fe3319f 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -91,10 +91,14 @@ def _create_libinstall(rvm, test_installed):
 #    install_tmp = join(_fastr_suite_dir(), "install.tmp")
     shutil.rmtree(install_tmp, ignore_errors=True)
     os.mkdir(install_tmp)
+    _create_testdot(rvm)
+    return libinstall, install_tmp
+
+def _create_testdot(rvm):
     testdir = join(_fastr_suite_dir(), "test." + rvm)
     shutil.rmtree(testdir, ignore_errors=True)
     os.mkdir(testdir)
-    return libinstall, install_tmp, testdir
+    return testdir
 
 def _log_step(state, step, rvariant):
     if not quiet:
@@ -149,8 +153,8 @@ def pkgtest(args):
     '''
 
     test_installed = '--no-install' in args
-    fastr_libinstall, fastr_install_tmp, fastr_testdir = _create_libinstall('fastr', test_installed)
-    gnur_libinstall, gnur_install_tmp, gnur_testdir = _create_libinstall('gnur', test_installed)
+    fastr_libinstall, fastr_install_tmp = _create_libinstall('fastr', test_installed)
+    gnur_libinstall, gnur_install_tmp = _create_libinstall('gnur', test_installed)
 
     if "--quiet" in args:
         global quiet
@@ -227,7 +231,7 @@ def pkgtest(args):
             install_args += ['--print-install-status']
 
     _log_step('BEGIN', 'install/test', 'FastR')
-    # Currently installpkgs does not set a return code (in install.packages.packages.R)
+    # Currently installpkgs does not set a return code (in install.packages.R)
     rc = _installpkgs(install_args, nonZeroIsFatal=False, env=env, out=out, err=out)
     if rc == 100:
         # fatal error connecting to package repo
@@ -253,36 +257,14 @@ def pkgtest(args):
                 rc = rc | 2
             print '{0}: {1}'.format(pkg, test_status.status)
 
-        # tar up the test results
-        tar_tests(fastr_testdir)
-        tar_tests(gnur_testdir)
+        diffdir = _create_testdot('diffs')
+        for pkg, _ in out.test_info.iteritems():
+            diff_file = join(diffdir, pkg)
+            subprocess.call(['diff', '-r', _pkg_testdir('fastr', pkg), _pkg_testdir('gnur', pkg)], stdout=open(diff_file, 'w'))
 
     shutil.rmtree(fastr_install_tmp, ignore_errors=True)
     return rc
 
-def tar_tests(testdir):
-    if os.environ.has_key('FASTR_TEST_GZIP'):
-        test_tar = testdir + '.tar'
-        subprocess.call(['tar', 'cf', test_tar, os.path.basename(testdir)])
-        if os.path.exists(test_tar + '.gz'):
-            os.remove(test_tar + '.gz')
-        subprocess.call(['gzip', test_tar])
-    else:
-        # workaround for lack of support for accessing gz files
-        with open(testdir + '.agg', 'w') as o:
-            for root, _, files in os.walk(testdir):
-                for f in files:
-                    ext = os.path.splitext(f)[1]
-                    if f == 'test_time' or f == 'testfile_status' or ext == '.pdf' or ext == '.prev' or ext == '.save':
-                        continue
-                    absfile = join(root, f)
-                    relfile = relpath(absfile, _fastr_suite_dir())
-                    o.write('#### ' + relfile + '\n')
-                    with open(absfile) as inp:
-                        text = inp.read()
-                        o.write(text)
-
-
 class TestFileStatus:
     '''
     Records the status of a test file. status is either "OK" or "FAILED".
@@ -341,7 +323,7 @@ def _args_to_forward_to_gnur(args):
 
 def _gnur_install_test(forwarded_args, pkgs, gnur_libinstall, gnur_install_tmp):
     '''
-    Install/test with GNU R  exactly those packages that installe3d correctly with FastR.
+    Install/test with GNU R  exactly those packages that installed correctly with FastR.
     N.B. That means that regardless of how the packages were specified to pkgtest
     we always use a --pkg-filelist' arg to GNU R
     '''
-- 
GitLab


From 997f7f2095f44cba1c205c8879d7cc6bc06eed78 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 28 Mar 2017 17:27:40 -0700
Subject: [PATCH 198/402] change to more stable check for a FastR R_HOME

---
 .../oracle/truffle/r/runtime/REnvVars.java    | 24 +++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index dac1239411..639f77c174 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -34,6 +34,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -160,10 +161,10 @@ public final class REnvVars implements RContext.ContextState {
     private static String rHome;
 
     /**
-     * Returns a file that only exists in a FastR {@code R_HOME}.
+     * Returns a file that serves to distinguish a FastR {@code R_HOME}.
      */
     private static String markerFile() {
-        return "libjniboot." + (isMacOS() ? "dylib" : "so");
+        return "Makeconf";
     }
 
     /**
@@ -217,8 +218,23 @@ public final class REnvVars implements RContext.ContextState {
         if (path == null) {
             return false;
         }
-        Path lib = path.resolve("lib");
-        return Files.exists(lib) && Files.isDirectory(lib) && Files.exists(lib.resolve(markerFile));
+        Path etc = path.resolve("etc");
+        Path absMarkerFile = etc.resolve(markerFile);
+        return Files.exists(etc) && Files.isDirectory(etc) && Files.exists(absMarkerFile) && isFastR(absMarkerFile);
+    }
+
+    private static boolean isFastR(Path makeconf) {
+        try {
+            List<String> lines = Files.readAllLines(makeconf);
+            for (String line : lines) {
+                if (line.startsWith("CFLAGS")) {
+                    return line.contains("-DFASTR");
+                }
+            }
+        } catch (IOException ex) {
+            throw RInternalError.shouldNotReachHere();
+        }
+        return false;
     }
 
     private void checkRHome() {
-- 
GitLab


From f3b634e8ee9f9637311d0eb09c3ed3f6e3f33fa9 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 28 Mar 2017 17:58:32 +0200
Subject: [PATCH 199/402] FastR Grid: display list support

---
 .../r/library/fastrGrid/DisplayList.java      | 108 ++++++++++++++++++
 .../fastrGrid/FastRGridExternalLookup.java    |  26 +++--
 .../r/library/fastrGrid/GridState.java        |  36 ++++++
 .../r/library/fastrGrid/LGridDirty.java       |   2 +-
 .../library/fastrGrid/device/GridDevice.java  |   2 -
 .../fastrGrid/device/awt/JFrameDevice.java    |   1 +
 .../grDevices/InitWindowedDevice.java         |   2 -
 7 files changed, 164 insertions(+), 13 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java
new file mode 100644
index 0000000000..06f33e2aa3
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
+import java.util.Arrays;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.DisplayListFactory.LGetDisplayListElementNodeGen;
+import com.oracle.truffle.r.library.fastrGrid.DisplayListFactory.LSetDisplayListOnNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class DisplayList {
+    private static final int INITIAL_DL_SIZE = 100;
+
+    static RList createInitialDisplayList() {
+        Object[] data = new Object[INITIAL_DL_SIZE];
+        Arrays.fill(data, 0, data.length, RNull.instance);
+        RList list = RDataFactory.createList(data);
+        list.makeSharedPermanent();
+        return list;
+    }
+
+    static void initDisplayList(GridState gridState) {
+        RList list = createInitialDisplayList();
+        list.setDataAt(list.getInternalStore(), 0, gridState.getViewPort());
+        gridState.setDisplayList(list);
+        gridState.setDisplayListIndex(1);
+    }
+
+    public abstract static class LGetDisplayListElement extends RExternalBuiltinNode.Arg1 {
+        static {
+            Casts casts = new Casts(LGetDisplayListElement.class);
+            casts.arg(0).asIntegerVector().findFirst();
+        }
+
+        public static LGetDisplayListElement create() {
+            return LGetDisplayListElementNodeGen.create();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        Object getDLElement(int index) {
+            return GridContext.getContext().getGridState().getDisplayList().getDataAt(index);
+        }
+    }
+
+    public abstract static class LSetDisplayListOn extends RExternalBuiltinNode.Arg1 {
+        static {
+            Casts casts = new Casts(LSetDisplayListOn.class);
+            casts.arg(0).asLogicalVector().findFirst().map(toBoolean());
+        }
+
+        public static LSetDisplayListOn create() {
+            return LSetDisplayListOnNodeGen.create();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        byte setDLOn(boolean value) {
+            GridState gridState = GridContext.getContext().getGridState();
+            boolean result = gridState.isDisplayListOn();
+            gridState.setIsDisplayListOn(value);
+            return RRuntime.asLogical(result);
+        }
+    }
+
+    public static final class LInitDisplayList extends RExternalBuiltinNode.Arg0 {
+        static {
+            Casts.noCasts(LInitDisplayList.class);
+        }
+
+        @Override
+        @TruffleBoundary
+        public Object execute() {
+            GridState gridState = GridContext.getContext().getGridState();
+            initDisplayList(gridState);
+            return RNull.instance;
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index 354cc20747..dc2ca5e33d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import com.oracle.truffle.r.library.fastrGrid.DisplayList.LGetDisplayListElement;
+import com.oracle.truffle.r.library.fastrGrid.DisplayList.LInitDisplayList;
+import com.oracle.truffle.r.library.fastrGrid.DisplayList.LSetDisplayListOn;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevOff;
@@ -34,7 +37,6 @@ import com.oracle.truffle.r.runtime.RInternalCode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -129,20 +131,28 @@ public final class FastRGridExternalLookup {
             case "L_initGPar":
                 return new LInitGPar();
 
-            // Display list stuff: not implemented atm
+            // Display list stuff
             case "L_getDisplayList":
-                return new IgnoredGridExternal(RDataFactory.createList());
+                return new GridStateGetNode(GridState::getDisplayList);
+            case "L_setDisplayList":
+                return GridStateSetNode.create((state, val) -> state.setDisplayList((RList) val));
             case "L_getDLindex":
-                return new IgnoredGridExternal(0);
+                return new GridStateGetNode(GridState::getDisplayListIndex);
+            case "L_setDLindex":
+                return GridStateSetNode.create((state, val) -> state.setDisplayListIndex(RRuntime.asInteger(val)));
+            case "L_setDLelt":
+                return GridStateSetNode.create(GridState::setDisplayListElement);
+            case "L_getDLelt":
+                return LGetDisplayListElement.create();
+            case "L_setDLon":
+                return LSetDisplayListOn.create();
             case "L_getDLon":
+                return new GridStateGetNode(state -> RRuntime.asLogical(state.isDisplayListOn()));
             case "L_getEngineDLon":
                 return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE);
             case "L_initDisplayList":
+                return new LInitDisplayList();
             case "L_newpagerecording":
-            case "L_setDisplayList":
-            case "L_setDLelt":
-            case "L_setDLindex":
-            case "L_setDLon":
                 return new IgnoredGridExternal(RNull.instance);
 
             // These methods do not use graphics system or any global state. For now,
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index deab204f3b..321e0a022b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -42,6 +42,39 @@ public final class GridState {
         return devHoldCount;
     }
 
+    public RList getDisplayList() {
+        if (devState.displayList == null) {
+            devState.displayList = DisplayList.createInitialDisplayList();
+        }
+        return devState.displayList;
+    }
+
+    public void setDisplayList(RList newList) {
+        newList.makeSharedPermanent();
+        devState.displayList = newList;
+    }
+
+    public void setDisplayListElement(Object element) {
+        Object[] data = devState.displayList.getDataWithoutCopying();
+        data[devState.displayListIndex] = element;
+    }
+
+    public boolean isDisplayListOn() {
+        return devState.isDisplayListOn;
+    }
+
+    public void setIsDisplayListOn(boolean flag) {
+        devState.isDisplayListOn = flag;
+    }
+
+    public int getDisplayListIndex() {
+        return devState.displayListIndex;
+    }
+
+    public void setDisplayListIndex(int newValue) {
+        devState.displayListIndex = newValue;
+    }
+
     public void init(REnvironment gridEnv) {
         this.gridEnv = gridEnv;
         this.currentGrob = RNull.instance;
@@ -112,5 +145,8 @@ public final class GridState {
         private RList viewPort;
         private double scale = 1;
         private int devHoldCount;
+        private boolean isDisplayListOn = true;
+        private RList displayList;
+        private int displayListIndex = 0;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index a6314dff2c..d24bea0560 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -54,7 +54,7 @@ final class LGridDirty extends RExternalBuiltinNode {
         if (gridState.getViewPort() == null) {
             gridState.setViewPort(initViewPort.execute(frame));
         }
-
+        DisplayList.initDisplayList(gridState);
         return RNull.instance;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 90a2dcd6e9..f893a5b02b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.device;
 
-import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
-
 /**
  * Abstract device that can draw primitive shapes and text. All sizes and coordinates are specified
  * in inches and angles in radians unless stated otherwise.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
index 6e31f1f417..93c4f700aa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
@@ -58,6 +58,7 @@ public final class JFrameDevice extends Graphics2DDevice {
     public static JFrameDevice create() {
         FastRFrame frame = new FastRFrame();
         frame.setVisible(true);
+        frame.pack();
         Graphics2D graphics = (Graphics2D) frame.getGraphics();
         defaultInitGraphics(graphics);
         return new JFrameDevice(frame, graphics, true);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index f1fab85632..5048fe9411 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
-import java.io.IOException;
-
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
-- 
GitLab


From 8d61940e886ea87d939a4fc7f79525f659323337 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 29 Mar 2017 11:37:19 +0200
Subject: [PATCH 200/402] FastR Grid: unit conversion fixes

---
 .../src/com/oracle/truffle/r/library/fastrGrid/Unit.java    | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index f881cc7081..a4287304d1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -215,7 +215,7 @@ public final class Unit {
                 for (int i = 0; i < lines.length; i++) {
                     result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), lines[i]));
                 }
-                return result;
+                return value * result;
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
                 str = RRuntime.asString(data.getDataAt(0));
@@ -223,7 +223,7 @@ public final class Unit {
                 for (int i = 0; i < lines.length; i++) {
                     result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), lines[i]);
                 }
-                return result;
+                return value * result;
             case NULL:
                 return evaluateNullUnit(value, vpSize, ctx.nullLayoutMode, ctx.nullArithmeticMode);
             default:
@@ -551,7 +551,7 @@ public final class Unit {
                 case "min":
                     return GridUtils.fmin(Double.MAX_VALUE, values);
                 case "max":
-                    return GridUtils.fmax(Double.MAX_VALUE, values);
+                    return GridUtils.fmax(Double.MIN_VALUE, values);
                 case "sum":
                     return GridUtils.sum(values);
                 default:
-- 
GitLab


From 5605ce6d633fa9dd7d8314f2f496a91621f7abfb Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 29 Mar 2017 13:43:17 +0200
Subject: [PATCH 201/402] readBin supports 2-byte size

---
 .../truffle/r/nodes/builtin/base/ConnectionFunctions.java | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 24a803191f..efa1508a88 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -54,6 +54,7 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.DoubleBuffer;
 import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
 import java.nio.channels.ByteChannel;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
@@ -860,7 +861,7 @@ public abstract class ConnectionFunctions {
                         if (size == RRuntime.INT_NA) {
                             size = 4;
                         }
-                        if (size == 1 || size == 4) {
+                        if (size == 1 || size == 4 || size == 2) {
                             result = readInteger(connection, n, size, swap, signed);
                         } else {
                             throw RError.nyi(RError.SHOW_CALLER, "readBin \"int\" size not implemented");
@@ -917,6 +918,11 @@ public abstract class ConnectionFunctions {
                     int d = signed ? b : b & 0xFF;
                     data[i] = d;
                 }
+            } else if (size == 2) {
+                ShortBuffer shortBuffer = buffer.asShortBuffer();
+                for (int i = 0; i < nInts; i++) {
+                    data[i] = shortBuffer.get();
+                }
             }
             return RDataFactory.createIntVector(data, complete);
         }
-- 
GitLab


From fdbe6efbd31cad48142cbb159879e7e148be1c4d Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 14:32:27 +0200
Subject: [PATCH 202/402] reduce number of promise subclasses

---
 .../r/nodes/function/PromiseHelperNode.java   | 17 +++++++------
 .../r/nodes/function/RMissingHelper.java      |  8 +++----
 .../nodes/function/signature/MissingNode.java |  3 ++-
 .../truffle/r/runtime/data/RDataFactory.java  |  2 +-
 .../truffle/r/runtime/data/RPromise.java      | 24 ++-----------------
 .../truffle/r/test/tck/FastRDebugTest.java    |  6 ++---
 6 files changed, 20 insertions(+), 40 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index aa95117cb5..836a0029fc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -48,7 +48,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.VirtualEvalFrame;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
-import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -121,7 +120,7 @@ public class PromiseHelperNode extends RBaseNode {
         private boolean deoptimize(RPromise promise) {
             if (!PromiseState.isDefaultOpt(promise.getState())) {
                 deoptimizeProfile.enter();
-                EagerPromiseBase eager = (EagerPromiseBase) promise;
+                EagerPromise eager = (EagerPromise) promise;
                 return eager.deoptimize();
             }
 
@@ -168,7 +167,7 @@ public class PromiseHelperNode extends RBaseNode {
         if (PromiseState.isDefaultOpt(state)) {
             obj = generateValueDefault(frame, promise);
         } else {
-            obj = generateValueEager(frame, state, (EagerPromiseBase) promise);
+            obj = generateValueEager(frame, state, (EagerPromise) promise);
         }
         if (isEvaluated(promise)) {
             // TODO: this only happens if compilation is in play and, as such, is difficult to track
@@ -201,7 +200,7 @@ public class PromiseHelperNode extends RBaseNode {
         }
     }
 
-    private Object generateValueEager(VirtualFrame frame, int state, EagerPromiseBase promise) {
+    private Object generateValueEager(VirtualFrame frame, int state, EagerPromise promise) {
         assert !PromiseState.isDefaultOpt(state);
         if (!isDeoptimized(promise)) {
             Assumption eagerAssumption = isValidAssumptionProfile.profile(promise.getIsValidAssumption());
@@ -211,7 +210,7 @@ public class PromiseHelperNode extends RBaseNode {
                     return checkNextNode().evaluate(frame, nextPromise);
                 } else {
                     assert PromiseState.isEager(state);
-                    return getEagerValue(frame, (EagerPromise) promise);
+                    return getEagerValue(frame, promise);
                 }
             } else {
                 CompilerDirectives.transferToInterpreter();
@@ -257,7 +256,7 @@ public class PromiseHelperNode extends RBaseNode {
             // Evaluate guarded by underEvaluation
             obj = generateValueDefaultSlowPath(frame, promise);
         } else {
-            obj = generateValueEagerSlowPath(frame, state, (EagerPromiseBase) promise);
+            obj = generateValueEagerSlowPath(frame, state, (EagerPromise) promise);
         }
         promise.setValue(obj);
         return obj;
@@ -286,7 +285,7 @@ public class PromiseHelperNode extends RBaseNode {
         return VirtualEvalFrame.create(promiseFrame, RArguments.getFunction(promiseFrame), RCaller.createForPromise(RArguments.getCall(promiseFrame), frame));
     }
 
-    private static Object generateValueEagerSlowPath(VirtualFrame frame, int state, EagerPromiseBase promise) {
+    private static Object generateValueEagerSlowPath(VirtualFrame frame, int state, EagerPromise promise) {
         assert !PromiseState.isDefaultOpt(state);
         if (!promise.isDeoptimized()) {
             Assumption eagerAssumption = promise.getIsValidAssumption();
@@ -318,7 +317,7 @@ public class PromiseHelperNode extends RBaseNode {
      */
     public void materialize(RPromise promise) {
         if (isDefaultOptProfile.profile(!PromiseState.isDefaultOpt(promise.getState()))) {
-            EagerPromiseBase eager = (EagerPromiseBase) promise;
+            EagerPromise eager = (EagerPromise) promise;
             eager.materialize();
         }
         // otherwise: already the generic and slow RPromise
@@ -336,7 +335,7 @@ public class PromiseHelperNode extends RBaseNode {
         return isNullFrameProfile.profile(promise.isNullFrame());
     }
 
-    private boolean isDeoptimized(EagerPromiseBase promise) {
+    private boolean isDeoptimized(EagerPromise promise) {
         return isDeoptimizedProfile.profile(promise.isDeoptimized());
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
index 2e26f58248..5a6a72b6b0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase;
+import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 
 /**
  * This class implements the behavior for {@link RMissing} which is needed inside this module, as it
@@ -135,8 +135,8 @@ public class RMissingHelper {
                 }
                 promise.setUnderEvaluation();
                 // TODO Profile necessary here???
-                if (promise instanceof EagerPromiseBase) {
-                    EagerPromiseBase eagerPromise = (EagerPromiseBase) promise;
+                if (promise instanceof EagerPromise) {
+                    EagerPromise eagerPromise = (EagerPromise) promise;
                     if (!eagerPromise.isDeoptimized()) {
                         Object eagerValue = eagerPromise.getEagerValue();
                         if (eagerValue instanceof RPromise) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
index f7f09332ee..98aff46476 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/MissingNode.java
@@ -46,6 +46,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
+import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -142,7 +143,7 @@ public final class MissingNode extends OperatorNode {
                 if (isSymbolNullProfile.profile(symbol == null)) {
                     return false;
                 } else {
-                    if (promise instanceof EagerPromise && !((EagerPromise) promise).isDeoptimized()) {
+                    if (PromiseState.isEager(promise.getState()) && !((EagerPromise) promise).isDeoptimized()) {
                         return false;
                     }
                     if (recursiveDesc != null) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index db2e0bbd3f..fb20f10a0d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -437,7 +437,7 @@ public final class RDataFactory {
         if (FastROptions.noEagerEval()) {
             throw RInternalError.shouldNotReachHere();
         }
-        return traceDataCreated(new RPromise.PromisedPromise(exprClosure, eagerValue, notChangedNonLocally, targetFrame, feedback));
+        return traceDataCreated(new RPromise.EagerPromise(PromiseState.Promised, exprClosure, eagerValue, notChangedNonLocally, targetFrame, feedback, -1));
     }
 
     public static Object createLangPairList(int size) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
index 24a4df04d6..cdb65dbbb9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -277,7 +277,7 @@ public class RPromise implements RTypedValue {
      * originally read from has not been altered in the mean time. If this cannot be guaranteed for
      * any reason, a Promise gets {@link #deoptimize()} (which includes {@link #materialize()}ion).
      */
-    public static class EagerPromiseBase extends RPromise {
+    public static final class EagerPromise extends RPromise {
         private final Object eagerValue;
 
         private final Assumption notChangedNonLocally;
@@ -291,7 +291,7 @@ public class RPromise implements RTypedValue {
          */
         private boolean deoptimized = false;
 
-        EagerPromiseBase(PromiseState state, Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback, int wrapIndex) {
+        EagerPromise(PromiseState state, Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback, int wrapIndex) {
             super(state, (MaterializedFrame) null, closure);
             assert state != PromiseState.Explicit;
             this.eagerValue = eagerValue;
@@ -348,26 +348,6 @@ public class RPromise implements RTypedValue {
         }
     }
 
-    /**
-     * This is a "proper" eager promise.
-     */
-    public static final class EagerPromise extends EagerPromiseBase {
-        EagerPromise(PromiseState state, Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback, int wrapIndex) {
-            super(state, closure, eagerValue, notChangedNonLocally, targetFrame, feedback, wrapIndex);
-        }
-    }
-
-    /**
-     * It's a variant of an eager promise used to store another promise, distinguished mostly for
-     * accounting purposes.
-     */
-    public static final class PromisedPromise extends EagerPromiseBase {
-
-        PromisedPromise(Closure closure, Object eagerValue, Assumption notChangedNonLocally, RCaller targetFrame, EagerFeedback feedback) {
-            super(PromiseState.Promised, closure, eagerValue, notChangedNonLocally, targetFrame, feedback, -1);
-        }
-    }
-
     /**
      * Used to allow feedback on {@link EagerPromise} evaluation.
      */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 2b1520a625..02ccdb2128 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -53,7 +53,7 @@ import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
-import com.oracle.truffle.r.runtime.data.RPromise.EagerPromiseBase;
+import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 public class FastRDebugTest {
@@ -302,8 +302,8 @@ public class FastRDebugTest {
 
     Object getRValue(Object value) {
         // This will only work in simple cases
-        if (value instanceof EagerPromiseBase) {
-            return ((EagerPromiseBase) value).getValue();
+        if (value instanceof EagerPromise) {
+            return ((EagerPromise) value).getValue();
         }
         return value;
     }
-- 
GitLab


From 21821b390ad834a640108ec72d00648262326795 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 14:33:05 +0200
Subject: [PATCH 203/402] gamma functions

---
 .../builtin/base/BaseGammaFunctions.java      | 124 ++++++++----------
 .../r/runtime/nmath/GammaFunctions.java       |   2 +-
 .../r/test/builtins/TestBuiltin_gamma.java    |   9 +-
 3 files changed, 63 insertions(+), 72 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index 496698e6d4..ff6d99d9c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -27,12 +27,12 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.BaseGammaFunctionsFactory.DpsiFnCalcNodeGen;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -44,101 +44,93 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class BaseGammaFunctions {
 
+    public abstract static class GammaBase extends RBuiltinNode {
+
+        private final NACheck naValCheck = NACheck.create();
+
+        protected static void casts(Casts casts) {
+            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector();
+        }
+
+        @Specialization
+        protected RDoubleVector digamma(RAbstractDoubleVector x) {
+            naValCheck.enable(x);
+            double[] result = new double[x.getLength()];
+            boolean warnNaN = false;
+            for (int i = 0; i < x.getLength(); i++) {
+                double xv = x.getDataAt(i);
+                double val;
+                if (naValCheck.check(xv)) {
+                    val = RRuntime.DOUBLE_NA;
+                } else {
+                    val = scalarFunction(xv);
+                    if (Double.isNaN(val)) {
+                        warnNaN = true;
+                    }
+                }
+                result[i] = val;
+            }
+            if (warnNaN) {
+                warning(RError.Message.NAN_PRODUCED);
+            }
+            return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
+        }
+
+        protected double scalarFunction(@SuppressWarnings("unused") double xv) {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
     @RBuiltin(name = "gamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Gamma extends RBuiltinNode {
+    public abstract static class Gamma extends GammaBase {
 
         static {
-            Casts casts = new Casts(Gamma.class);
-            casts.arg("x").mustNotBeMissing(RError.Message.ARGUMENTS_PASSED, 0, "'gamma'", 1).mustBe(numericValue(), RError.Message.NON_NUMERIC_MATH).asDoubleVector().findFirst();
+            casts(new Casts(Gamma.class));
         }
 
-        @Specialization
-        @TruffleBoundary
-        protected RDoubleVector lgamma(@SuppressWarnings("unused") RAbstractDoubleVector x) {
-            throw RError.nyi(this, "gamma");
+        @Override
+        protected double scalarFunction(double xv) {
+            return GammaFunctions.gammafn(xv);
         }
     }
 
     @RBuiltin(name = "trigamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class TriGamma extends RBuiltinNode {
+    public abstract static class TriGamma extends GammaBase {
         static {
-            Casts.noCasts(TriGamma.class);
+            casts(new Casts(TriGamma.class));
         }
 
-        @Specialization
-        @TruffleBoundary
-        protected RDoubleVector trigamma(@SuppressWarnings("unused") RAbstractDoubleVector x) {
-            // Note: this is actually unimplemented even in GnuR
+        @Override
+        protected double scalarFunction(double xv) {
             throw RError.nyi(this, "trigamma");
         }
     }
 
     @RBuiltin(name = "lgamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Lgamma extends RBuiltinNode {
-
-        private final NACheck naValCheck = NACheck.create();
+    public abstract static class Lgamma extends GammaBase {
 
         static {
-            Casts casts = new Casts(Lgamma.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector();
+            casts(new Casts(Lgamma.class));
         }
 
-        @Specialization
-        protected RDoubleVector lgamma(RAbstractDoubleVector x) {
-            naValCheck.enable(true);
-            double[] result = new double[x.getLength()];
-            for (int i = 0; i < x.getLength(); i++) {
-                double xv = x.getDataAt(i);
-                result[i] = GammaFunctions.lgammafn(xv);
-                naValCheck.check(result[i]);
-            }
-            return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
+        @Override
+        protected double scalarFunction(double xv) {
+            return GammaFunctions.lgammafn(xv);
         }
     }
 
     @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class DiGamma extends RBuiltinNode {
-
-        @Child private DpsiFnCalc dpsiFnCalc;
-
-        private final NACheck naValCheck = NACheck.create();
+    public abstract static class DiGamma extends GammaBase {
 
-        private double dpsiFnCalc(double x, int n, int kode, double ans) {
-            if (dpsiFnCalc == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                dpsiFnCalc = insert(DpsiFnCalcNodeGen.create());
-            }
-            return dpsiFnCalc.executeDouble(x, n, kode, ans);
-        }
+        @Child private DpsiFnCalc dpsiFnCalc = DpsiFnCalcNodeGen.create();
 
         static {
-            Casts casts = new Casts(DiGamma.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector();
+            casts(new Casts(DiGamma.class));
         }
 
-        @Specialization
-        protected RDoubleVector digamma(RAbstractDoubleVector x) {
-            naValCheck.enable(x);
-            double[] result = new double[x.getLength()];
-            boolean warnNaN = false;
-            for (int i = 0; i < x.getLength(); i++) {
-                double xv = x.getDataAt(i);
-                if (naValCheck.check(xv)) {
-                    result[i] = xv;
-                } else {
-                    double val = dpsiFnCalc(xv, 0, 1, 0);
-                    if (Double.isNaN(val)) {
-                        result[i] = val;
-                        warnNaN = true;
-                    } else {
-                        result[i] = -val;
-                    }
-                }
-            }
-            if (warnNaN) {
-                warning(RError.Message.NAN_PRODUCED);
-            }
-            return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
+        @Override
+        protected double scalarFunction(double xv) {
+            return -dpsiFnCalc.executeDouble(xv, 0, 1, 0);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java
index 38a90070f9..6145b2d5b4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java
@@ -126,7 +126,7 @@ public abstract class GammaFunctions {
 
     private static final double M_LN_SQRT_2PI = 0.918938533204672741780329736406;
 
-    static double gammafn(double x) {
+    public static double gammafn(double x) {
         int i;
         int n;
         double y;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
index 4282428e71..a1601e7249 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
@@ -19,12 +19,12 @@ public class TestBuiltin_gamma extends TestBase {
 
     @Test
     public void testgamma1() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1));gamma(argv[[1]]);");
+        assertEval("argv <- list(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1));gamma(argv[[1]]);");
     }
 
     @Test
     public void testgamma2() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE);gamma(argv[[1]]);");
+        assertEval("argv <- list(FALSE);gamma(argv[[1]]);");
     }
 
     @Test
@@ -34,12 +34,11 @@ public class TestBuiltin_gamma extends TestBase {
 
     @Test
     public void testgamma5() {
-        assertEval(Ignored.Unknown, "argv <- list(101);gamma(argv[[1]]);");
+        assertEval("argv <- list(101);gamma(argv[[1]]);");
     }
 
     @Test
     public void testgamma6() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(-3.000001, -3, -3, -2.999999, -2.965, -2.93, -2.895, -2.86, -2.825, -2.79, -2.755, -2.72, -2.685, -2.65, -2.615, -2.58, -2.545, -2.51, -2.475, -2.44, -2.405, -2.37, -2.335, -2.3, -2.265, -2.23, -2.195, -2.16, -2.125, -2.09, -2.055, -2.02, -2.000001, -2, -1.999999, -1.985, -1.95, -1.915, -1.88, -1.845, -1.81, -1.775, -1.74, -1.705, -1.67, -1.635, -1.6, -1.565, -1.53, -1.495, -1.46, -1.425, -1.39, -1.355, -1.32, -1.285, -1.25, -1.215, -1.18, -1.145, -1.11, -1.075, -1.04, -1.005, -1.000001, -1, -0.999999, -0.97, -0.935, -0.9, -0.865, -0.83, -0.795, -0.76, -0.725, -0.69, -0.655, -0.62, -0.585, -0.55, -0.515, -0.48, -0.445, -0.41, -0.375, -0.34, -0.305, -0.27, -0.235, -0.2, -0.165, -0.13, -0.0949999999999998, -0.0599999999999996, -0.0249999999999999, -1e-06, 0, 1e-06, 0.0100000000000002, 0.0450000000000004, 0.0800000000000001, 0.115, 0.15, 0.185, 0.22, 0.255, 0.29, 0.325, 0.36, 0.395, 0.43, 0.465, 0.5, 0.535, 0.57, 0.605, 0.640000000000001, 0.675, 0.71, 0.745000000000001, 0.78, 0.815, 0.850000000000001, 0.885, 0.92, 0.955000000000001, 0.99, 1.025, 1.06, 1.095, 1.13, 1.165, 1.2, 1.235, 1.27, 1.305, 1.34, 1.375, 1.41, 1.445, 1.48, 1.515, 1.55, 1.585, 1.62, 1.655, 1.69, 1.725, 1.76, 1.795, 1.83, 1.865, 1.9, 1.935, 1.97, 2.005, 2.04, 2.075, 2.11, 2.145, 2.18, 2.215, 2.25, 2.285, 2.32, 2.355, 2.39, 2.425, 2.46, 2.495, 2.53, 2.565, 2.6, 2.635, 2.67, 2.705, 2.74, 2.775, 2.81, 2.845, 2.88, 2.915, 2.95, 2.985, 3.02, 3.055, 3.09, 3.125, 3.16, 3.195, 3.23, 3.265, 3.3, 3.335, 3.37, 3.405, 3.44, 3.475, 3.51, 3.545, 3.58, 3.615, 3.65, 3.685, 3.72, 3.755, 3.79, 3.825, 3.86, 3.895, 3.93, 3.965, 4));gamma(argv[[1]]);");
+        assertEval("argv <- list(c(-3.000001, -3, -3, -2.999999, -2.965, -2.93, -2.895, -2.86, -2.825, -2.79, -2.755, -2.72, -2.685, -2.65, -2.615, -2.58, -2.545, -2.51, -2.475, -2.44, -2.405, -2.37, -2.335, -2.3, -2.265, -2.23, -2.195, -2.16, -2.125, -2.09, -2.055, -2.02, -2.000001, -2, -1.999999, -1.985, -1.95, -1.915, -1.88, -1.845, -1.81, -1.775, -1.74, -1.705, -1.67, -1.635, -1.6, -1.565, -1.53, -1.495, -1.46, -1.425, -1.39, -1.355, -1.32, -1.285, -1.25, -1.215, -1.18, -1.145, -1.11, -1.075, -1.04, -1.005, -1.000001, -1, -0.999999, -0.97, -0.935, -0.9, -0.865, -0.83, -0.795, -0.76, -0.725, -0.69, -0.655, -0.62, -0.585, -0.55, -0.515, -0.48, -0.445, -0.41, -0.375, -0.34, -0.305, -0.27, -0.235, -0.2, -0.165, -0.13, -0.0949999999999998, -0.0599999999999996, -0.0249999999999999, -1e-06, 0, 1e-06, 0.0100000000000002, 0.0450000000000004, 0.0800000000000001, 0.115, 0.15, 0.185, 0.22, 0.255, 0.29, 0.325, 0.36, 0.395, 0.43, 0.465, 0.5, 0.535, 0.57, 0.605, 0.640000000000001, 0.675, 0.71, 0.745000000000001, 0.78, 0.815, 0.850000000000001, 0.885, 0.92, 0.955000000000001, 0.99, 1.025, 1.06, 1.095, 1.13, 1.165, 1.2, 1.235, 1.27, 1.305, 1.34, 1.375, 1.41, 1.445, 1.48, 1.515, 1.55, 1.585, 1.62, 1.655, 1.69, 1.725, 1.76, 1.795, 1.83, 1.865, 1.9, 1.935, 1.97, 2.005, 2.04, 2.075, 2.11, 2.145, 2.18, 2.215, 2.25, 2.285, 2.32, 2.355, 2.39, 2.425, 2.46, 2.495, 2.53, 2.565, 2.6, 2.635, 2.67, 2.705, 2.74, 2.775, 2.81, 2.845, 2.88, 2.915, 2.95, 2.985, 3.02, 3.055, 3.09, 3.125, 3.16, 3.195, 3.23, 3.265, 3.3, 3.335, 3.37, 3.405, 3.44, 3.475, 3.51, 3.545, 3.58, 3.615, 3.65, 3.685, 3.72, 3.755, 3.79, 3.825, 3.86, 3.895, 3.93, 3.965, 4));gamma(argv[[1]]);");
     }
 }
-- 
GitLab


From db0626aa832cd49b363029a24baba1f16c9edf54 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 14:34:24 +0200
Subject: [PATCH 204/402] implement La_chol2inv

---
 .../fficall/src/jni/lapack_rffi.c             |  12 ++
 com.oracle.truffle.r.native/version.source    |   2 +-
 .../r/nodes/builtin/base/BasePackage.java     |   1 +
 .../r/nodes/builtin/base/LaFunctions.java     | 116 +++++++++++++-----
 .../truffle/r/runtime/ffi/jni/JNI_Lapack.java |  15 +++
 .../com/oracle/truffle/r/runtime/RError.java  |   3 +
 .../truffle/r/runtime/ffi/LapackRFFI.java     |  14 +++
 7 files changed, 129 insertions(+), 34 deletions(-)

diff --git a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
index 3a086352c9..ec9a445966 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
@@ -137,6 +137,18 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env
     return info;
 }
 
+extern int dpotri_(char *uplo, int *n, double *a, int *lda, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotri(JNIEnv *env, jclass klass,
+        char uplo, int n, jdoubleArray ja, int lda) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    int info;
+    dpotri_(&uplo, &n, a, &lda, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    return info;
+}
+
 extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info);
 
 JNIEXPORT jint JNICALL
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index b6a7d89c68..98d9bcb75a 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-16
+17
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 938bee74e6..627bdb1bcf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -491,6 +491,7 @@ public class BasePackage extends RBuiltinPackage {
         add(IsUnsorted.class, IsUnsortedNodeGen::create);
         add(LaFunctions.DetGeReal.class, LaFunctionsFactory.DetGeRealNodeGen::create);
         add(LaFunctions.LaChol.class, LaFunctionsFactory.LaCholNodeGen::create);
+        add(LaFunctions.LaChol2Inv.class, LaFunctionsFactory.LaChol2InvNodeGen::create);
         add(LaFunctions.Qr.class, LaFunctionsFactory.QrNodeGen::create);
         add(LaFunctions.QrCoefReal.class, LaFunctionsFactory.QrCoefRealNodeGen::create);
         add(LaFunctions.Rg.class, LaFunctionsFactory.RgNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index fec8c896f3..956badb0e4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -38,11 +38,12 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
 import com.oracle.truffle.r.runtime.RAccuracyInfo;
-import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -86,8 +87,8 @@ public class LaFunctions {
 
         protected static Casts createCasts(Class<? extends RsgRBuiltinNode> extClass) {
             Casts casts = new Casts(extClass);
-            casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_NUMERIC, "x");
-            casts.arg("onlyValues").defaultError(RError.Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), Message.MUST_BE_SQUARE_NUMERIC, "x");
+            casts.arg("onlyValues").defaultError(Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
             return casts;
         }
     }
@@ -124,14 +125,14 @@ public class LaFunctions {
             // ask for optimal size of work array
             int info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, -1);
             if (info != 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dgeev");
+                throw error(Message.LAPACK_ERROR, info, "dgeev");
             }
             // now allocate work array and make the actual call
             int lwork = (int) work[0];
             work = new double[lwork];
             info = dgeevNode.execute(jobVL, jobVR, n, a, n, wr, wi, left, n, right, n, work, lwork);
             if (info != 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dgeev");
+                throw error(Message.LAPACK_ERROR, info, "dgeev");
             }
             // result is a list containing "values" and "vectors" (unless only.values is TRUE)
             boolean complexValues = false;
@@ -229,7 +230,7 @@ public class LaFunctions {
             int[] iwork = new int[1];
             int info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
             if (info != 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dysevr");
+                throw error(Message.LAPACK_ERROR, info, "dysevr");
             }
             lwork = (int) work[0];
             liwork = iwork[0];
@@ -237,7 +238,7 @@ public class LaFunctions {
             iwork = new int[liwork];
             info = dsyevrNode.execute(jobv, range, uplo, n, x, n, vl, vu, il, iu, abstol, m, values, z, n, isuppz, work, lwork, iwork, liwork);
             if (info != 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dysevr");
+                throw error(Message.LAPACK_ERROR, info, "dysevr");
             }
             Object[] data = new Object[onlyValues ? 1 : 2];
             RStringVector names;
@@ -260,7 +261,7 @@ public class LaFunctions {
 
         static {
             Casts casts = new Casts(Qr.class);
-            casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a");
+            casts.arg("in").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a");
         }
 
         @Specialization
@@ -280,13 +281,13 @@ public class LaFunctions {
             // ask for optimal size of work array
             int info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, -1);
             if (info < 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dgeqp3");
+                throw error(Message.LAPACK_ERROR, info, "dgeqp3");
             }
             int lwork = (int) work[0];
             work = new double[lwork];
             info = dgeqp3Node.execute(m, n, a, m, jpvt, tau, work, lwork);
             if (info < 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dgeqp3");
+                throw error(Message.LAPACK_ERROR, info, "dgeqp3");
             }
             Object[] data = new Object[4];
             // TODO check complete
@@ -310,7 +311,7 @@ public class LaFunctions {
         static {
             Casts casts = new Casts(QrCoefReal.class);
             casts.arg("q").mustBe(instanceOf(RList.class));
-            casts.arg("b").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "b");
+            casts.arg("b").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "b");
         }
 
         @Specialization
@@ -331,7 +332,7 @@ public class LaFunctions {
             int[] qrDims = getQDimsNode.getDimensions(qr);
             int n = qrDims[0];
             if (bDims[0] != n) {
-                throw error(RError.Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]);
+                throw error(Message.RHS_SHOULD_HAVE_ROWS, n, bDims[0]);
             }
             int nrhs = bDims[1];
             double[] work = new double[1];
@@ -343,17 +344,17 @@ public class LaFunctions {
             // ask for optimal size of work array
             int info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1);
             if (info < 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dormqr");
+                throw error(Message.LAPACK_ERROR, info, "dormqr");
             }
             int lwork = (int) work[0];
             work = new double[lwork];
             info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, lwork);
             if (info < 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dormqr");
+                throw error(Message.LAPACK_ERROR, info, "dormqr");
             }
             info = dtrtrsNode.execute('U', 'N', 'N', k, nrhs, qrData, n, bData, n);
             if (info < 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dtrtrs");
+                throw error(Message.LAPACK_ERROR, info, "dtrtrs");
             }
             // TODO check complete
             return b;
@@ -374,9 +375,9 @@ public class LaFunctions {
 
         static {
             Casts casts = new Casts(DetGeReal.class);
-            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a");
+            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX, "a");
 
-            casts.arg("uselog").defaultError(RError.Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+            casts.arg("uselog").defaultError(Message.MUST_BE_LOGICAL, "logarithm").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
         }
 
         @Specialization
@@ -392,7 +393,7 @@ public class LaFunctions {
             int info = dgetrfNode.execute(n, n, aData, n, ipiv);
             int sign = 1;
             if (info < 0) {
-                throw error(RError.Message.LAPACK_ERROR, info, "dgetrf");
+                throw error(Message.LAPACK_ERROR, info, "dgetrf");
             } else if (infoGreaterZero.profile(info > 0)) {
                 modulus = useLog ? Double.NEGATIVE_INFINITY : 0;
             } else {
@@ -451,8 +452,8 @@ public class LaFunctions {
 
         static {
             Casts casts = new Casts(LaChol.class);
-            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX, "a").mustBe(
-                            dimGt(1, 0), RError.Message.DIMS_GT_ZERO, "a");
+            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX, "a").mustBe(
+                            dimGt(1, 0), Message.DIMS_GT_ZERO, "a");
 
             casts.arg("pivot").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
 
@@ -482,7 +483,7 @@ public class LaFunctions {
                 info = dpotrfNode.execute('U', m, aData, m);
                 if (info != 0) {
                     // TODO informative error message (aka GnuR)
-                    throw error(RError.Message.LAPACK_ERROR, info, "dpotrf");
+                    throw error(Message.LAPACK_ERROR, info, "dpotrf");
                 }
             } else {
                 int[] ipiv = new int[m];
@@ -491,7 +492,7 @@ public class LaFunctions {
                 info = dpstrfNode.execute('U', n, aData, n, ipiv, rank, tol, work);
                 if (info != 0) {
                     // TODO informative error message (aka GnuR)
-                    throw error(RError.Message.LAPACK_ERROR, info, "dpotrf");
+                    throw error(Message.LAPACK_ERROR, info, "dpotrf");
                 }
                 setPivotAttrNode.execute(a, RRuntime.asLogical(piv));
                 setRankAttrNode.execute(a, rank[0]);
@@ -509,6 +510,55 @@ public class LaFunctions {
         }
     }
 
+    @RBuiltin(name = "La_chol2inv", kind = INTERNAL, parameterNames = {"a", "size"}, behavior = PURE)
+    public abstract static class LaChol2Inv extends RBuiltinNode {
+
+        @Child private SetFixedAttributeNode setPivotAttrNode = SetFixedAttributeNode.create("pivot");
+        @Child private SetFixedAttributeNode setRankAttrNode = SetFixedAttributeNode.create("rank");
+
+        static {
+            Casts casts = new Casts(LaChol2Inv.class);
+            casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a");
+            casts.arg("size").asIntegerVector().mustBe(Predef.notEmpty()).findFirst().mustBe(Predef.gt(0), Message.MUST_BE_POSITIVE_INT);
+        }
+
+        @Specialization
+        protected RDoubleVector chol2inv(RAbstractDoubleVector a, int size,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") LapackRFFI.DpotriNode dpotriNode) {
+
+            int[] aDims = getDimsNode.getDimensions(a);
+            int m = aDims[0];
+            int n = aDims[1];
+
+            if (size > n) {
+                throw error(Message.CANNOT_EXCEED_X, "size", "ncol", n);
+            }
+            if (size > m) {
+                throw error(Message.CANNOT_EXCEED_X, "size", "nrow", n);
+            }
+            double[] result = new double[size * size];
+            for (int j = 0; j < size; j++) {
+                for (int i = 0; i <= j; i++) {
+                    result[i + j * size] = a.getDataAt(i + j * m);
+                }
+            }
+            int info = dpotriNode.execute('U', size, result, size);
+            if (info != 0) {
+                if (info > 0) {
+                    throw error(Message.LAPACK_ZERO_INVERSE, info, info);
+                }
+                throw error(Message.LAPACK_INVALID_VALUE, -info, "dpotri");
+            }
+            for (int j = 0; j < size; j++) {
+                for (int i = j + 1; i < size; i++) {
+                    result[i + j * size] = result[j + i * size];
+                }
+            }
+            return RDataFactory.createDoubleVector(result, true, new int[]{size, size});
+        }
+    }
+
     @RBuiltin(name = "La_solve", kind = INTERNAL, parameterNames = {"a", "bin", "tolin"}, behavior = PURE)
     public abstract static class LaSolve extends RBuiltinNode {
         @Child private CastDoubleNode castDouble = CastDoubleNodeGen.create(false, false, false);
@@ -519,10 +569,10 @@ public class LaFunctions {
 
         static {
             Casts casts = new Casts(LaSolve.class);
-            casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), RError.Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)),
-                            RError.Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), RError.Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
+            casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)),
+                            Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
 
-            casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), RError.Message.GENERIC, "no right-hand side in 'b'");
+            casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), Message.GENERIC, "no right-hand side in 'b'");
 
             casts.arg("tolin").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
         }
@@ -542,11 +592,11 @@ public class LaFunctions {
             int[] aDims = getADimsNode.getDimensions(a);
             int n = aDims[0];
             if (n == 0) {
-                throw error(RError.Message.GENERIC, "'a' is 0-diml");
+                throw error(Message.GENERIC, "'a' is 0-diml");
             }
             int n2 = aDims[1];
             if (n2 != n) {
-                throw error(RError.Message.MUST_BE_SQUARE, "a", n, n2);
+                throw error(Message.MUST_BE_SQUARE, "a", n, n2);
             }
             RList aDn = getADimNamesNode.getDimNames(a);
             int p;
@@ -556,11 +606,11 @@ public class LaFunctions {
                 int[] bDims = getBinDimsNode.getDimensions(bin);
                 p = bDims[1];
                 if (p == 0) {
-                    throw error(RError.Message.GENERIC, "no right-hand side in 'b'");
+                    throw error(Message.GENERIC, "no right-hand side in 'b'");
                 }
                 int p2 = bDims[0];
                 if (p2 != n) {
-                    throw error(RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", p2, p, "a", n, n);
+                    throw error(Message.MUST_BE_SQUARE_COMPATIBLE, "b", p2, p, "a", n, n);
                 }
                 bData = new double[n * p];
                 b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR);
@@ -583,7 +633,7 @@ public class LaFunctions {
             } else {
                 p = 1;
                 if (bin.getLength() != n) {
-                    throw error(RError.Message.MUST_BE_SQUARE_COMPATIBLE, "b", bin.getLength(), p, "a", n, n);
+                    throw error(Message.MUST_BE_SQUARE_COMPATIBLE, "b", bin.getLength(), p, "a", n, n);
                 }
                 bData = new double[n];
                 b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR);
@@ -606,10 +656,10 @@ public class LaFunctions {
             }
             int info = dgesvNode.execute(n, p, avals, n, ipiv, bData, n);
             if (info < 0) {
-                throw error(RError.Message.LAPACK_INVALID_VALUE, -info, "dgesv");
+                throw error(Message.LAPACK_INVALID_VALUE, -info, "dgesv");
             }
             if (info > 0) {
-                throw error(RError.Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
+                throw error(Message.LAPACK_EXACTLY_SINGULAR, "dgesv", info, info);
             }
             if (tol > 0) {
                 double anorm = dlangeNode.execute('1', n, n, avals, n, null);
@@ -617,7 +667,7 @@ public class LaFunctions {
                 double[] rcond = new double[1];
                 dgeconNode.execute('1', n, avals, n, anorm, rcond, work, ipiv);
                 if (rcond[0] < tol) {
-                    throw error(RError.Message.SYSTEM_COMP_SINGULAR, rcond[0]);
+                    throw error(Message.SYSTEM_COMP_SINGULAR, rcond[0]);
                 }
             }
             return b;
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
index 798c393675..25c8ad506d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
@@ -82,6 +82,14 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
+    private static class JNI_DpotriNode extends DpotriNode {
+        @Override
+        @TruffleBoundary
+        public int execute(char uplo, int n, double[] a, int lda) {
+            return native_dpotri(uplo, n, a, lda);
+        }
+    }
+
     private static class JNI_DpstrfNode extends DpstrfNode {
         @Override
         @TruffleBoundary
@@ -157,6 +165,11 @@ public class JNI_Lapack implements LapackRFFI {
         return new JNI_DpotrfNode();
     }
 
+    @Override
+    public DpotriNode createDpotriNode() {
+        return new JNI_DpotriNode();
+    }
+
     @Override
     public DpstrfNode createDpstrfNode() {
         return new JNI_DpstrfNode();
@@ -198,6 +211,8 @@ public class JNI_Lapack implements LapackRFFI {
 
     private static native int native_dpotrf(char uplo, int n, double[] a, int lda);
 
+    private static native int native_dpotri(char uplo, int n, double[] a, int lda);
+
     private static native int native_dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work);
 
     private static native int native_dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index ae1752dba7..f1086ac6da 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -311,6 +311,7 @@ public final class RError extends RuntimeException {
         NO_NONMISSING_MIN_NA("no non-missing arguments, returning NA"),
         LENGTH_NONNEGATIVE("length must be non-negative number"),
         MUST_BE_POSITIVE("'%s' must be a non-negative number"),
+        MUST_BE_POSITIVE_INT("'%s' must be a positive integer"),
         MUST_BE_POSITIVE_SD("%s must be non-negative number"),
         MUST_BE_SQUARE("'%s' (%d x %d) must be square"),
         MUST_BE_SQUARE_COMPATIBLE("'%s' (%d x %d) must be compatible with '%' (%d x %d)"),
@@ -549,6 +550,7 @@ public final class RError extends RuntimeException {
         DIMS_GT_ZERO("'%s' must have dims > 0"),
         NOT_POSITIVE_DEFINITE("the leading minor of order %d is not positive definite"),
         LAPACK_INVALID_VALUE("argument %d of Lapack routine %s had invalid value"),
+        LAPACK_ZERO_INVERSE("element (%d, %d) is zero, so the inverse cannot be computed"),
         LAPACK_EXACTLY_SINGULAR("Lapack routine %s: system is exactly singular: U[%d,%d] = 0"),
         SYSTEM_COMP_SINGULAR("system is computationally singular: reciprocal condition number = %g"),
         RHS_SHOULD_HAVE_ROWS("right-hand side should have %d not %d rows"),
@@ -580,6 +582,7 @@ public final class RError extends RuntimeException {
         USE_DEFUNCT("use of '%s' is defunct: use %s instead"),
         NCOL_ZERO("nc(0 for non-null data"),
         NROW_ZERO("nr(0 for non-null data"),
+        CANNOT_EXCEED_X("'%s' cannot exceed %s(x) = %d"),
         SAMPLE_LARGER_THAN_POPULATION("cannot take a sample larger than the population when 'replace(FALSE'\n"),
         SAMPLE_OBJECT_NOT_FOUND("object '%s' not found"),
         ERROR_IN_SAMPLE("Error in sample.int(x, size, replace, prob) :  "),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
index 4d8e072cad..30632fc5d3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
@@ -110,6 +110,18 @@ public interface LapackRFFI {
         }
     }
 
+    abstract class DpotriNode extends Node {
+
+        /**
+         * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotri_8f.html">spec</a>.
+         */
+        public abstract int execute(char uplo, int n, double[] a, int lda);
+
+        public static DpotriNode create() {
+            return RFFIFactory.getRFFI().getLapackRFFI().createDpotriNode();
+        }
+    }
+
     abstract class DpstrfNode extends Node {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/dd/dad/dpstrf_8f.html">spec</a>.
@@ -180,6 +192,8 @@ public interface LapackRFFI {
 
     DpotrfNode createDpotrfNode();
 
+    DpotriNode createDpotriNode();
+
     DpstrfNode createDpstrfNode();
 
     DgesvNode createDgesvNode();
-- 
GitLab


From fc02d2f092d0b6cf2d6a62a1156dbf41c0920c44 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 14:34:49 +0200
Subject: [PATCH 205/402] =?UTF-8?q?support=20double=20value=20for=20?=
 =?UTF-8?q?=E2=80=9Cfill=E2=80=9D=20in=20=E2=80=9Ccat=E2=80=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../com/oracle/truffle/r/nodes/builtin/base/Cat.java   | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
index 20c0a39034..4abee5300e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
@@ -26,8 +26,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asBoolean;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asInteger;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyStringVector;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt0;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
@@ -82,9 +80,7 @@ public abstract class Cat extends RBuiltinNode {
 
         casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
 
-        casts.arg("fill").mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().shouldBe(
-                        instanceOf(Byte.class).or(instanceOf(Integer.class).and(gt0())),
-                        Message.NON_POSITIVE_FILL).mapIf(atomicLogicalValue(), asBoolean(), asInteger());
+        casts.arg("fill").mustBe(numericValue()).asVector().mustBe(singleElement()).findFirst().mapIf(atomicLogicalValue(), asBoolean(), asInteger());
 
         casts.arg("labels").mapNull(emptyStringVector()).mustBe(stringValue()).asStringVector();
 
@@ -106,7 +102,9 @@ public abstract class Cat extends RBuiltinNode {
     @Specialization
     protected RNull cat(RList args, int file, RAbstractStringVector sepVec, int givenFillWidth, RAbstractStringVector labels, boolean append) {
         int fillWidth = -1;
-        if (givenFillWidth >= 1) {
+        if (givenFillWidth < 0) {
+            warning(Message.NON_POSITIVE_FILL);
+        } else if (givenFillWidth >= 1) {
             fillWidth = givenFillWidth;
         }
         return output(args, file, sepVec, fillWidth, labels, append);
-- 
GitLab


From 7907ab3bce75ab509fbbd299ee87a56d6d6a2fdc Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 14:35:11 +0200
Subject: [PATCH 206/402] better implementation for format and formatC

---
 .../fficall/src/jni/lapack_rffi.c             |   2 +-
 .../truffle/r/nodes/builtin/base/Format.java  | 186 +++++++++---------
 .../truffle/r/nodes/builtin/base/FormatC.java | 182 ++++++++++++++---
 .../r/nodes/builtin/base/LaFunctions.java     |   2 -
 .../base/printer/ComplexVectorPrinter.java    |  25 ++-
 .../base/printer/DoubleVectorPrinter.java     |  16 +-
 .../base/printer/IntegerVectorPrinter.java    |  25 ++-
 .../builtin/base/printer/ListPrinter.java     |   2 +-
 .../base/printer/LogicalVectorPrinter.java    |  21 +-
 .../builtin/base/printer/PrintParameters.java |   2 +-
 .../truffle/r/nodes/function/RCallNode.java   |   5 +-
 .../com/oracle/truffle/r/test/S4/TestS4.java  |   4 +-
 .../r/test/builtins/TestBuiltin_La.java       |   5 +-
 .../r/test/builtins/TestBuiltin_deriv.java    |   4 +-
 .../r/test/builtins/TestBuiltin_fileinfo.java |   6 +-
 .../r/test/builtins/TestBuiltin_format.java   |  58 ++----
 .../r/test/builtins/TestBuiltin_formatC.java  |  12 +-
 .../test/builtins/TestBuiltin_formatpval.java |   6 +-
 .../r/test/builtins/TestBuiltin_gamma.java    |   2 +-
 .../r/test/builtins/TestBuiltin_lm.java       |  10 +-
 .../test/builtins/TestBuiltin_operators.java  |   3 +-
 .../r/test/builtins/TestBuiltin_print.java    |   7 +-
 .../r/test/builtins/TestBuiltin_summary.java  |   7 +-
 23 files changed, 380 insertions(+), 212 deletions(-)

diff --git a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
index ec9a445966..daa89b365b 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index 1ef9642089..15d6c2f6a8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -19,10 +19,17 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.printer.AnyVectorToStringVectorWriter;
+import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter;
+import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorMetrics;
+import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter;
+import com.oracle.truffle.r.nodes.builtin.base.printer.IntegerVectorPrinter;
+import com.oracle.truffle.r.nodes.builtin.base.printer.LogicalVectorPrinter;
+import com.oracle.truffle.r.nodes.builtin.base.printer.PrintParameters;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
@@ -46,36 +53,13 @@ public abstract class Format extends RBuiltinNode {
     @Child private CastIntegerNode castInteger;
     @Child protected ValuePrinterNode valuePrinter = new ValuePrinterNode();
 
-    protected final BranchProfile errorProfile = BranchProfile.create();
-
-    public static final int R_MAX_DIGITS_OPT = 22;
     public static final int R_MIN_DIGITS_OPT = 0;
+    public static final int R_MAX_DIGITS_OPT = 22;
 
-    private static Config printConfig;
-
-    private static Config setPrintDefaults() {
-        if (printConfig == null) {
-            printConfig = new Config();
-        }
-        printConfig.width = (int) RContext.getInstance().stateROptions.getValue("width");
-        printConfig.naWidth = RRuntime.STRING_NA.length();
-        printConfig.naWidthNoQuote = RRuntime.NA_HEADER.length();
-        printConfig.digits = 7 /* default */;
-        printConfig.scipen = 0 /* default */;
-        printConfig.gap = 1;
-        printConfig.quote = 1;
-        printConfig.right = Adjustment.LEFT;
-        printConfig.max = 99999 /* default */;
-        printConfig.naString = RRuntime.STRING_NA;
-        printConfig.naStringNoQuote = RRuntime.NA_HEADER;
-        printConfig.useSource = 8 /* default */;
-        printConfig.cutoff = 60;
-        return printConfig;
-    }
-
-    private static Config getConfig() {
-        return setPrintDefaults();
-    }
+    public static final int JUSTIFY_LEFT = 0;
+    public static final int JUSTIFY_RIGHT = 1;
+    public static final int JUSTIFY_CENTER = 2;
+    public static final int JUSTIFY_NONE = 3;
 
     private RAbstractIntVector castInteger(Object operand) {
         if (castInteger == null) {
@@ -92,90 +76,116 @@ public abstract class Format extends RBuiltinNode {
         casts.arg("digits").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(R_MIN_DIGITS_OPT).and(lte(R_MAX_DIGITS_OPT))));
         casts.arg("nsmall").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(0).and(lte(20))));
         casts.arg("width").asIntegerVector().findFirst(0).mustNotBeNA();
-        casts.arg("justify").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(0).and(lte(3))));
+        casts.arg("justify").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(JUSTIFY_LEFT).and(lte(JUSTIFY_NONE))));
         casts.arg("na.encode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
         casts.arg("scientific").asIntegerVector().findFirst();
         casts.arg("decimal.mark").asStringVector().findFirst();
     }
 
-    @Specialization
-    protected RStringVector format(RAbstractLogicalVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific,
-                    String decimalMark) {
-        return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new);
-    }
-
-    @Specialization
-    protected RStringVector format(RAbstractIntVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific,
-                    String decimalMark) {
-        return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new);
+    private static char getDecimalMark(String decimalMark) {
+        return decimalMark.length() == 0 ? '.' : decimalMark.charAt(0);
     }
 
-    // TODO: even though format's arguments are not used at this point, their processing mirrors
-    // what GNU R does
-
-    private int computeSciArg(RAbstractVector sciVec) {
-        assert sciVec.getLength() > 0;
-        int tmp = castInteger(sciVec).getDataAt(0);
-        int ret;
-        if (sciVec instanceof RAbstractLogicalVector) {
-            if (RRuntime.isNA(tmp)) {
-                ret = tmp;
-            } else {
-                ret = tmp > 0 ? -100 : 100;
-            }
-        } else {
-            ret = tmp;
+    private static PrintParameters getParameters(int digits, int scientific) {
+        PrintParameters pp = new PrintParameters();
+        pp.setDefaults();
+        if (!RRuntime.isNA(digits)) {
+            pp.setDigits(digits);
         }
-        if (!RRuntime.isNA(ret)) {
-            getConfig().scipen = ret;
+        if (!RRuntime.isNA(scientific)) {
+            pp.setScipen(scientific);
         }
-        return ret;
+        return pp;
+    }
+
+    private static RStringVector createResult(RAbstractVector value, String[] array) {
+        RStringVector result = RDataFactory.createStringVector(array, value.isComplete(), value.getDimensions(), value.getNames());
+        result.setDimNames(value.getDimNames());
+        return result;
     }
 
     @Specialization
-    protected RStringVector format(RAbstractDoubleVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific,
-                    String decimalMark) {
-        return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new);
+    @TruffleBoundary
+    protected RStringVector format(RAbstractLogicalVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
+        String[] result = LogicalVectorPrinter.format(value, trim, width, getParameters(digits, scientific));
+        return createResult(value, result);
     }
 
     @Specialization
-    protected RStringVector format(RAbstractComplexVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific,
-                    String decimalMark) {
-        return (RStringVector) valuePrinter.prettyPrint(value, AnyVectorToStringVectorWriter::new);
+    @TruffleBoundary
+    protected RStringVector format(RAbstractIntVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
+        String[] result = IntegerVectorPrinter.format(value, trim, width, getParameters(digits, scientific));
+        return createResult(value, result);
     }
 
     @Specialization
-    protected RStringVector format(REnvironment value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific,
-                    String decimalMark) {
-        return RDataFactory.createStringVector(value.getPrintName());
+    @TruffleBoundary
+    protected RStringVector format(RAbstractDoubleVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
+        String[] result = DoubleVectorPrinter.format(value, trim, nsmall, width, getDecimalMark(decimalMark), getParameters(digits, scientific));
+        return createResult(value, result);
     }
 
     @Specialization
-    protected RStringVector format(RAbstractStringVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
-        // TODO: implement full semantics
-        return value.materialize();
+    @TruffleBoundary
+    protected RStringVector format(RAbstractComplexVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
+        String[] result = ComplexVectorPrinter.format(value, trim, nsmall, width, getDecimalMark(decimalMark), getParameters(digits, scientific));
+        return createResult(value, result);
     }
 
-    private static class Config {
-        public int width;
-        public int naWidth;
-        public int naWidthNoQuote;
-        public int digits;
-        public int scipen;
-        public int gap;
-        public int quote;
-        public Adjustment right;
-        public int max;
-        public String naString;
-        public String naStringNoQuote;
-        public int useSource;
-        public int cutoff;
+    @Specialization
+    protected RStringVector format(REnvironment value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
+        return RDataFactory.createStringVector(value.getPrintName());
     }
 
-    private enum Adjustment {
-        LEFT,
-        RIGHT,
-        CENTRE,
-        NONE;
+    @Specialization
+    @TruffleBoundary
+    protected RStringVector format(RAbstractStringVector value, boolean trim, int digits, int nsmall, int width, int justify, boolean naEncode, int scientific, String decimalMark) {
+        PrintParameters pp = getParameters(digits, scientific);
+        int w;
+        if (justify == JUSTIFY_NONE) {
+            w = 0;
+        } else {
+            w = width;
+            for (int i = 0; i < value.getLength(); i++) {
+                String element = value.getDataAt(i);
+                if (RRuntime.isNA(element)) {
+                    if (naEncode) {
+                        w = Math.max(w, pp.getNaWidth());
+                    }
+                } else {
+                    w = Math.max(w, element.length());
+                }
+            }
+        }
+        String[] result = new String[value.getLength()];
+        for (int i = 0; i < value.getLength(); i++) {
+            String element = value.getDataAt(i);
+            if (!naEncode && RRuntime.isNA(element)) {
+                result[i] = RRuntime.STRING_NA;
+            } else {
+                String s0;
+                if (RRuntime.isNA(element)) {
+                    element = pp.getNaString();
+                }
+                int il = element.length();
+                int b = w - il;
+                StringBuilder str = new StringBuilder(Math.max(w, il));
+                if (b > 0 && justify != JUSTIFY_LEFT) {
+                    int b0 = (justify == JUSTIFY_CENTER) ? b / 2 : b;
+                    for (int j = 0; j < b0; j++) {
+                        str.append(' ');
+                    }
+                    b -= b0;
+                }
+                str.append(element);
+                if (b > 0 && justify != JUSTIFY_RIGHT) {
+                    for (int j = 0; j < b; j++) {
+                        str.append(' ');
+                    }
+                }
+                result[i] = str.toString();
+            }
+        }
+        return createResult(value, result);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
index b872f1187f..f0d0e4ea81 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
@@ -11,37 +11,31 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.CastStringNode;
-import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.Round.RoundArithmetic;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "formatC", kind = INTERNAL, parameterNames = {"x", "mode", "width", "digits", "format", "flag", "i.strlen"}, behavior = PURE)
 public abstract class FormatC extends RBuiltinNode {
 
-    @Child private CastStringNode castStringNode;
-
-    private RStringVector castStringVector(Object o) {
-        if (castStringNode == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            castStringNode = insert(CastStringNodeGen.create(true, true, true));
-        }
-        return (RStringVector) ((RStringVector) castStringNode.executeString(o)).copyDropAttributes();
-    }
+    @Child private RoundArithmetic round = new RoundArithmetic();
 
     static {
         Casts casts = new Casts(FormatC.class);
-        casts.arg("x");
+        casts.arg("x").mustBe(integerValue().or(doubleValue()), Message.UNSUPPORTED_TYPE);
         casts.arg("mode").asStringVector().findFirst();
         casts.arg("width").asIntegerVector().findFirst();
         casts.arg("digits").asIntegerVector().findFirst();
@@ -50,12 +44,154 @@ public abstract class FormatC extends RBuiltinNode {
         casts.arg("i.strlen").asIntegerVector().findFirst();
     }
 
-    @SuppressWarnings("unused")
     @Specialization
-    RAttributable formatC(RAbstractContainer x, String mode, int width, int digits, String format, String flag, int iStrlen,
-                    @Cached("create()") SetClassAttributeNode setClassAttrNode) {
-        RStringVector res = castStringVector(x);
-        setClassAttrNode.reset(res);
-        return res;
+    @TruffleBoundary
+    RAttributable formatC(RAbstractVector x, String mode, int width, int digits, String format, String flag, @SuppressWarnings("unused") int iStrlen) {
+        // ignores iStrlen
+        RType type = "integer".equals(mode) ? RType.Integer : RType.Double;
+        String[] result = strSignif(x, type, width, digits, format, flag);
+        return RDataFactory.createStringVector(result, true);
+    }
+
+    /*
+     * Former src/appl/strsignif.c
+     *
+     * Copyright (C) Martin Maechler, 1994, 1998 Copyright (C) 2001-2013 the R Core Team
+     *
+     * I want you to preserve the copyright of the original author(s), and encourage you to send me
+     * any improvements by e-mail. (MM).
+     *
+     * Originally from Bill Dunlap bill@stat.washington.edu Wed Feb 21, 1990
+     *
+     * Much improved by Martin Maechler, including the "fg" format.
+     *
+     * Patched by Friedrich.Leisch@ci.tuwien.ac.at Fri Nov 22, 1996
+     *
+     * Some fixes by Ross Ihaka ihaka@stat.auckland.ac.nz Sat Dec 21, 1996 Integer arguments changed
+     * from "long" to "int" Bus error due to non-writable strings fixed
+     *
+     * BDR 2001-10-30 use R_alloc not Calloc as memory was not reclaimed on error (and there are
+     * many error exits).
+     *
+     * type "double" or "integer" (R - numeric 'mode').
+     *
+     * width The total field width; width < 0 means to left justify the number in this field
+     * (equivalent to flag = "-"). It is possible that the result will be longer than this, but that
+     * should only happen in reasonable cases.
+     *
+     * digits The desired number of digits after the decimal point. digits < 0 uses the default for
+     * C, namely 6 digits.
+     *
+     * format "d" (for integers) or "f", "e","E", "g", "G" (for 'real') "f" gives numbers in the
+     * usual "xxx.xxx" format; "e" and "E" give n.ddde<nn> or n.dddE<nn> (scientific format); "g"
+     * and "G" puts them into scientific format if it saves space to do so. NEW: "fg" gives numbers
+     * in "xxx.xxx" format as "f", ~~ however, digits are *significant* digits and, if digits > 0,
+     * no trailing zeros are produced, as in "g".
+     *
+     * flag Format modifier as in K&R "C", 2nd ed., p.243; e.g., "0" pads leading zeros; "-" does
+     * left adjustment the other possible flags are "+", " ", and "#". New (Feb.98): if flag has
+     * more than one character, all are passed..
+     */
+
+    private String[] strSignif(RAbstractVector x, RType type, int width, int digits, String format, String flag) {
+        int dig = Math.abs(digits);
+        boolean rmTrailing0 = digits >= 0;
+        boolean doFg = "fg".equals(format); /* TRUE iff format == "fg" */
+
+        if (width == 0) {
+            throw error(Message.GENERIC, "width cannot be zero");
+        }
+
+        String[] result = new String[x.getLength()];
+        if ("d".equals(format)) {
+            String form = "%" + flag + width + "d";
+            if (type == RType.Integer) {
+                for (int i = 0; i < x.getLength(); i++) {
+                    result[i] = String.format(form, x.getDataAtAsObject(i));
+                }
+            } else {
+                throw error(Message.GENERIC, "'type' must be \"integer\" for  \"d\"-format");
+            }
+        } else { /* --- floating point --- */
+
+            if (type == RType.Double) {
+                if (doFg) { /* do smart "f" : */
+                    for (int i = 0; i < x.getLength(); i++) {
+                        double xx = ((RAbstractDoubleVector) x).getDataAt(i);
+                        if (xx == 0.) {
+                            result[i] = "0";
+                        } else {
+                            /*
+                             * This was iex= (int)floor(log10(fabs(xx))) That's wrong, as xx might
+                             * get rounded up, and we do need some fuzz or 99.5 is correct.
+                             */
+                            double xxx = Math.abs(xx);
+                            int iex = (int) Math.floor(Math.log10(xxx) + 1e-12);
+                            double scaledX = round.opd(xxx / Math.pow(10, iex) + 1e-12, dig - 1);
+                            if (iex > 0 && scaledX >= 10) {
+                                xx = scaledX * Math.pow(10, iex);
+                                iex++;
+                            }
+                            if (iex == -4 && Math.abs(xx) < 1e-4) {
+                                /* VERY rare case */
+                                iex = -5;
+                            }
+                            if (iex < -4) {
+                                /* "g" would result in 'e-' representation: */
+                                String form = "%" + flag + "." + (dig - 1 + -iex) + "f";
+                                String str = String.format(form, xx);
+                                /* Remove trailing "0"s __ IFF flag has no '#': */
+                                if (rmTrailing0) {
+                                    int j = str.length();
+                                    while (j > 0 && str.charAt(j - 1) == '0') {
+                                        j--;
+                                    }
+                                    if (j != str.length()) {
+                                        str = str.substring(0, j);
+                                    }
+                                }
+                                result[i] = str;
+                            } else { /* iex >= -4: NOT "e-" */
+                                /* if iex >= dig, would have "e+" representation */
+                                String formatString = "%" + flag + width + "." + ((iex >= dig) ? (iex + 1) : dig) + "g";
+                                result[i] = trimZero(String.format(formatString, xx));
+                            }
+                        } /* xx != 0 */
+                    } /* if(do_fg) for(i..) */
+                } else {
+                    String form = "%" + flag + width + "." + dig + format;
+                    for (int i = 0; i < x.getLength(); i++) {
+                        String str = String.format(form, x.getDataAtAsObject(i));
+                        result[i] = ("g".equals(format) || "f".equals(format)) ? trimZero(str) : str;
+                    }
+                }
+            } else {
+                throw error(Message.GENERIC, "'type' must be \"real\" for this format");
+            }
+        }
+        return result;
+    }
+
+    private static String trimZero(String str) {
+        int i = str.length();
+        while (i > 0 && str.charAt(i - 1) == '0') {
+            i--;
+        }
+        if (i > 0 && str.charAt(i - 1) == '.') {
+            i--;
+            return str.substring(0, i);
+        }
+        if (i == str.length()) {
+            return str;
+        }
+        // need to check whether we're after the decimal point:
+        int j = i;
+        while (j > 0 && str.charAt(j - 1) >= '0' && str.charAt(j) <= '9') {
+            j--;
+        }
+        if (j > 0 && str.charAt(j - 1) == '.') {
+            return str.substring(0, i);
+        }
+        return str;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 956badb0e4..64f880fc2a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
@@ -83,7 +82,6 @@ public class LaFunctions {
 
     private abstract static class RsgRBuiltinNode extends RBuiltinNode {
         protected static final String[] NAMES = new String[]{"values", "vectors"};
-        protected final BranchProfile errorProfile = BranchProfile.create();
 
         protected static Casts createCasts(Class<? extends RsgRBuiltinNode> extClass) {
             Casts casts = new Casts(extClass);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
index 8181e251d4..635ec09626 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
@@ -58,7 +58,7 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
             ComplexVectorMetrics cfm = (ComplexVectorMetrics) fm;
-            String v = encodeComplex(vector.getDataAt(i), cfm, printCtx.parameters());
+            String v = encodeComplex(vector.getDataAt(i), cfm, '.', printCtx.parameters());
             out.print(v);
         }
 
@@ -401,20 +401,20 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
     @TruffleBoundary
     public static String encodeComplex(RComplex x, int digits, int sciPen, String naString) {
         ComplexVectorMetrics cvm = formatComplexVector(x, 0, 1, 0, digits, sciPen, naString.length());
-        return encodeComplex(x, cvm, digits, naString);
+        return encodeComplex(x, cvm, '.', digits, naString);
     }
 
     @TruffleBoundary
-    static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, PrintParameters pp) {
-        return encodeComplex(x, cvm, pp.getDigits(), pp.getNaString());
+    static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, char cdec, PrintParameters pp) {
+        return encodeComplex(x, cvm, cdec, pp.getDigits(), pp.getNaString());
     }
 
     @TruffleBoundary
-    static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, int digits, String naString) {
+    static String encodeComplex(RComplex x, ComplexVectorMetrics cvm, char cdec, int digits, String naString) {
         if (x.isNA()) {
-            return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, '.', naString);
+            return DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, cvm.maxWidth, 0, 0, cdec, naString);
         } else {
-            String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, '.', digits, naString);
+            String s = encodeComplex(x, cvm.wr, cvm.dr, cvm.er, cvm.wi, cvm.di, cvm.ei, cdec, digits, naString);
             int g = cvm.maxWidth - cvm.wr - cvm.wi - 2;
             if (g > 0) {
                 // fill the remaining space by blanks to fit the maxWidth
@@ -475,4 +475,15 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
         }
         return buff;
     }
+
+    public static String[] format(RAbstractComplexVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) {
+        ComplexVectorMetrics dfm = formatComplexVector(value, 0, value.getLength(), nsmall, pp);
+        ComplexVectorMetrics adjusted = new ComplexVectorMetrics(Math.max(trim ? 1 : dfm.wr, width), dfm.dr, dfm.er, Math.max(trim ? 1 : dfm.wi, width), dfm.di, dfm.ei);
+
+        String[] result = new String[value.getLength()];
+        for (int i = 0; i < value.getLength(); i++) {
+            result[i] = encodeComplex(value.getDataAt(i), adjusted, decimalMark, pp);
+        }
+        return result;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
index b692c0fd51..9ee413f6e6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
@@ -77,7 +77,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
     }
 
     @TruffleBoundary
-    static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) {
+    public static DoubleVectorMetrics formatDoubleVector(RAbstractDoubleVector x, int offs, int n, int nsmall, int digits, int sciPen, int naWidth) {
         int left;
         int right;
         int sleft;
@@ -438,8 +438,7 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
     }
 
     private static String prependBlanks(int width, String id) {
-        assert id.length() <= width;
-        if (id.length() == width) {
+        if (id.length() >= width) {
             return id;
         }
         StringBuilder str = new StringBuilder(width);
@@ -448,4 +447,15 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
         }
         return str.append(id).toString();
     }
+
+    public static String[] format(RAbstractDoubleVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) {
+        DoubleVectorMetrics dfm = formatDoubleVector(value, 0, value.getLength(), nsmall, pp);
+        int w = Math.max(trim ? 1 : dfm.maxWidth, width);
+
+        String[] result = new String[value.getLength()];
+        for (int i = 0; i < value.getLength(); i++) {
+            result[i] = encodeReal(value.getDataAt(i), w, dfm.d, dfm.e, decimalMark, pp);
+        }
+        return result;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
index 726492384f..5453a2fa40 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -20,7 +20,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 //Transcribed from GnuR, src/main/printutils.c, src/main/format.c
 
-final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> {
+public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> {
 
     static final IntegerVectorPrinter INSTANCE = new IntegerVectorPrinter();
 
@@ -66,7 +66,7 @@ final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> {
         }
     }
 
-    static FormatMetrics formatIntVector(RAbstractIntVector x, int offs, int n, int naWidth) {
+    public static FormatMetrics formatIntVector(RAbstractIntVector x, int offs, int n, int naWidth) {
         int xmin = RRuntime.INT_MAX_VALUE;
         int xmax = RRuntime.INT_MIN_VALUE;
         boolean naflag = false;
@@ -114,11 +114,28 @@ final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector> {
      */
     static int NB = 1000;
 
-    static String encodeInteger(int x, int w, PrintParameters pp) {
+    public static String encodeInteger(int x, int w, PrintParameters pp) {
         if (x == RRuntime.INT_NA) {
             return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s", pp.getNaString());
         } else {
             return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "d", x);
         }
     }
+
+    public static String[] format(RAbstractIntVector value, boolean trim, int width, PrintParameters pp) {
+        int w;
+        if (trim) {
+            w = 1;
+        } else {
+            FormatMetrics metrics = formatIntVector(value, 0, value.getLength(), pp.getNaWidth());
+            w = metrics.maxWidth;
+        }
+        w = Math.max(w, width);
+
+        String[] result = new String[value.getLength()];
+        for (int i = 0; i < value.getLength(); i++) {
+            result[i] = encodeInteger(value.getDataAt(i), w, pp);
+        }
+        return result;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index 9c04b376ee..3cde3e059f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -113,7 +113,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
                         pbuf = DoubleVectorPrinter.encodeReal(RRuntime.DOUBLE_NA, pp.getNaWidth(), 0, 0, '.', pp);
                     } else {
                         ComplexVectorMetrics cvm = ComplexVectorPrinter.formatComplexVector(x, 0, 1, 0, pp);
-                        pbuf = ComplexVectorPrinter.encodeComplex(x, cvm, pp);
+                        pbuf = ComplexVectorPrinter.encodeComplex(x, cvm, '.', pp);
                     }
                 } else {
                     pbuf = "Complex," + cv.getLength();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
index 5e0272f34c..2923162499 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2013,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -21,7 +21,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
 //Transcribed from GnuR, src/main/printutils.c, src/main/format.c
 
-final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVector> {
+public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVector> {
 
     static final LogicalVectorPrinter INSTANCE = new LogicalVectorPrinter();
 
@@ -96,4 +96,21 @@ final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVector> {
             return snprintf(NB, fmt, "FALSE");
         }
     }
+
+    public static String[] format(RAbstractLogicalVector value, boolean trim, int width, PrintParameters pp) {
+        int w;
+        if (trim) {
+            w = 1;
+        } else {
+            FormatMetrics metrics = formatLogicalVector(value, 0, value.getLength(), pp.getNaWidth());
+            w = metrics.maxWidth;
+        }
+        w = Math.max(w, width);
+
+        String[] result = new String[value.getLength()];
+        for (int i = 0; i < value.getLength(); i++) {
+            result[i] = encodeLogical(value.getDataAt(i), w, pp);
+        }
+        return result;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
index 6f7bbfa855..45a9a4724b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
@@ -139,7 +139,7 @@ public final class PrintParameters {
     }
 
     public void setDefaults() {
-        this.naString = RRuntime.STRING_NA;
+        this.naString = "NA";
         this.naStringNoquote = "<NA>";
         this.naWidth = this.naString.length();
         this.naWidthNoquote = this.naStringNoquote.length();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 94e738e581..d9a6c913e2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -47,7 +47,6 @@ import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.SourceSection;
@@ -539,8 +538,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         @Child private Node foreignCall;
         @CompilationFinal private int foreignCallArgCount;
 
-        private final BranchProfile errorProfile = BranchProfile.create();
-
         public ForeignCall(CallArgumentsNode arguments) {
             this.arguments = arguments;
         }
@@ -561,7 +558,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                 }
                 return result;
             } catch (Throwable e) {
-                errorProfile.enter();
+                CompilerDirectives.transferToInterpreter();
                 throw RError.interopError(RError.findParentRBase(this), e, function);
             }
         }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 5fd998ead2..d5cf915d84 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -101,9 +101,7 @@ public class TestS4 extends TestRBase {
 
     @Test
     public void testClassCreation() {
-        // output slightly different from GNU R even though we use R's "show" method to print it
-        assertEval(Ignored.OutputFormatting, "{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }");
-
+        assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }");
         assertEval("{ setClass(\"foo\"); setClass(\"bar\", representation(j = \"numeric\"), contains = \"foo\"); is.null(getClass(\"foo\")@prototype) }");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java
index f6e94d3f58..62d41240e2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_La.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -68,8 +68,7 @@ public class TestBuiltin_La extends TestBase {
 
     @Test
     public void testLa9() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-9.64365076099295, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, -29634.0055320061, -5658.08855789941, 0.0595010632288954, 0.0648032071760975, 0.106336668095848, -0.0279843118999398, 0.0762911857283688, 0.188519899277481, 0.0807096390177039, 0.102801905464379, 0.158474416910002, -0.0969121832135675, -0.0447744343994132, 0.0356414154664858, 0.0276881995456826, -5.08106330417909, 3.14280306547868, 3.64768208463163, 0.0962151262827947, -0.216651778533863, -0.0914289830351174, 0.0855052819309283, -0.0191216590449975, 0.0813861110263642, 0.0607902565035442, 0.00888870310603775, -0.027169916923919, -0.0757761335977742, 0.123401654252917, -0.143330536432624, -0.207390338946085, -0.18719988871654, -0.127596387499216, 1.38045811630541, 0.0118370110620473, 0.00504893180870276, 0.0281684584122627, 0.0338400772620966, 0.0283917504929648, 0.0295082108964754, 0.0323216911133222, 0.00156557534974961, 0.00420042190203468, 0.0261141712698031, 0.00786241202554953, -3.21455025366432, -2.66432733346907, -2.18217405946767, -1.0459324747522, 2.77707906967759, -0.000588115022584812, -0.0784367740030637, -0.0437014732535189, -0.0770692424774911, 0.28985899050302, 0.307089887725235, -0.0219216068215179, -0.00578473481976082, -0.0910180640383319, 0.0166427821996303, -0.725866186311298, -0.943724610301472, -0.197997366006898, -0.255325765345392, -1.99736582726463, 1.22009740929232, -0.000660179745382102, 0.118090770461339, 0.00401505451472504, -0.265276591063721, -0.206368639386371, -0.0413572976755921, 0.0138104665936721, -0.0436723349383677, 0.0904843084594291, -0.103695169473043, 0.0314422837299137, -0.171533212490836, -0.0271695331685966, -0.234884785308008, -0.455412006973628, -0.833981960018826, -0.0497205266764892, -0.00169048456815939, 0.0359873442560765, 0.0111849454624309, 0.0174129325629219, -0.00581471075176227, 0.0183876477886015, -0.0380971980704758, -1.14064686420347, -1.21031412747477, -0.546078284372325, -0.385964209884133, -0.535335872363138, 0.617909299639904, 0.034437791264286, -2.66782912116871, -0.0707120154460491, 0.170259689757997, -0.200116024334743, -0.0120487035676503, -0.00787104751465206, -0.0743232096613527, -0.00206481367828156, -2.28129372840694, -1.27183039972242, -0.162921372163874, 0.194143545128708, 0.405329624202872, -0.0239884453210967, 0.161826508366356, 1.47283157923894, -3.57122150532158, 0.0184573285734211, 0.0768346205272587, -0.00300367200170235, -0.047539037475449, -0.0955077077363865, 0.170580587807138, -2.17759855893389, 2.82091161681306, -0.529126651121425, 0.00648102843720064, -0.227590137804697, 0.429332016819553, 0.315382802791974, -0.0921680424483324, 0.358484158960907, 2.74734594573339, -0.00180797874108619, 0.211048746835586, 0.146553774483952, 0.0892496085418831, 0.02104367339158, -1.4517323726226, 0.428703993666521, -0.198393471445493, -0.178300389025286, -0.0518091667043893, 0.133208332446864, -1.01393441911662, 0.520772381447608, 0.936102434059857, -1.6420319436063, 2.59716822825227, 0.194828402482676, 0.15057424104202, -0.232155536267878, -0.0298159890277092, -0.933256525257383, -1.20515451427884, 0.0125087156504907, 0.421920000319943, 0.452875082015975, -0.655679104390575, 0.284781968418535, 0.643096539054797, 1.38165893036928, 0.447700892848835, -0.482856979100538, 1.73960015308741, 0.115853953901054, 0.107343556163412, -0.0385322695831968, -25.7267715462619, -8.40853040573162, -1.45105839286435, -1.58984152452525, -1.59606771970776, 2.79428919380473, 0.596892611732863, -1.03839368638655, -0.0376487500979583, -0.507302835476536, 0.184174590388395, -0.70905481454677, -3.32884312972433, 0.134236291836065, -0.0993249017707237, -6.94757635469386, 1.58613921242054, 0.195741168102286, 0.638223445194413, 1.07571321411184, 0.659104584950073, 0.199707908602043, -0.565980943574209, -0.967985377031296, -0.112927393875596, -0.934672543429794, 0.198159847509218, 0.275086401661377, 3.44668029704689, -0.05066048099299, -1.65912271156868, -1.17593571026872, -0.20132598039105, -0.42732880950559, -1.20727437557593, 0.102943259109259, -0.697974199306205, 0.103630431164098, -0.0620963660266192, -0.16978912837867, 0.739571733406047, -0.872308493604205, -0.757980967070979, -2.00985526447536, -1.92891236077264), .Dim = c(15L, 15L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'), c('(Intercept)', 'Weight', 'Cylinders4', 'Cylinders5', 'Cylinders6', 'Cylinders8', 'Cylindersrotary', 'TypeLarge', 'TypeMidsize', 'TypeSmall', 'TypeSporty', 'TypeVan', 'EngineSize', 'DriveTrainFront', 'DriveTrainRear'))), 15L); .Internal(La_chol2inv(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(-9.64365076099295, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, -29634.0055320061, -5658.08855789941, 0.0595010632288954, 0.0648032071760975, 0.106336668095848, -0.0279843118999398, 0.0762911857283688, 0.188519899277481, 0.0807096390177039, 0.102801905464379, 0.158474416910002, -0.0969121832135675, -0.0447744343994132, 0.0356414154664858, 0.0276881995456826, -5.08106330417909, 3.14280306547868, 3.64768208463163, 0.0962151262827947, -0.216651778533863, -0.0914289830351174, 0.0855052819309283, -0.0191216590449975, 0.0813861110263642, 0.0607902565035442, 0.00888870310603775, -0.027169916923919, -0.0757761335977742, 0.123401654252917, -0.143330536432624, -0.207390338946085, -0.18719988871654, -0.127596387499216, 1.38045811630541, 0.0118370110620473, 0.00504893180870276, 0.0281684584122627, 0.0338400772620966, 0.0283917504929648, 0.0295082108964754, 0.0323216911133222, 0.00156557534974961, 0.00420042190203468, 0.0261141712698031, 0.00786241202554953, -3.21455025366432, -2.66432733346907, -2.18217405946767, -1.0459324747522, 2.77707906967759, -0.000588115022584812, -0.0784367740030637, -0.0437014732535189, -0.0770692424774911, 0.28985899050302, 0.307089887725235, -0.0219216068215179, -0.00578473481976082, -0.0910180640383319, 0.0166427821996303, -0.725866186311298, -0.943724610301472, -0.197997366006898, -0.255325765345392, -1.99736582726463, 1.22009740929232, -0.000660179745382102, 0.118090770461339, 0.00401505451472504, -0.265276591063721, -0.206368639386371, -0.0413572976755921, 0.0138104665936721, -0.0436723349383677, 0.0904843084594291, -0.103695169473043, 0.0314422837299137, -0.171533212490836, -0.0271695331685966, -0.234884785308008, -0.455412006973628, -0.833981960018826, -0.0497205266764892, -0.00169048456815939, 0.0359873442560765, 0.0111849454624309, 0.0174129325629219, -0.00581471075176227, 0.0183876477886015, -0.0380971980704758, -1.14064686420347, -1.21031412747477, -0.546078284372325, -0.385964209884133, -0.535335872363138, 0.617909299639904, 0.034437791264286, -2.66782912116871, -0.0707120154460491, 0.170259689757997, -0.200116024334743, -0.0120487035676503, -0.00787104751465206, -0.0743232096613527, -0.00206481367828156, -2.28129372840694, -1.27183039972242, -0.162921372163874, 0.194143545128708, 0.405329624202872, -0.0239884453210967, 0.161826508366356, 1.47283157923894, -3.57122150532158, 0.0184573285734211, 0.0768346205272587, -0.00300367200170235, -0.047539037475449, -0.0955077077363865, 0.170580587807138, -2.17759855893389, 2.82091161681306, -0.529126651121425, 0.00648102843720064, -0.227590137804697, 0.429332016819553, 0.315382802791974, -0.0921680424483324, 0.358484158960907, 2.74734594573339, -0.00180797874108619, 0.211048746835586, 0.146553774483952, 0.0892496085418831, 0.02104367339158, -1.4517323726226, 0.428703993666521, -0.198393471445493, -0.178300389025286, -0.0518091667043893, 0.133208332446864, -1.01393441911662, 0.520772381447608, 0.936102434059857, -1.6420319436063, 2.59716822825227, 0.194828402482676, 0.15057424104202, -0.232155536267878, -0.0298159890277092, -0.933256525257383, -1.20515451427884, 0.0125087156504907, 0.421920000319943, 0.452875082015975, -0.655679104390575, 0.284781968418535, 0.643096539054797, 1.38165893036928, 0.447700892848835, -0.482856979100538, 1.73960015308741, 0.115853953901054, 0.107343556163412, -0.0385322695831968, -25.7267715462619, -8.40853040573162, -1.45105839286435, -1.58984152452525, -1.59606771970776, 2.79428919380473, 0.596892611732863, -1.03839368638655, -0.0376487500979583, -0.507302835476536, 0.184174590388395, -0.70905481454677, -3.32884312972433, 0.134236291836065, -0.0993249017707237, -6.94757635469386, 1.58613921242054, 0.195741168102286, 0.638223445194413, 1.07571321411184, 0.659104584950073, 0.199707908602043, -0.565980943574209, -0.967985377031296, -0.112927393875596, -0.934672543429794, 0.198159847509218, 0.275086401661377, 3.44668029704689, -0.05066048099299, -1.65912271156868, -1.17593571026872, -0.20132598039105, -0.42732880950559, -1.20727437557593, 0.102943259109259, -0.697974199306205, 0.103630431164098, -0.0620963660266192, -0.16978912837867, 0.739571733406047, -0.872308493604205, -0.757980967070979, -2.00985526447536, -1.92891236077264), .Dim = c(15L, 15L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'), c('(Intercept)', 'Weight', 'Cylinders4', 'Cylinders5', 'Cylinders6', 'Cylinders8', 'Cylindersrotary', 'TypeLarge', 'TypeMidsize', 'TypeSmall', 'TypeSporty', 'TypeVan', 'EngineSize', 'DriveTrainFront', 'DriveTrainRear'))), 15L); .Internal(La_chol2inv(argv[[1]], argv[[2]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
index 63dfe59737..3dcdec562d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
@@ -131,7 +131,7 @@ public class TestBuiltin_deriv extends TestBase {
 
     @Test
     public void testDeriveFunctions1() {
-        deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(Ignored.MissingWarning, -1);
+        deriv1("log(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0).eval(1).eval(-1);
         assertDerivAndEval1("exp(x)");
         assertDerivAndEval1("cos(x)");
         assertDerivAndEval1("sin(x)");
@@ -145,7 +145,7 @@ public class TestBuiltin_deriv extends TestBase {
         assertDerivAndEval1("asin(x)");
         assertDerivAndEval1(Ignored.OutputFormatting, "acos(x)");
         deriv1("atan(x)").derive().eval(0).withHessian().derive(Ignored.OutputFormatting).eval(0);
-        assertDeriv1("gamma(x)").eval(Ignored.Unimplemented, 0);
+        assertDeriv1("gamma(x)").eval(0);
         assertDeriv1("lgamma(x)").eval(0.5);
         assertDeriv1("digamma(x)").eval(Ignored.Unimplemented, 0);
         assertDeriv1("trigamma(x)").eval(Ignored.Unimplemented, 0);
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java
index 8f25d9475f..9802cd410e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_fileinfo.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -19,11 +19,11 @@ public class TestBuiltin_fileinfo extends TestBase {
 
     @Test
     public void testfileinfo1() {
-        assertEval(Ignored.Unknown, "argv <- list('/home/lzhao/hg/r-instrumented/library/codetools/data'); .Internal(file.info(argv[[1]]))");
+        assertEval("argv <- list('/home/lzhao/hg/r-instrumented/library/codetools/data'); .Internal(file.info(argv[[1]]))");
     }
 
     @Test
     public void testfileinfo2() {
-        assertEval(Ignored.Unknown, "argv <- list(character(0)); .Internal(file.info(argv[[1]]))");
+        assertEval("argv <- list(character(0)); .Internal(file.info(argv[[1]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java
index d783aa1d15..c426128a20 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java
@@ -19,7 +19,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat1() {
-        assertEval(Ignored.Unknown,
+        assertEval(Output.IgnoreErrorMessage,
                         "argv <- list(structure(c(0, 72.7, 56.4, 72.7, 0, 63.3, 56.4, 63.3, 0), .Dim = c(3L, 3L), .Dimnames = list(c('Girth', 'Height', 'Volume'), c('Girth', 'Height', 'Volume'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]], , argv[[9]]))");
     }
 
@@ -30,14 +30,12 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat3() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c('Inf', '-Inf', 'NaN', 'NA'), FALSE, NULL, 0L, 4, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c('Inf', '-Inf', 'NaN', 'NA'), FALSE, NULL, 0L, 4, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat4() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c('axx', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), .Dim = c(2L, 4L)), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c('axx', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), .Dim = c(2L, 4L)), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -47,8 +45,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat7() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c('a', 'NA', NA, 'b'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c('a', 'NA', NA, 'b'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -73,8 +70,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat12() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -84,14 +80,12 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat14() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(NA, 1, 1, 1), .Names = c('<none>', '- x4', '- x2', '- x1')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c(NA, 1, 1, 1), .Names = c('<none>', '- x4', '- x2', '- x1')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat15() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(2.22044604925031e-16, FALSE, 1, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(2.22044604925031e-16, FALSE, 1, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -121,14 +115,12 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat23() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(NA, 2L, 4L, 7L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c(NA, 2L, 4L, 7L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat24() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(1.1+0i, NA, 3+0i), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c(1.1+0i, NA, 3+0i), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -143,26 +135,22 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat27() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(142L, 104L, 71L, 250L), .Dim = 4L, .Dimnames = structure(list(c('(1) Approve STRONGLY', '(2) Approve SOMEWHAT', '(3) Disapprove SOMEWHAT', '(4) Disapprove STRONGLY')), .Names = '')), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c(142L, 104L, 71L, 250L), .Dim = 4L, .Dimnames = structure(list(c('(1) Approve STRONGLY', '(2) Approve SOMEWHAT', '(3) Disapprove SOMEWHAT', '(4) Disapprove STRONGLY')), .Names = '')), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat28() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c('***', '*', ' ', ' ', ' '), legend = '0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1', class = 'noquote'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c('***', '*', ' ', ' ', ' '), legend = '0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1', class = 'noquote'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat29() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0, 5, 118, 57, 0, 1, 4, 140, 0, 11, 154, 14, 0, 13, 13, 80, 35, 13, 387, 75, 17, 14, 89, 76, 0, 0, 670, 192, 0, 0, 3, 20), .Dim = c(1L, 32L), row.vars = structure(list(), .Names = character(0)), col.vars = structure(list(Class = c('1st', '2nd', '3rd', 'Crew'), Sex = c('Male', 'Female'), Age = c('Child', 'Adult'), Survived = c('No', 'Yes')), .Names = c('Class', 'Sex', 'Age', 'Survived'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c(0, 5, 118, 57, 0, 1, 4, 140, 0, 11, 154, 14, 0, 13, 13, 80, 35, 13, 387, 75, 17, 14, 89, 76, 0, 0, 670, 192, 0, 0, 3, 20), .Dim = c(1L, 32L), row.vars = structure(list(), .Names = character(0)), col.vars = structure(list(Class = c('1st', '2nd', '3rd', 'Crew'), Sex = c('Male', 'Female'), Age = c('Child', 'Adult'), Survived = c('No', 'Yes')), .Names = c('Class', 'Sex', 'Age', 'Survived'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat30() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c('', '', '\\\'Adult\\\'', '\\\'No\\\'', '', '387'), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c('', '', '\\\'Adult\\\'', '\\\'No\\\'', '', '387'), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -172,8 +160,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat32() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(-0.318309886183791+0i, 0-0.564189583547756i, 1+0i, 0+1.77245385090552i, -3.14159265358979+0i), TRUE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c(-0.318309886183791+0i, 0-0.564189583547756i, 1+0i, 0+1.77245385090552i, -3.14159265358979+0i), TRUE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -198,8 +185,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat37() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(213198964, 652424.52183908), .Names = c('null.deviance', 'deviance')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c(213198964, 652424.52183908), .Names = c('null.deviance', 'deviance')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -224,14 +210,12 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat42() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(2.5, 97.5), TRUE, 3, 0L, NULL, 3L, TRUE, FALSE, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(c(2.5, 97.5), TRUE, 3, 0L, NULL, 3L, TRUE, FALSE, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
     public void testformat43() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(9.4, 10.2, 9.2, 4.4, 3.5, 2.7), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('Estimate', 'Std.Err'))), FALSE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(structure(c(9.4, 10.2, 9.2, 4.4, 3.5, 2.7), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('Estimate', 'Std.Err'))), FALSE, 2, 0L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -246,8 +230,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat47() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(-0.01234+3.14159265358979i, FALSE, NULL, 14L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(-0.01234+3.14159265358979i, FALSE, NULL, 14L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -257,8 +240,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat49() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(3.141, FALSE, NULL, 13L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
+        assertEval("argv <- list(3.141, FALSE, NULL, 13L, NULL, 3L, TRUE, NA, \".\"); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))");
     }
 
     @Test
@@ -293,7 +275,7 @@ public class TestBuiltin_format extends TestBase {
 
     @Test
     public void testformat56() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(x = 0.04, digits = 3, nsmall = 3), .Names = c('x',     'digits', 'nsmall'));do.call('format', argv)");
+        assertEval("argv <- structure(list(x = 0.04, digits = 3, nsmall = 3), .Names = c('x',     'digits', 'nsmall'));do.call('format', argv)");
     }
 
     /**
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java
index 31f24a6776..b1f0342232 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -47,7 +47,7 @@ public class TestBuiltin_formatC extends TestBase {
 
     @Test
     public void testformatC6() {
-        assertEval(Ignored.Unknown, "argv <- list(3L, 'integer', 3, 2L, 'd', '0', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(3L, 'integer', 3, 2L, 'd', '0', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
@@ -57,8 +57,7 @@ public class TestBuiltin_formatC extends TestBase {
 
     @Test
     public void testformatC8() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(48.4333681840033, .Names = 'value'), 'double', 5L, 4L, 'g', '', 12L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(structure(48.4333681840033, .Names = 'value'), 'double', 5L, 4L, 'g', '', 12L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
@@ -79,13 +78,12 @@ public class TestBuiltin_formatC extends TestBase {
 
     @Test
     public void testformatC12() {
-        assertEval(Ignored.Unknown, "argv <- list(5L, 'integer', 2, 2L, 'd', '', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(5L, 'integer', 2, 2L, 'd', '', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
     public void testformatC13() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(c(3.14159265358979e-05, 0.000314159265358979, 0.00314159265358979, 0.0314159265358979, 0.314159265358979, 3.14159265358979, 31.4159265358979, 314.159265358979, 3141.59265358979, 31415.9265358979), 'double', 5, 4, 'fg', '', c(15, 14, 13, 12, 11, 10, 9, 9, 9, 9)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(c(3.14159265358979e-05, 0.000314159265358979, 0.00314159265358979, 0.0314159265358979, 0.314159265358979, 3.14159265358979, 31.4159265358979, 314.159265358979, 3141.59265358979, 31415.9265358979), 'double', 5, 4, 'fg', '', c(15, 14, 13, 12, 11, 10, 9, 9, 9, 9)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java
index 305bd3eb08..85b21c4780 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatpval.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -14,12 +14,10 @@ import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
 
-// Checkstyle: stop line length check
-
 public class TestBuiltin_formatpval extends TestBase {
 
     @Test
     public void testformatpval1() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv',     'digits'));do.call('format.pval', argv)");
+        assertEval("argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv',     'digits'));do.call('format.pval', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
index a1601e7249..f8d55fed54 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java
index 026eee8044..1761b0e116 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lm.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -36,22 +36,22 @@ public class TestBuiltin_lm extends TestBase {
 
     @Test
     public void testlm334() {
-        assertEval(Ignored.Unknown, "require(stats);" + "lm(data = LifeCycleSavings, formula = sr ~ pop15 + pop75 + dpi + ddpi)");
+        assertEval("require(stats);" + "lm(data = LifeCycleSavings, formula = sr ~ pop15 + pop75 + dpi + ddpi)");
     }
 
     @Test
     public void testlm445() {
-        assertEval(Ignored.Unknown, "require(stats);" + "lm(data = attitude, formula = rating ~ .)");
+        assertEval("require(stats);" + "lm(data = attitude, formula = rating ~ .)");
     }
 
     @Test
     public void testlm875() {
-        assertEval(Ignored.Unknown, "require(stats); lm(data = mtcars, formula = 100/mpg ~ disp + hp + wt + am)");
+        assertEval("require(stats); lm(data = mtcars, formula = 100/mpg ~ disp + hp + wt + am)");
     }
 
     @Test
     public void testlm876() {
-        assertEval(Ignored.Unknown, "require(stats); lm(data = npk, formula = yield ~ block + N * P * K, singular.ok = TRUE)");
+        assertEval("require(stats); lm(data = npk, formula = yield ~ block + N * P * K, singular.ok = TRUE)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
index 52807ae955..7765b87195 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
@@ -1048,8 +1048,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators207() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(list(coefficients = structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317), .Names = c('(Intercept)', 'x1', 'x2', 'x3')), residuals = structure(c(0.224762433374997, 0.4813346401898, -0.548705796690786, -0.873306430909872, 0.3255545927283, -0.288240908441576, 0.530823516045489, -0.0649703574297026, 1.2699009772491, -1.05715266611575), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), effects = structure(c(-18.0083860263211, 7.91372047070235, 0.594462796282497, -0.733976126666906, 0.546582698364345, -0.032332374655677, 0.774795104738016, 0.120246912926227, 1.34954655602521, -1.1298961521627), .Names = c('(Intercept)', 'x1', 'x3', '', '', '', '', '', '', '')), rank = 3L, fitted.values = structure(c(2.08447598454963, 2.74878255284838, 3.46483046621199, 4.23261972464046, 5.0521503281338, 5.923422276692, 6.84643557031507, 7.821190209003, 8.84768619275579, 9.92592352157344), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), assign = 0:3, qr = structure(list(    qr = structure(c(-3.16227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, -17.3925271309261, 9.08295106229247, 0.15621147358221, 0.0461150970695743, -0.0639812794430617, -0.174077655955698, -0.284174032468334, -0.39427040898097, -0.504366785493606, -0.614463162006242, -12.1747689916483, 9.99124616852172, 2.29782505861521, 0.388354773181155, 0.471167347118467, 0.46694109307793,     0.375676011059543, 0.197372101063308, -0.0679706369107753, -0.420352202862709, -17.3925271309261, 9.08295106229247, 1.30962518065979e-16, -1.00907321685019e-15, 0.0501848681992808, -0.170313338748631, 0.0400139169574381, -0.419073670426332, -0.887431917453648, -0.0447724572319277), .Dim = c(10L, 4L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), c('(Intercept)', 'x1', 'x3', 'x2')), assign = 0:3), qraux = c(1.31622776601684, 1.26630785009485, 1.21850337126599, 1.04136435435488    ), pivot = c(1L, 2L, 4L, 3L), tol = 1e-07, rank = 3L), .Names = c('qr', 'qraux', 'pivot', 'tol', 'rank'), class = 'qr'), df.residual = 7L, xlevels = structure(list(), .Names = character(0)), call = quote(lm(formula = y ~ x1 + x2 + x3)), terms = quote(y ~ x1 + x2 + x3), model = structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10,     x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), terms = quote(y ~ x1 + x2 + x3), row.names = c(NA, 10L), class = 'data.frame')), .Names = c('coefficients', 'residuals', 'effects', 'rank', 'fitted.values', 'assign', 'qr', 'df.residual', 'xlevels', 'call', 'terms', 'model'), class = 'lm'));`(`(argv[[1]]);");
+        assertEval("argv <- list(structure(list(coefficients = structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317), .Names = c('(Intercept)', 'x1', 'x2', 'x3')), residuals = structure(c(0.224762433374997, 0.4813346401898, -0.548705796690786, -0.873306430909872, 0.3255545927283, -0.288240908441576, 0.530823516045489, -0.0649703574297026, 1.2699009772491, -1.05715266611575), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), effects = structure(c(-18.0083860263211, 7.91372047070235, 0.594462796282497, -0.733976126666906, 0.546582698364345, -0.032332374655677, 0.774795104738016, 0.120246912926227, 1.34954655602521, -1.1298961521627), .Names = c('(Intercept)', 'x1', 'x3', '', '', '', '', '', '', '')), rank = 3L, fitted.values = structure(c(2.08447598454963, 2.74878255284838, 3.46483046621199, 4.23261972464046, 5.0521503281338, 5.923422276692, 6.84643557031507, 7.821190209003, 8.84768619275579, 9.92592352157344), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), assign = 0:3, qr = structure(list(    qr = structure(c(-3.16227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, -17.3925271309261, 9.08295106229247, 0.15621147358221, 0.0461150970695743, -0.0639812794430617, -0.174077655955698, -0.284174032468334, -0.39427040898097, -0.504366785493606, -0.614463162006242, -12.1747689916483, 9.99124616852172, 2.29782505861521, 0.388354773181155, 0.471167347118467, 0.46694109307793,     0.375676011059543, 0.197372101063308, -0.0679706369107753, -0.420352202862709, -17.3925271309261, 9.08295106229247, 1.30962518065979e-16, -1.00907321685019e-15, 0.0501848681992808, -0.170313338748631, 0.0400139169574381, -0.419073670426332, -0.887431917453648, -0.0447724572319277), .Dim = c(10L, 4L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), c('(Intercept)', 'x1', 'x3', 'x2')), assign = 0:3), qraux = c(1.31622776601684, 1.26630785009485, 1.21850337126599, 1.04136435435488    ), pivot = c(1L, 2L, 4L, 3L), tol = 1e-07, rank = 3L), .Names = c('qr', 'qraux', 'pivot', 'tol', 'rank'), class = 'qr'), df.residual = 7L, xlevels = structure(list(), .Names = character(0)), call = quote(lm(formula = y ~ x1 + x2 + x3)), terms = quote(y ~ x1 + x2 + x3), model = structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10,     x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), terms = quote(y ~ x1 + x2 + x3), row.names = c(NA, 10L), class = 'data.frame')), .Names = c('coefficients', 'residuals', 'effects', 'rank', 'fitted.values', 'assign', 'qr', 'df.residual', 'xlevels', 'call', 'terms', 'model'), class = 'lm'));`(`(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java
index afd022da35..4cbcb19b59 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_print.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -43,9 +43,8 @@ public class TestBuiltin_print extends TestBase {
 
     @Test
     public void testprint5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- structure(list(x = structure(list(statistic = structure(0.87901108669074,     .Names = 't'), parameter = structure(19, .Names = 'df'),     p.value = 0.390376937081292, conf.int = structure(c(-0.332667989442433,         0.814407243771461), conf.level = 0.95), estimate = structure(0.240869627164514,         .Names = 'mean of x'), null.value = structure(0, .Names = 'mean'),     alternative = 'two.sided', method = 'One Sample t-test',     data.name = 'x'), .Names = c('statistic', 'parameter', 'p.value',     'conf.int', 'estimate', 'null.value', 'alternative', 'method',     'data.name'), class = 'htest')), .Names = 'x');" +
-                                        "do.call('print', argv)");
+        assertEval("argv <- structure(list(x = structure(list(statistic = structure(0.87901108669074,     .Names = 't'), parameter = structure(19, .Names = 'df'),     p.value = 0.390376937081292, conf.int = structure(c(-0.332667989442433,         0.814407243771461), conf.level = 0.95), estimate = structure(0.240869627164514,         .Names = 'mean of x'), null.value = structure(0, .Names = 'mean'),     alternative = 'two.sided', method = 'One Sample t-test',     data.name = 'x'), .Names = c('statistic', 'parameter', 'p.value',     'conf.int', 'estimate', 'null.value', 'alternative', 'method',     'data.name'), class = 'htest')), .Names = 'x');" +
+                        "do.call('print', argv)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java
index 2d90060ea7..c505c30846 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -33,8 +33,7 @@ public class TestBuiltin_summary extends TestBase {
 
     @Test
     public void testsummary3() {
-        assertEval(Ignored.Unknown,
-                        "argv <- structure(list(object = structure(list(Sepal.Length = c(5.1,     4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3,     5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5,     5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4,     5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5, 7, 6.4,     6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6,     6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8,     6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5,     5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8,     7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7,     5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2,     6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4,     6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9),     Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9,         3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4,         3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4,         4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 3.2,         3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3,         2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1,         3, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3,         2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5,         2.6, 3, 2.6, 2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7,         3, 2.9, 3, 3, 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8,         3.2, 3, 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2,         2.8, 3, 2.8, 3, 2.8, 3.8, 2.8, 2.8, 2.6, 3, 3.4, 3.1,         3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 3, 2.5, 3, 3.4, 3),     Petal.Length = c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5,         1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7,         1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6,         1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3,         1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5,         4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7,         3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3,         4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5,         4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3,         3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1,         5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9,         6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6,         5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9,         5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 0.2,         0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1,         0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5,         0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2,         0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3,         0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6,         1, 1.3, 1.4, 1, 1.5, 1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1,         1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1, 1.1,         1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4,         1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1,         1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 2.1, 2, 2.4,         2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 1.8, 1.8,         1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8,         1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3,         1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L), .Label = c('setosa', 'versicolor', 'virginica'),         class = 'factor')), .Names = c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width', 'Species'), row.names = c(NA,     -150L), class = 'data.frame')), .Names = 'object');" +
-                                        "do.call('summary', argv)");
+        assertEval("argv <- structure(list(object = structure(list(Sepal.Length = c(5.1,     4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3,     5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5,     5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4,     5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5, 7, 6.4,     6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6,     6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8,     6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5,     5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8,     7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7,     5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2,     6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4,     6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9),     Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9,         3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4,         3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4,         4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 3.2,         3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3,         2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1,         3, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3,         2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5,         2.6, 3, 2.6, 2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7,         3, 2.9, 3, 3, 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8,         3.2, 3, 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2,         2.8, 3, 2.8, 3, 2.8, 3.8, 2.8, 2.8, 2.6, 3, 3.4, 3.1,         3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 3, 2.5, 3, 3.4, 3),     Petal.Length = c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5,         1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7,         1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6,         1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3,         1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5,         4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7,         3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3,         4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5,         4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3,         3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1,         5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9,         6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6,         5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9,         5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 0.2,         0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1,         0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5,         0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2,         0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3,         0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6,         1, 1.3, 1.4, 1, 1.5, 1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1,         1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1, 1.1,         1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4,         1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1,         1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 2.1, 2, 2.4,         2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 1.8, 1.8,         1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8,         1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3,         1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L), .Label = c('setosa', 'versicolor', 'virginica'),         class = 'factor')), .Names = c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width', 'Species'), row.names = c(NA,     -150L), class = 'data.frame')), .Names = 'object');" +
+                        "do.call('summary', argv)");
     }
 }
-- 
GitLab


From 189d4573c6efe6bf252eccaa6639a6f11f3f880f Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 19:02:11 +0200
Subject: [PATCH 207/402] =?UTF-8?q?throw=20proper=20errors=20when=20eval?=
 =?UTF-8?q?=E2=80=99ing=20symbols?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../src/com/oracle/truffle/r/engine/REngine.java            | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index ab19a0a278..5245ffc126 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -372,8 +372,12 @@ final class REngine implements Engine, Engine.Timings {
         for (int i = 0; i < exprs.getLength(); i++) {
             Object obj = exprs.getDataAt(i);
             if (obj instanceof RSymbol) {
-                result = ReadVariableNode.lookupAny(((RSymbol) obj).getName(), envir.getFrame(), false);
+                String identifier = ((RSymbol) obj).getName();
+                result = ReadVariableNode.lookupAny(identifier, envir.getFrame(), false);
                 caller.setVisibility(true);
+                if (result == null) {
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MISSING, identifier);
+                }
             } else if (obj instanceof RLanguage) {
                 result = evalNode(((RLanguage) obj).getRep().asRSyntaxNode(), envir, caller);
             } else {
-- 
GitLab


From f44a075ee3d2a6b2d0638cb3dc9af88c843a9407 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Mar 2017 19:02:48 +0200
Subject: [PATCH 208/402] =?UTF-8?q?raise=20=E2=80=9Cempty=20symbol?=
 =?UTF-8?q?=E2=80=9D=20errors=20during=20parsing?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../truffle/r/nodes/function/RCallNode.java   |  10 --
 .../truffle/r/nodes/unary/CastSymbolNode.java |   6 +-
 .../truffle/r/parser/ParserGeneration.java    |   3 +-
 .../src/com/oracle/truffle/r/parser/R.g       |  25 ++-
 .../truffle/r/test/ExpectedTestOutput.test    | 163 +++++++++++++-----
 .../truffle/r/test/parser/TestParser.java     |  24 +++
 6 files changed, 173 insertions(+), 58 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index d9a6c913e2..a921d98f18 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -170,16 +170,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         this.explicitArgs = null;
         this.varArgIndexes = getVarArgIndexes(arguments);
         this.lookupVarArgs = varArgIndexes.length == 0 ? null : ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any);
-
-        for (String name : signature) {
-            if (name != null && name.isEmpty()) {
-                /*
-                 * In GnuR this is evidently output by the parser, so very early, and never with a
-                 * caller in the message.
-                 */
-                throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
-            }
-        }
         this.signature = signature;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java
index 4aac866720..2b45b6639a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastSymbolNode.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RError;
@@ -88,7 +89,10 @@ public abstract class CastSymbolNode extends CastBaseNode {
     @Specialization
     @TruffleBoundary
     protected RSymbol doString(String value) {
-        // TODO: see if this is going to hit us performance-wise
+        if (value.isEmpty()) {
+            CompilerDirectives.transferToInterpreter();
+            throw error(RError.Message.ZERO_LENGTH_VARIABLE);
+        }
         return RDataFactory.createSymbolInterned(value);
     }
 
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
index 4b3743e659..76e8351cb9 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
@@ -88,6 +88,7 @@ public class ParserGeneration {
         "support ? for help",
         "support for hex float literals",
         "support for hex float literals without decimal point: 0x0p0",
-        "different warning for hex and dec integer literals"
+        "different warning for hex and dec integer literals",
+        "raise ZERO_LENGTH_VARIABLE errors in parser"
     };
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
index e30c5f77e9..c1e9f36e56 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
@@ -48,6 +48,8 @@ import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
 @lexer::header {
 //@formatter:off
 package com.oracle.truffle.r.parser;
+
+import com.oracle.truffle.r.runtime.RError;
 }
 
 @rulecatch {
@@ -81,9 +83,19 @@ package com.oracle.truffle.r.parser;
      * Helper function to create a function lookup for the symbol in a given token.
      */
     private T operator(Token op) {
-        return builder.lookup(src(op), op.getText(), true);
+        return builder.lookup(src(op), argName(op.getText()), true);
     }
     
+    /**
+     * Helper to check for empty lookups.
+     */
+     private String argName(String name) {
+         if (name.length() == 0) {
+             throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
+         } 
+         return name;
+     }
+    
     /**
      * Create a {@link SourceSection} from a single token.
      */
@@ -487,8 +499,8 @@ args [T firstArg] returns [List<Argument<T>> v]
 arg_expr [List<Argument<T>> l]
     @init { Token start = input.LT(1); }
     : e=expr                                                   { $l.add(RCodeBuilder.argument(src(start, last()), (String) null, $e.v)); }
-    | name=(ID | VARIADIC | NULL | STRING) n_ ASSIGN n_ e=expr { $l.add(RCodeBuilder.argument(src($name, last()), $name.text, $e.v)); }
-    | name=(ID | VARIADIC | NULL | STRING) n_ a=ASSIGN         { $l.add(RCodeBuilder.argument(src($name, $a), $name.text, null)); }
+    | name=(ID | VARIADIC | NULL | STRING) n_ ASSIGN n_ e=expr { $l.add(RCodeBuilder.argument(src($name, last()), argName($name.text), $e.v)); }
+    | name=(ID | VARIADIC | NULL | STRING) n_ a=ASSIGN         { $l.add(RCodeBuilder.argument(src($name, $a), argName($name.text), null)); }
     ;
 
 ///
@@ -606,7 +618,12 @@ fragment BACKTICK_NAME
         | i = ~( '\\' | '`' ) { buf.appendCodePoint(i); }
         )*
         '`'
-        { setText(buf.toString()); }
+        {
+          if (buf.length() == 0) {
+            throw RError.error(RError.NO_CALLER, RError.Message.ZERO_LENGTH_VARIABLE);
+          }
+          setText(buf.toString());
+        }
       )
     ;
 
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 8721518a96..d2b8d348af 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
@@ -386,7 +386,7 @@ Slot "j":
 #{ setClass("foo"); setClass("bar", representation(j = "numeric"), contains = "foo"); is.null(getClass("foo")@prototype) }
 [1] FALSE
 
-##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#
 #{ setClass("foo", representation(j="numeric")); getClass("foo") }
 Class "foo" [in ".GlobalEnv"]
 
@@ -1287,7 +1287,7 @@ $vt
 [1,]    0
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_La.testLa9#
 #argv <- list(structure(c(-9.64365076099295, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, 0.103695169473043, -29634.0055320061, -5658.08855789941, 0.0595010632288954, 0.0648032071760975, 0.106336668095848, -0.0279843118999398, 0.0762911857283688, 0.188519899277481, 0.0807096390177039, 0.102801905464379, 0.158474416910002, -0.0969121832135675, -0.0447744343994132, 0.0356414154664858, 0.0276881995456826, -5.08106330417909, 3.14280306547868, 3.64768208463163, 0.0962151262827947, -0.216651778533863, -0.0914289830351174, 0.0855052819309283, -0.0191216590449975, 0.0813861110263642, 0.0607902565035442, 0.00888870310603775, -0.027169916923919, -0.0757761335977742, 0.123401654252917, -0.143330536432624, -0.207390338946085, -0.18719988871654, -0.127596387499216, 1.38045811630541, 0.0118370110620473, 0.00504893180870276, 0.0281684584122627, 0.0338400772620966, 0.0283917504929648, 0.0295082108964754, 0.0323216911133222, 0.00156557534974961, 0.00420042190203468, 0.0261141712698031, 0.00786241202554953, -3.21455025366432, -2.66432733346907, -2.18217405946767, -1.0459324747522, 2.77707906967759, -0.000588115022584812, -0.0784367740030637, -0.0437014732535189, -0.0770692424774911, 0.28985899050302, 0.307089887725235, -0.0219216068215179, -0.00578473481976082, -0.0910180640383319, 0.0166427821996303, -0.725866186311298, -0.943724610301472, -0.197997366006898, -0.255325765345392, -1.99736582726463, 1.22009740929232, -0.000660179745382102, 0.118090770461339, 0.00401505451472504, -0.265276591063721, -0.206368639386371, -0.0413572976755921, 0.0138104665936721, -0.0436723349383677, 0.0904843084594291, -0.103695169473043, 0.0314422837299137, -0.171533212490836, -0.0271695331685966, -0.234884785308008, -0.455412006973628, -0.833981960018826, -0.0497205266764892, -0.00169048456815939, 0.0359873442560765, 0.0111849454624309, 0.0174129325629219, -0.00581471075176227, 0.0183876477886015, -0.0380971980704758, -1.14064686420347, -1.21031412747477, -0.546078284372325, -0.385964209884133, -0.535335872363138, 0.617909299639904, 0.034437791264286, -2.66782912116871, -0.0707120154460491, 0.170259689757997, -0.200116024334743, -0.0120487035676503, -0.00787104751465206, -0.0743232096613527, -0.00206481367828156, -2.28129372840694, -1.27183039972242, -0.162921372163874, 0.194143545128708, 0.405329624202872, -0.0239884453210967, 0.161826508366356, 1.47283157923894, -3.57122150532158, 0.0184573285734211, 0.0768346205272587, -0.00300367200170235, -0.047539037475449, -0.0955077077363865, 0.170580587807138, -2.17759855893389, 2.82091161681306, -0.529126651121425, 0.00648102843720064, -0.227590137804697, 0.429332016819553, 0.315382802791974, -0.0921680424483324, 0.358484158960907, 2.74734594573339, -0.00180797874108619, 0.211048746835586, 0.146553774483952, 0.0892496085418831, 0.02104367339158, -1.4517323726226, 0.428703993666521, -0.198393471445493, -0.178300389025286, -0.0518091667043893, 0.133208332446864, -1.01393441911662, 0.520772381447608, 0.936102434059857, -1.6420319436063, 2.59716822825227, 0.194828402482676, 0.15057424104202, -0.232155536267878, -0.0298159890277092, -0.933256525257383, -1.20515451427884, 0.0125087156504907, 0.421920000319943, 0.452875082015975, -0.655679104390575, 0.284781968418535, 0.643096539054797, 1.38165893036928, 0.447700892848835, -0.482856979100538, 1.73960015308741, 0.115853953901054, 0.107343556163412, -0.0385322695831968, -25.7267715462619, -8.40853040573162, -1.45105839286435, -1.58984152452525, -1.59606771970776, 2.79428919380473, 0.596892611732863, -1.03839368638655, -0.0376487500979583, -0.507302835476536, 0.184174590388395, -0.70905481454677, -3.32884312972433, 0.134236291836065, -0.0993249017707237, -6.94757635469386, 1.58613921242054, 0.195741168102286, 0.638223445194413, 1.07571321411184, 0.659104584950073, 0.199707908602043, -0.565980943574209, -0.967985377031296, -0.112927393875596, -0.934672543429794, 0.198159847509218, 0.275086401661377, 3.44668029704689, -0.05066048099299, -1.65912271156868, -1.17593571026872, -0.20132598039105, -0.42732880950559, -1.20727437557593, 0.102943259109259, -0.697974199306205, 0.103630431164098, -0.0620963660266192, -0.16978912837867, 0.739571733406047, -0.872308493604205, -0.757980967070979, -2.00985526447536, -1.92891236077264), .Dim = c(15L, 15L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'), c('(Intercept)', 'Weight', 'Cylinders4', 'Cylinders5', 'Cylinders6', 'Cylinders8', 'Cylindersrotary', 'TypeLarge', 'TypeMidsize', 'TypeSmall', 'TypeSporty', 'TypeVan', 'EngineSize', 'DriveTrainFront', 'DriveTrainRear'))), 15L); .Internal(La_chol2inv(argv[[1]], argv[[2]]))
                [,1]          [,2]          [,3]          [,4]          [,5]
  [1,]  2.4965590071 -8.201566e-04  0.0523016012  0.4022192142  0.3409468314
@@ -19342,7 +19342,7 @@ attr(,"hessian")
 [1,] 1
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
 #df <- deriv(~ gamma(x), c("x"), hessian=FALSE); x<-0; eval(df)
 [1] NaN
 attr(,"gradient")
@@ -19366,7 +19366,7 @@ attr(,"gradient")
        x
 [1,] Inf
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#Ignored.MissingWarning#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deriv.testDeriveFunctions1#
 #df <- deriv(~ log(x), c("x"), hessian=TRUE); x<--1; eval(df)
 [1] NaN
 attr(,"gradient")
@@ -23969,11 +23969,11 @@ logical(0)
 #argv <- list(character(0)); .Internal(file.exists(argv[[1]]))
 logical(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo1#
 #argv <- list('/home/lzhao/hg/r-instrumented/library/codetools/data'); .Internal(file.info(argv[[1]]))
 Error: 1 argument passed to .Internal(file.info) which requires 2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_fileinfo.testfileinfo2#
 #argv <- list(character(0)); .Internal(file.info(argv[[1]]))
 Error: 1 argument passed to .Internal(file.info) which requires 2
 
@@ -24168,7 +24168,7 @@ NULL
 #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame')); .Internal(formals(argv[[1]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat1#Output.IgnoreErrorMessage#
 #argv <- list(structure(c(0, 72.7, 56.4, 72.7, 0, 63.3, 56.4, 63.3, 0), .Dim = c(3L, 3L), .Dimnames = list(c('Girth', 'Height', 'Volume'), c('Girth', 'Height', 'Volume'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]], , argv[[9]]))
 Error in .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]],  :
   argument 10 is empty
@@ -24183,7 +24183,7 @@ Error in .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]],  :
    1    2 <NA>
  "1"  "2"  "1"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat12#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat12#
 #argv <- list(c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "Min.   " "1st Qu." "Median " "Mean   " "3rd Qu." "Max.   "
 
@@ -24191,12 +24191,12 @@ Error in .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]],  :
 #argv <- list(c(1L, 2L, 3L, 4L, 5L, -1L, -2L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] " 1" " 2" " 3" " 4" " 5" "-1" "-2"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat14#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat14#
 #argv <- list(structure(c(NA, 1, 1, 1), .Names = c('<none>', '- x4', '- x2', '- x1')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 <none>   - x4   - x2   - x1
   "NA"   " 1"   " 1"   " 1"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat15#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat15#
 #argv <- list(2.22044604925031e-16, FALSE, 1, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "2e-16"
 
@@ -24225,11 +24225,11 @@ Error in argv[[9]] : subscript out of bounds
 #argv <- list(c('abc', NA, 'def'), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "abc" NA    "def"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat23#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat23#
 #argv <- list(c(NA, 2L, 4L, 7L), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "NA" " 2" " 4" " 7"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat24#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat24#
 #argv <- list(c(1.1+0i, NA, 3+0i), FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "1.1+0i" "    NA" "3.0+0i"
 
@@ -24241,7 +24241,7 @@ Error in argv[[9]] : subscript out of bounds
 #argv <- list(c(172, 88, 88, 55, 92, 92, 72, 72, 63, 63), TRUE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
  [1] "172" "88"  "88"  "55"  "92"  "92"  "72"  "72"  "63"  "63"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat27#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat27#
 #argv <- list(structure(c(142L, 104L, 71L, 250L), .Dim = 4L, .Dimnames = structure(list(c('(1) Approve STRONGLY', '(2) Approve SOMEWHAT', '(3) Disapprove SOMEWHAT', '(4) Disapprove STRONGLY')), .Names = '')), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 
    (1) Approve STRONGLY    (2) Approve SOMEWHAT (3) Disapprove SOMEWHAT
@@ -24249,11 +24249,11 @@ Error in argv[[9]] : subscript out of bounds
 (4) Disapprove STRONGLY
                   "250"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat28#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat28#
 #argv <- list(structure(c('***', '*', ' ', ' ', ' '), legend = '0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1', class = 'noquote'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "***" "*  " "   " "   " "   "
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat29#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat29#
 #argv <- list(structure(c(0, 5, 118, 57, 0, 1, 4, 140, 0, 11, 154, 14, 0, 13, 13, 80, 35, 13, 387, 75, 17, 14, 89, 76, 0, 0, 670, 192, 0, 0, 3, 20), .Dim = c(1L, 32L), row.vars = structure(list(), .Names = character(0)), col.vars = structure(list(Class = c('1st', '2nd', '3rd', 'Crew'), Sex = c('Male', 'Female'), Age = c('Child', 'Adult'), Survived = c('No', 'Yes')), .Names = c('Class', 'Sex', 'Age', 'Survived'))), FALSE, 7L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
      [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]  [,10] [,11] [,12]
 [1,] "  0" "  5" "118" " 57" "  0" "  1" "  4" "140" "  0" " 11" "154" " 14"
@@ -24262,11 +24262,11 @@ Error in argv[[9]] : subscript out of bounds
      [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32]
 [1,] "  0" "  0" "670" "192" "  0" "  0" "  3" " 20"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat3#
 #argv <- list(c('Inf', '-Inf', 'NaN', 'NA'), FALSE, NULL, 0L, 4, 1L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] " Inf" "-Inf" " NaN" "  NA"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat30#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat30#
 #argv <- list(c('', '', '\'Adult\'', '\'No\'', '', '387'), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "       " "       " "'Adult'" "   'No'" "       " "    387"
 
@@ -24274,7 +24274,7 @@ Error in argv[[9]] : subscript out of bounds
 #argv <- list(2.2250738585072e-308, TRUE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "2.225074e-308"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat32#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat32#
 #argv <- list(c(-0.318309886183791+0i, 0-0.564189583547756i, 1+0i, 0+1.77245385090552i, -3.14159265358979+0i), TRUE, 2, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "-0.32+0.00i" "0.00-0.56i"  "1.00+0.00i"  "0.00+1.77i"  "-3.14+0.00i"
 
@@ -24312,7 +24312,7 @@ Error in argv[[9]] : subscript out of bounds
 #argv <- list(structure(integer(0), .Label = character(0), class = 'factor'), TRUE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat37#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat37#
 #argv <- list(structure(c(213198964, 652424.52183908), .Names = c('null.deviance', 'deviance')), FALSE, 5L, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 null.deviance      deviance
   "213198964"   "   652425"
@@ -24326,7 +24326,7 @@ null.deviance      deviance
 #argv <- list(FALSE, FALSE, NULL, 0L, NULL, 3L, FALSE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "FALSE"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat4#
 #argv <- list(structure(c('axx', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), .Dim = c(2L, 4L)), FALSE, NULL, 0L, NULL, 1L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
      [,1]  [,2]  [,3]  [,4]
 [1,] "axx" "  c" "  e" "  g"
@@ -24347,11 +24347,11 @@ null.deviance      deviance
 [61] "3084" "2605" "2573" "2143" "1693" "1504" "1461" "1354" "1333" "1492"
 [71] "1781" "1915"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat42#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat42#
 #argv <- list(c(2.5, 97.5), TRUE, 3, 0L, NULL, 3L, TRUE, FALSE, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "2.5"  "97.5"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat43#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat43#
 #argv <- list(structure(c(9.4, 10.2, 9.2, 4.4, 3.5, 2.7), .Dim = c(3L, 2L), .Dimnames = list(NULL, c('Estimate', 'Std.Err'))), FALSE, 2, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
      Estimate Std.Err
 [1,] " 9.4"   " 4.4"
@@ -24366,7 +24366,7 @@ null.deviance      deviance
 #argv <- list(1.2e+07, FALSE, NULL, 9L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "1.2e+07"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat47#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat47#
 #argv <- list(-0.01234+3.14159265358979i, FALSE, NULL, 14L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "-0.01234000000000+3.14159265358979i"
 
@@ -24374,7 +24374,7 @@ null.deviance      deviance
 #argv <- list(c(TRUE, FALSE, TRUE, FALSE, FALSE, FALSE), FALSE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] " TRUE" "FALSE" " TRUE" "FALSE" "FALSE" "FALSE"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat49#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat49#
 #argv <- list(3.141, FALSE, NULL, 13L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "3.1410000000000"
 
@@ -24407,7 +24407,7 @@ null.deviance      deviance
 #argv <- list(1e-11, FALSE, NULL, 0L, NULL, 3L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "1e-11"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat56#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat56#
 #argv <- structure(list(x = 0.04, digits = 3, nsmall = 3), .Names = c('x',     'digits', 'nsmall'));do.call('format', argv)
 [1] "0.040"
 
@@ -24420,7 +24420,7 @@ null.deviance      deviance
   <none>     - x4     - x2     - x1
 " 47.97" " 57.90" " 74.76" "868.88"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_format.testformat7#
 #argv <- list(c('a', 'NA', NA, 'b'), FALSE, NULL, 0L, NULL, 0L, TRUE, NA, "."); .Internal(format(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]], argv[[9]]))
 [1] "a " "NA" "NA" "b "
 
@@ -24448,11 +24448,11 @@ character(0)
 #argv <- list(c(0, 25, 50, 75, 100), 'double', 1, 6L, 'fg', '', c(14L, 13L, 13L, 13L, 13L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "0"   "25"  "50"  "75"  "100"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC12#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC12#
 #argv <- list(5L, 'integer', 2, 2L, 'd', '', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] " 5"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC13#
 #argv <- list(c(3.14159265358979e-05, 0.000314159265358979, 0.00314159265358979, 0.0314159265358979, 0.314159265358979, 3.14159265358979, 31.4159265358979, 314.159265358979, 3141.59265358979, 31415.9265358979), 'double', 5, 4, 'fg', '', c(15, 14, 13, 12, 11, 10, 9, 9, 9, 9)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
  [1] "0.00003142" "0.0003142"  "0.003142"   "0.03142"    "0.3142"
  [6] "3.142"      "31.42"      "314.2"      " 3142"      "31416"
@@ -24480,7 +24480,7 @@ character(0)
 #argv <- list(c(-3, -2, -1, 0, 1, 2, 3), 'double', 1L, 4L, 'g', '', c(12L, 12L, 12L, 12L, 12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "-3" "-2" "-1" "0"  "1"  "2"  "3"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC6#
 #argv <- list(3L, 'integer', 3, 2L, 'd', '0', 10L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "003"
 
@@ -24488,7 +24488,7 @@ character(0)
 #argv <- list(c(0, 25, 50, 75, 100), 'double', 1, 7L, 'fg', '', c(16L, 15L, 15L, 15L, 15L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "0"   "25"  "50"  "75"  "100"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC8#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC8#
 #argv <- list(structure(48.4333681840033, .Names = 'value'), 'double', 5L, 4L, 'g', '', 12L); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "48.43"
 
@@ -24605,7 +24605,7 @@ character(0)
 #argv <- list(712L, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatpval.testformatpval1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatpval.testformatpval1#
 #argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv',     'digits'));do.call('format.pval', argv)
 [1] "0.201"
 
@@ -24613,14 +24613,14 @@ character(0)
 #argv <- list(1);g(argv[[1]]);
 Error: could not find function "g"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma1#
 #argv <- list(c(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1));gamma(argv[[1]]);
  [1]      NaN 9.513508 4.590844 2.991569 2.218160 1.772454 1.489192 1.298055
  [9] 1.164230 1.068629 1.000000
 Warning message:
 In gamma(argv[[1]]) : NaNs produced
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma2#
 #argv <- list(FALSE);gamma(argv[[1]]);
 [1] NaN
 Warning message:
@@ -24630,11 +24630,11 @@ In gamma(argv[[1]]) : NaNs produced
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));gamma(argv[[1]]);
 <0 x 0 matrix>
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma5#
 #argv <- list(101);gamma(argv[[1]]);
 [1] 9.332622e+157
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma6#
 #argv <- list(c(-3.000001, -3, -3, -2.999999, -2.965, -2.93, -2.895, -2.86, -2.825, -2.79, -2.755, -2.72, -2.685, -2.65, -2.615, -2.58, -2.545, -2.51, -2.475, -2.44, -2.405, -2.37, -2.335, -2.3, -2.265, -2.23, -2.195, -2.16, -2.125, -2.09, -2.055, -2.02, -2.000001, -2, -1.999999, -1.985, -1.95, -1.915, -1.88, -1.845, -1.81, -1.775, -1.74, -1.705, -1.67, -1.635, -1.6, -1.565, -1.53, -1.495, -1.46, -1.425, -1.39, -1.355, -1.32, -1.285, -1.25, -1.215, -1.18, -1.145, -1.11, -1.075, -1.04, -1.005, -1.000001, -1, -0.999999, -0.97, -0.935, -0.9, -0.865, -0.83, -0.795, -0.76, -0.725, -0.69, -0.655, -0.62, -0.585, -0.55, -0.515, -0.48, -0.445, -0.41, -0.375, -0.34, -0.305, -0.27, -0.235, -0.2, -0.165, -0.13, -0.0949999999999998, -0.0599999999999996, -0.0249999999999999, -1e-06, 0, 1e-06, 0.0100000000000002, 0.0450000000000004, 0.0800000000000001, 0.115, 0.15, 0.185, 0.22, 0.255, 0.29, 0.325, 0.36, 0.395, 0.43, 0.465, 0.5, 0.535, 0.57, 0.605, 0.640000000000001, 0.675, 0.71, 0.745000000000001, 0.78, 0.815, 0.850000000000001, 0.885, 0.92, 0.955000000000001, 0.99, 1.025, 1.06, 1.095, 1.13, 1.165, 1.2, 1.235, 1.27, 1.305, 1.34, 1.375, 1.41, 1.445, 1.48, 1.515, 1.55, 1.585, 1.62, 1.655, 1.69, 1.725, 1.76, 1.795, 1.83, 1.865, 1.9, 1.935, 1.97, 2.005, 2.04, 2.075, 2.11, 2.145, 2.18, 2.215, 2.25, 2.285, 2.32, 2.355, 2.39, 2.425, 2.46, 2.495, 2.53, 2.565, 2.6, 2.635, 2.67, 2.705, 2.74, 2.775, 2.81, 2.845, 2.88, 2.915, 2.95, 2.985, 3.02, 3.055, 3.09, 3.125, 3.16, 3.195, 3.23, 3.265, 3.3, 3.335, 3.37, 3.405, 3.44, 3.475, 3.51, 3.545, 3.58, 3.615, 3.65, 3.685, 3.72, 3.755, 3.79, 3.825, 3.86, 3.895, 3.93, 3.965, 4));gamma(argv[[1]]);
   [1]  1.666665e+05           NaN           NaN -1.666669e+05 -4.985099e+00
   [6] -2.619025e+00 -1.841442e+00 -1.462054e+00 -1.242971e+00 -1.105073e+00
@@ -32988,7 +32988,7 @@ Error in eval(expr, envir, enclos) : object 'weight' not found
 #require(stats);lm(formula = weight ~ group, method = 'model.frame')
 Error in eval(expr, envir, enclos) : object 'weight' not found
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm334#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm334#
 #require(stats);lm(data = LifeCycleSavings, formula = sr ~ pop15 + pop75 + dpi + ddpi)
 
 Call:
@@ -32999,7 +32999,7 @@ Coefficients:
  28.5660865   -0.4611931   -1.6914977   -0.0003369    0.4096949
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm445#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm445#
 #require(stats);lm(data = attitude, formula = rating ~ .)
 
 Call:
@@ -33012,7 +33012,7 @@ Coefficients:
    -0.21706
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm875#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm875#
 #require(stats); lm(data = mtcars, formula = 100/mpg ~ disp + hp + wt + am)
 
 Call:
@@ -33023,7 +33023,7 @@ Coefficients:
    0.740648     0.002703     0.005275     1.001303     0.155815
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm876#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lm.testlm876#
 #require(stats); lm(data = npk, formula = yield ~ block + N * P * K, singular.ok = TRUE)
 
 Call:
@@ -40040,7 +40040,7 @@ y ~ a + b:c + d + e + e:d
 #argv <- list(structure(character(0), .Dim = c(0L, 7L), .Dimnames = list(NULL, c('description', 'class', 'mode', 'text', 'isopen', 'can read', 'can write'))));`(`(argv[[1]]);
      description class mode text isopen can read can write
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators207#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators207#
 #argv <- list(structure(list(coefficients = structure(c(1.47191076131574, 0.586694550701453, NA, 0.258706725324317), .Names = c('(Intercept)', 'x1', 'x2', 'x3')), residuals = structure(c(0.224762433374997, 0.4813346401898, -0.548705796690786, -0.873306430909872, 0.3255545927283, -0.288240908441576, 0.530823516045489, -0.0649703574297026, 1.2699009772491, -1.05715266611575), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), effects = structure(c(-18.0083860263211, 7.91372047070235, 0.594462796282497, -0.733976126666906, 0.546582698364345, -0.032332374655677, 0.774795104738016, 0.120246912926227, 1.34954655602521, -1.1298961521627), .Names = c('(Intercept)', 'x1', 'x3', '', '', '', '', '', '', '')), rank = 3L, fitted.values = structure(c(2.08447598454963, 2.74878255284838, 3.46483046621199, 4.23261972464046, 5.0521503281338, 5.923422276692, 6.84643557031507, 7.821190209003, 8.84768619275579, 9.92592352157344), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10')), assign = 0:3, qr = structure(list(    qr = structure(c(-3.16227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, 0.316227766016838, -17.3925271309261, 9.08295106229247, 0.15621147358221, 0.0461150970695743, -0.0639812794430617, -0.174077655955698, -0.284174032468334, -0.39427040898097, -0.504366785493606, -0.614463162006242, -12.1747689916483, 9.99124616852172, 2.29782505861521, 0.388354773181155, 0.471167347118467, 0.46694109307793,     0.375676011059543, 0.197372101063308, -0.0679706369107753, -0.420352202862709, -17.3925271309261, 9.08295106229247, 1.30962518065979e-16, -1.00907321685019e-15, 0.0501848681992808, -0.170313338748631, 0.0400139169574381, -0.419073670426332, -0.887431917453648, -0.0447724572319277), .Dim = c(10L, 4L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), c('(Intercept)', 'x1', 'x3', 'x2')), assign = 0:3), qraux = c(1.31622776601684, 1.26630785009485, 1.21850337126599, 1.04136435435488    ), pivot = c(1L, 2L, 4L, 3L), tol = 1e-07, rank = 3L), .Names = c('qr', 'qraux', 'pivot', 'tol', 'rank'), class = 'qr'), df.residual = 7L, xlevels = structure(list(), .Names = character(0)), call = quote(lm(formula = y ~ x1 + x2 + x3)), terms = quote(y ~ x1 + x2 + x3), model = structure(list(y = c(2.30923841792462, 3.23011719303818, 2.9161246695212, 3.35931329373059, 5.3777049208621, 5.63518136825043, 7.37725908636056, 7.75621985157329, 10.1175871700049, 8.86877085545769), x1 = 1:10, x2 = 1:10,     x3 = c(0.1, 0.4, 0.9, 1.6, 2.5, 3.6, 4.9, 6.4, 8.1, 10)), .Names = c('y', 'x1', 'x2', 'x3'), terms = quote(y ~ x1 + x2 + x3), row.names = c(NA, 10L), class = 'data.frame')), .Names = c('coefficients', 'residuals', 'effects', 'rank', 'fitted.values', 'assign', 'qr', 'df.residual', 'xlevels', 'call', 'terms', 'model'), class = 'lm'));`(`(argv[[1]]);
 
 Call:
@@ -44331,7 +44331,7 @@ $summary
 [13] -0.80942879  1.39969713  0.43065679  0.19581825 -0.06228429  0.57841339
 [19]  2.31951400  2.93765524
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_print.testprint5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_print.testprint5#
 #argv <- structure(list(x = structure(list(statistic = structure(0.87901108669074,     .Names = 't'), parameter = structure(19, .Names = 'df'),     p.value = 0.390376937081292, conf.int = structure(c(-0.332667989442433,         0.814407243771461), conf.level = 0.95), estimate = structure(0.240869627164514,         .Names = 'mean of x'), null.value = structure(0, .Names = 'mean'),     alternative = 'two.sided', method = 'One Sample t-test',     data.name = 'x'), .Names = c('statistic', 'parameter', 'p.value',     'conf.int', 'estimate', 'null.value', 'alternative', 'method',     'data.name'), class = 'htest')), .Names = 'x');do.call('print', argv)
 
 	One Sample t-test
@@ -68095,7 +68095,7 @@ Test for independence of all factors:
    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
   4.600   5.100   5.150   5.236   5.400   5.800
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_summary.testsummary3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_summary.testsummary3#
 #argv <- structure(list(object = structure(list(Sepal.Length = c(5.1,     4.9, 4.7, 4.6, 5, 5.4, 4.6, 5, 4.4, 4.9, 5.4, 4.8, 4.8, 4.3,     5.8, 5.7, 5.4, 5.1, 5.7, 5.1, 5.4, 5.1, 4.6, 5.1, 4.8, 5,     5, 5.2, 5.2, 4.7, 4.8, 5.4, 5.2, 5.5, 4.9, 5, 5.5, 4.9, 4.4,     5.1, 5, 4.5, 4.4, 5, 5.1, 4.8, 5.1, 4.6, 5.3, 5, 7, 6.4,     6.9, 5.5, 6.5, 5.7, 6.3, 4.9, 6.6, 5.2, 5, 5.9, 6, 6.1, 5.6,     6.7, 5.6, 5.8, 6.2, 5.6, 5.9, 6.1, 6.3, 6.1, 6.4, 6.6, 6.8,     6.7, 6, 5.7, 5.5, 5.5, 5.8, 6, 5.4, 6, 6.7, 6.3, 5.6, 5.5,     5.5, 6.1, 5.8, 5, 5.6, 5.7, 5.7, 6.2, 5.1, 5.7, 6.3, 5.8,     7.1, 6.3, 6.5, 7.6, 4.9, 7.3, 6.7, 7.2, 6.5, 6.4, 6.8, 5.7,     5.8, 6.4, 6.5, 7.7, 7.7, 6, 6.9, 5.6, 7.7, 6.3, 6.7, 7.2,     6.2, 6.1, 6.4, 7.2, 7.4, 7.9, 6.4, 6.3, 6.1, 7.7, 6.3, 6.4,     6, 6.9, 6.7, 6.9, 5.8, 6.8, 6.7, 6.7, 6.3, 6.5, 6.2, 5.9),     Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9,         3.1, 3.7, 3.4, 3, 3, 4, 4.4, 3.9, 3.5, 3.8, 3.8, 3.4,         3.7, 3.6, 3.3, 3.4, 3, 3.4, 3.5, 3.4, 3.2, 3.1, 3.4,         4.1, 4.2, 3.1, 3.2, 3.5, 3.6, 3, 3.4, 3.5, 2.3, 3.2,         3.5, 3.8, 3, 3.8, 3.2, 3.7, 3.3, 3.2, 3.2, 3.1, 2.3,         2.8, 2.8, 3.3, 2.4, 2.9, 2.7, 2, 3, 2.2, 2.9, 2.9, 3.1,         3, 2.7, 2.2, 2.5, 3.2, 2.8, 2.5, 2.8, 2.9, 3, 2.8, 3,         2.9, 2.6, 2.4, 2.4, 2.7, 2.7, 3, 3.4, 3.1, 2.3, 3, 2.5,         2.6, 3, 2.6, 2.3, 2.7, 3, 2.9, 2.9, 2.5, 2.8, 3.3, 2.7,         3, 2.9, 3, 3, 2.5, 2.9, 2.5, 3.6, 3.2, 2.7, 3, 2.5, 2.8,         3.2, 3, 3.8, 2.6, 2.2, 3.2, 2.8, 2.8, 2.7, 3.3, 3.2,         2.8, 3, 2.8, 3, 2.8, 3.8, 2.8, 2.8, 2.6, 3, 3.4, 3.1,         3, 3.1, 3.1, 3.1, 2.7, 3.2, 3.3, 3, 2.5, 3, 3.4, 3),     Petal.Length = c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5,         1.4, 1.5, 1.5, 1.6, 1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7,         1.5, 1.7, 1.5, 1, 1.7, 1.9, 1.6, 1.6, 1.5, 1.4, 1.6,         1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3, 1.5, 1.3,         1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5,         4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7,         3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3,         4.4, 4.8, 5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5,         4.7, 4.4, 4.1, 4, 4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3,         3, 4.1, 6, 5.1, 5.9, 5.6, 5.8, 6.6, 4.5, 6.3, 5.8, 6.1,         5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 6.7, 6.9, 5, 5.7, 4.9,         6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 6.1, 6.4, 5.6,         5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 5.9,         5.7, 5.2, 5, 5.2, 5.4, 5.1), Petal.Width = c(0.2, 0.2,         0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.2, 0.1,         0.1, 0.2, 0.4, 0.4, 0.3, 0.3, 0.3, 0.2, 0.4, 0.2, 0.5,         0.2, 0.2, 0.4, 0.2, 0.2, 0.2, 0.2, 0.4, 0.1, 0.2, 0.2,         0.2, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.6, 0.4, 0.3,         0.2, 0.2, 0.2, 0.2, 1.4, 1.5, 1.5, 1.3, 1.5, 1.3, 1.6,         1, 1.3, 1.4, 1, 1.5, 1, 1.4, 1.3, 1.4, 1.5, 1, 1.5, 1.1,         1.8, 1.3, 1.5, 1.2, 1.3, 1.4, 1.4, 1.7, 1.5, 1, 1.1,         1, 1.2, 1.6, 1.5, 1.6, 1.5, 1.3, 1.3, 1.3, 1.2, 1.4,         1.2, 1, 1.3, 1.2, 1.3, 1.3, 1.1, 1.3, 2.5, 1.9, 2.1,         1.8, 2.2, 2.1, 1.7, 1.8, 1.8, 2.5, 2, 1.9, 2.1, 2, 2.4,         2.3, 1.8, 2.2, 2.3, 1.5, 2.3, 2, 2, 1.8, 2.1, 1.8, 1.8,         1.8, 2.1, 1.6, 1.9, 2, 2.2, 1.5, 1.4, 2.3, 2.4, 1.8,         1.8, 2.1, 2.4, 2.3, 1.9, 2.3, 2.5, 2.3, 1.9, 2, 2.3,         1.8), Species = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,         1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,         2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,         3L, 3L, 3L), .Label = c('setosa', 'versicolor', 'virginica'),         class = 'factor')), .Names = c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width', 'Species'), row.names = c(NA,     -150L), class = 'data.frame')), .Names = 'object');do.call('summary', argv)
   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width
  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100
@@ -143656,6 +143656,85 @@ see '?methods' for accessing help and source code
 #0xa.p2
 [1] 40
 
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#``(1)
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#as.symbol(''))
+Error: unexpected ')' in "as.symbol(''))"
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#e <- quote(b(f=1,foo)); names(e) <- c('','',''); e
+b(1, foo)
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#e <- quote(b(f=1,foo)); names(e) <- c('','f',''); e
+b(f = 1, foo)
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#Output.IgnoreErrorMessage#
+#e <- quote(x <- 1); e[[2]] <- as.symbol(''); 
+Error in as.symbol("") : attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#Output.IgnoreErrorMessage#
+#f <- function(){ function('') cat(asdf=1) }
+Error: unexpected string constant in "f <- function(){ function(''"
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#f <- function(){ function() cat(``=1) }
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#f <- function(){ function() cat(asdf=1) }
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#f <- function(){ function(``) cat(asdf=1) }
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#f <- function(){ function(``=1) 1 }
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#f <- function(){ function(``=1) cat(``=1) }
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#names(e)
+Error: object 'e' not found
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(``(1))
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(``:::a)
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(a$'')
+a$""
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(a$``)
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(a$b)
+a$b
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(a:::``)
+Error: attempt to use zero-length variable name
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(a:::a)
+a:::a
+
+##com.oracle.truffle.r.test.parser.TestParser.testEmptySymbols#
+#quote(x <- 1)
+x <- 1
+
 ##com.oracle.truffle.r.test.parser.TestParser.testHexLiterals#
 #+0xFFF
 [1] 4095
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
index c68a018863..b68f29703a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
@@ -105,6 +105,30 @@ public class TestParser extends TestBase {
         assertEval(Output.IgnoreErrorMessage, "a <- 1:100; y <- 2; z <- 5; x <- (a[[{y \n * z}]])");
     }
 
+    @Test
+    public void testEmptySymbols() {
+        assertEval("names(e)");
+        assertEval("e <- quote(b(f=1,foo)); names(e) <- c('','f',''); e");
+        assertEval("e <- quote(b(f=1,foo)); names(e) <- c('','',''); e");
+        assertEval("f <- function(){ function(``=1) 1 }");
+        assertEval("f <- function(){ function(``=1) cat(``=1) }");
+        assertEval("f <- function(){ function() cat(``=1) }");
+        assertEval("f <- function(){ function() cat(asdf=1) }");
+        assertEval("f <- function(){ function(``) cat(asdf=1) }");
+        assertEval(Output.IgnoreErrorMessage, "f <- function(){ function('') cat(asdf=1) }");
+        assertEval("``(1)");
+        assertEval("quote(``(1))");
+        assertEval("quote(a$b)");
+        assertEval("quote(a$``)");
+        assertEval("quote(a$'')");
+        assertEval("quote(``:::a)");
+        assertEval("quote(a:::a)");
+        assertEval("quote(a:::``)");
+        assertEval("quote(x <- 1)");
+        assertEval(Output.IgnoreErrorMessage, "e <- quote(x <- 1); e[[2]] <- as.symbol(''); ");
+        assertEval("as.symbol(''))");
+    }
+
     @Test
     public void testLexerError() {
         // FastR provides a more accurate error message
-- 
GitLab


From cc8f1c11d5038f04fdf89f7780d77ef383f94798 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 29 Mar 2017 11:26:33 +0200
Subject: [PATCH 209/402] pass along original exception in
 HiddenInternalFunctions

---
 .../truffle/r/nodes/builtin/base/HiddenInternalFunctions.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index 7c155fb9c0..f95d1d95a6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -424,7 +424,7 @@ public class HiddenInternalFunctions {
             } catch (Throwable ex) {
                 // Exceptions have been observed that were masked and very hard to find
                 ex.printStackTrace();
-                throw RInternalError.shouldNotReachHere("lazyLoadDBinsertValue exception");
+                throw RInternalError.shouldNotReachHere(ex, "lazyLoadDBinsertValue exception");
             }
         }
 
-- 
GitLab


From 2251a322eeb29146def9ca8bbd5441b3b65d0bab Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Wed, 29 Mar 2017 16:35:21 +0200
Subject: [PATCH 210/402] A bug in the output format fixed

---
 .../src/com/oracle/truffle/r/library/utils/Download.java        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
index e3b26dca3d..d9b2e1d55b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
@@ -68,7 +68,7 @@ public abstract class Download extends RExternalBuiltinNode.Arg5 {
 
                     StdConnections.getStderr().writeString(String.format("Content type '%s'", contentType != null ? contentType : "unknown"), false);
                     if (len > 1024 * 1024) {
-                        StdConnections.getStderr().writeString(String.format(" length %0.0f bytes (%0.1f MB)", (double) len, len / 1024.0 / 1024.0), true);
+                        StdConnections.getStderr().writeString(String.format(" length %d bytes (%.1f MB)", len, len / 1024.0 / 1024.0), true);
                     } else if (len > 10240) {
                         StdConnections.getStderr().writeString(String.format(" length %d bytes (%d KB)", len, len / 1024), true);
                     } else if (len >= 0) {
-- 
GitLab


From 31605db5278d9759c66796456534ce8d3ee17a3b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 30 Mar 2017 10:59:10 +0200
Subject: [PATCH 211/402] Assert that RLists do not contain "null" values.

---
 .../truffle/r/nodes/builtin/base/Combine.java |  4 +--
 .../r/nodes/builtin/base/LaFunctions.java     | 12 +++-----
 .../truffle/r/nodes/builtin/base/MatMult.java | 10 ++++---
 .../truffle/r/nodes/builtin/base/Merge.java   | 14 ++++------
 .../r/nodes/builtin/base/RowsumFunctions.java |  7 ++---
 .../truffle/r/nodes/builtin/base/Scan.java    |  2 +-
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  7 +----
 .../truffle/r/runtime/data/RDataFactory.java  | 28 ++++++++++++++++++-
 .../truffle/r/runtime/data/RExpression.java   |  2 +-
 .../oracle/truffle/r/runtime/data/RList.java  |  2 +-
 .../truffle/r/runtime/data/RListBase.java     |  7 +++++
 .../closures/RAbstactVectorToListClosure.java |  4 +--
 .../data/model/RAbstractListVector.java       |  5 +++-
 13 files changed, 64 insertions(+), 40 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 142900be4e..8670e1bfc8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -382,9 +382,9 @@ public abstract class Combine extends RBuiltinNode {
             case RAW_PRECEDENCE:
                 return RDataFactory.createRawVector(new byte[size], names);
             case EXPRESSION_PRECEDENCE:
-                return RDataFactory.createExpression(new Object[size], names);
+                return RDataFactory.createExpression(size, names);
             case LIST_PRECEDENCE:
-                return RDataFactory.createList(new Object[size], names);
+                return RDataFactory.createList(size, names);
             case NO_PRECEDENCE:
                 return null;
             default:
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 64f880fc2a..c379ee6da5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -617,14 +617,10 @@ public class LaFunctions {
                 // This is somewhat odd, but Matrix relies on dropping NULL dimnames
                 if (aDn != null || binDn != null) {
                     // rownames(ans) = colnames(A), colnames(ans) = colnames(Bin)
-                    Object[] bDnData = new Object[2];
-                    if (aDn != null) {
-                        bDnData[0] = aDn.getDataAt(1);
-                    }
-                    if (binDn != null) {
-                        bDnData[1] = binDn.getDataAt(1);
-                    }
-                    if (bDnData[0] != null || bDnData[1] != null) {
+                    if (aDn != null || binDn != null) {
+                        Object[] bDnData = new Object[2];
+                        bDnData[0] = aDn == null ? RNull.instance : aDn.getDataAt(1);
+                        bDnData[1] = binDn == null ? RNull.instance : binDn.getDataAt(1);
                         setBDimNamesNode.setDimNames(b, RDataFactory.createList(bDnData));
                     }
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index a531e18b3e..5630ef3dab 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -51,6 +51,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -229,14 +230,15 @@ public abstract class MatMult extends RBuiltinNode {
             return resultVec;
         }
 
-        Object[] newDimsNames = new Object[2];
+        Object dimName1 = RNull.instance;
         if (aDimNames != null && aDimNames.getLength() > 0) {
-            newDimsNames[0] = aDimNames.getDataAt(0);
+            dimName1 = aDimNames.getDataAt(0);
         }
+        Object dimName2 = RNull.instance;
         if (bDimNames != null && bDimNames.getLength() > 1) {
-            newDimsNames[1] = bDimNames.getDataAt(1);
+            dimName2 = bDimNames.getDataAt(1);
         }
-        setDimNamesNode.setDimNames(resultVec, RDataFactory.createList(newDimsNames));
+        setDimNamesNode.setDimNames(resultVec, RDataFactory.createList(new Object[]{dimName1, dimName2}));
         return resultVec;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
index 018f96b894..530074e875 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
@@ -151,28 +151,24 @@ public abstract class Merge extends RBuiltinNode {
         int[] ansXData = new int[nans];
         int[] ansYData = new int[nans];
 
-        RList ans = RDataFactory.createList(new Object[4], RDataFactory.createStringVector(new String[]{"xi", "yi", "x.alone", "y.alone"}, RDataFactory.COMPLETE_VECTOR));
-        ans.updateDataAt(0, RDataFactory.createIntVector(ansXData, RDataFactory.COMPLETE_VECTOR), null);
-        ans.updateDataAt(1, RDataFactory.createIntVector(ansYData, RDataFactory.COMPLETE_VECTOR), null);
+        Object[] ansData = new Object[]{RDataFactory.createIntVector(ansXData, RDataFactory.COMPLETE_VECTOR), RDataFactory.createIntVector(ansYData, RDataFactory.COMPLETE_VECTOR), RNull.instance,
+                        RNull.instance};
+        RList ans = RDataFactory.createList(ansData, RDataFactory.createStringVector(new String[]{"xi", "yi", "x.alone", "y.alone"}, RDataFactory.COMPLETE_VECTOR));
 
         if (allX) {
             int[] xLoneData = new int[nxLone];
-            ans.updateDataAt(2, RDataFactory.createIntVector(xLoneData, RDataFactory.COMPLETE_VECTOR), null);
+            ansData[2] = RDataFactory.createIntVector(xLoneData, RDataFactory.COMPLETE_VECTOR);
             for (int i = 0, ll = 0; i < nxLone; i++) {
                 xLoneData[ll++] = ix[i];
             }
-        } else {
-            ans.updateDataAt(2, RNull.instance, null);
         }
 
         if (allY) {
             int[] yLoneData = new int[nyLone];
-            ans.updateDataAt(3, RDataFactory.createIntVector(yLoneData, RDataFactory.COMPLETE_VECTOR), null);
+            ansData[3] = RDataFactory.createIntVector(yLoneData, RDataFactory.COMPLETE_VECTOR);
             for (int i = 0, ll = 0; i < nyLone; i++) {
                 yLoneData[ll++] = iy[i];
             }
-        } else {
-            ans.updateDataAt(3, RNull.instance, null);
         }
 
         j = nyLone;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
index 6a8df0334b..c8b0232b06 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
@@ -137,13 +137,12 @@ public class RowsumFunctions {
                 }
                 result = RDataFactory.createDoubleVector(ansd, complete, new int[]{ng, p});
             }
-            Object[] dimNamesData = new Object[2];
-            dimNamesData[0] = rn;
             RList dn2 = xv.materialize().getDimNames();
+            Object dn2Obj = RNull.instance;
             if (dn2 != null && dn2.getLength() >= 2 && dn2.getDataAt(1) != RNull.instance) {
-                dimNamesData[1] = dn2.getDataAt(1);
+                dn2Obj = dn2.getDataAt(1);
             }
-            RList dimNames = RDataFactory.createList(dimNamesData);
+            RList dimNames = RDataFactory.createList(new Object[]{rn, dn2Obj});
             result.setDimNames(dimNames);
             return result;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index dcc06718fd..4e90a9dd39 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -321,7 +321,7 @@ public abstract class Scan extends RBuiltinNode {
         }
         int blockSize = maxRecords > 0 ? maxRecords : (maxLines > 0 ? maxLines : SCAN_BLOCKSIZE);
 
-        RList list = RDataFactory.createList(new Object[nc]);
+        RList list = RDataFactory.createList(nc);
         for (int i = 0; i < nc; i++) {
             if (what.getDataAt(i) == RNull.instance) {
                 throw error(RError.Message.INVALID_ARGUMENT, "what");
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 c06af8b64f..2c78c9fbb6 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
@@ -392,12 +392,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             case RAWSXP:
                 return RDataFactory.createRawVector(new byte[n]);
             case VECSXP:
-                // fill list with "NULL" values
-                RList list = RDataFactory.createList(n);
-                for (int i = 0; i < n; i++) {
-                    list.setElement(i, RNull.instance);
-                }
-                return list;
+                return RDataFactory.createList(n);
             case LANGSXP:
                 return RDataFactory.createLangPairList(n);
             default:
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index fb20f10a0d..ee8b17a277 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -375,13 +375,33 @@ public final class RDataFactory {
     }
 
     public static RList createList(int n) {
-        return createList(new Object[n], null, null);
+        return createList(createRNullArray(n), null, null);
+    }
+
+    public static RList createList(int size, RStringVector names) {
+        if (names == null) {
+            return createList(size);
+        }
+        assert size == names.getLength();
+        return createList(createRNullArray(names.getLength()), null, names);
     }
 
     public static RList createList(Object[] data, int[] newDimensions, RStringVector names) {
         return traceDataCreated(new RList(data, newDimensions, names));
     }
 
+    public static RExpression createExpression(int size) {
+        return createExpression(createRNullArray(size));
+    }
+
+    public static RExpression createExpression(int size, RStringVector names) {
+        if (names == null) {
+            return createExpression(size);
+        }
+        assert size == names.getLength();
+        return createExpression(createRNullArray(size), names);
+    }
+
     public static RExpression createExpression(Object[] data, int[] newDimensions) {
         return traceDataCreated(new RExpression(data, newDimensions, null));
     }
@@ -558,4 +578,10 @@ public final class RDataFactory {
     public static void addListener(Listener listener) {
         listeners.addLast(listener);
     }
+
+    private static Object[] createRNullArray(int size) {
+        Object[] data = new Object[size];
+        Arrays.fill(data, RNull.instance);
+        return data;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index dd24eb9fc1..450359f5b7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -70,7 +70,7 @@ public final class RExpression extends RListBase implements RAbstractVector {
 
     @Override
     public RExpression createEmptySameType(int newLength, boolean newIsComplete) {
-        return RDataFactory.createExpression(new Object[newLength]);
+        return RDataFactory.createExpression(newLength);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
index f9082b3bb9..63184283da 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
@@ -70,7 +70,7 @@ public final class RList extends RListBase implements RAbstractListVector {
 
     @Override
     public RList createEmptySameType(int newLength, boolean newIsComplete) {
-        return RDataFactory.createList(new Object[newLength]);
+        return RDataFactory.createList(newLength);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
index b4abaf3bbe..9ad1c7c3b1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
@@ -80,6 +80,7 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
 
     @Override
     public void setDataAt(Object store, int index, Object valueArg) {
+        assert valueArg != null : "lists must not contain nulls";
         Object value = valueArg;
         assert store == data;
         ((Object[]) store)[index] = value;
@@ -92,6 +93,11 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
 
     @Override
     protected final boolean internalVerify() {
+        for (Object item : data) {
+            if (item == null) {
+                return false;
+            }
+        }
         return true;
     }
 
@@ -123,6 +129,7 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
 
     public final RListBase updateDataAt(int i, Object right, @SuppressWarnings("unused") NACheck rightNACheck) {
         assert !this.isShared() : "data in shared list must not be updated, make a copy";
+        assert right != null : "lists must not contain nulls";
         data[i] = right;
         return this;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java
index 4d076c044e..ae651a3e46 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,6 @@ final class RAbstactVectorToListClosure extends RToVectorClosure implements RAbs
 
     @Override
     public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
-        return RDataFactory.createList(new Object[newLength]);
+        return RDataFactory.createList(newLength);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java
index 681861e7e5..46c3406328 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractListVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@ package com.oracle.truffle.r.runtime.data.model;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RList;
 
+/**
+ * Note: lists must not contain {@code null} values.
+ */
 public interface RAbstractListVector extends RAbstractListBaseVector {
 
     @Override
-- 
GitLab


From 2d9e7013f09964633a29d6545c236cc2d5f5793a Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 30 Mar 2017 10:59:57 +0200
Subject: [PATCH 212/402] Cast exception fix

---
 .../src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 8b34ba02b1..8784637eb9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -140,7 +140,7 @@ final class GridUtils {
 
     static double asDouble(Object val, int cyclicIndex) {
         if (val instanceof Double) {
-            return (int) val;
+            return (double) val;
         } else if (val instanceof RAbstractDoubleVector) {
             RAbstractDoubleVector vec = (RAbstractDoubleVector) val;
             if (vec.getLength() > 0) {
-- 
GitLab


From 9cfdf369e776d11578025324c573ec6f5a3e6557 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 30 Mar 2017 11:17:00 +0200
Subject: [PATCH 213/402] Implemented some missing functionality in function
 C_readtablehead.

---
 .../builtin/base/foreign/ReadTableHead.java   | 43 +++++++++++++++++--
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
index aa4b0da4d8..9c3477a46d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java
@@ -12,9 +12,12 @@
 package com.oracle.truffle.r.nodes.builtin.base.foreign;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -28,17 +31,51 @@ public abstract class ReadTableHead extends RExternalBuiltinNode.Arg7 {
         Casts casts = new Casts(ReadTableHead.class);
         casts.arg(0).defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
         casts.arg(1).mustNotBeNull().asIntegerVector().findFirst();
+        casts.arg(2).mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector().findFirst();
+        casts.arg(3).mustNotBeMissing().mustBe(Predef.logicalValue()).asLogicalVector().findFirst().map(Predef.toBoolean());
+        casts.arg(4).mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector().findFirst();
+        casts.arg(5).mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector().findFirst();
+        casts.arg(6).mustNotBeMissing().mustBe(Predef.logicalValue()).asLogicalVector().findFirst().map(Predef.toBoolean());
     }
 
     @Specialization
     @TruffleBoundary
-    public RAbstractStringVector read(int con, int nlines, @SuppressWarnings("unused") Object commentChar, @SuppressWarnings("unused") Object blankLinesSkip,
-                    @SuppressWarnings("unused") Object quote, @SuppressWarnings("unused") Object sep, @SuppressWarnings("unused") Object skipNull) {
+    public RAbstractStringVector read(int con, int nlines, String commentChar, boolean blankLinesSkip,
+                    String quote, String sep, boolean skipNull) {
         // TODO This is quite incomplete and just uses readLines, which works for some inputs
         try (RConnection openConn = RConnection.fromIndex(con).forceOpen("r")) {
-            return RDataFactory.createStringVector(openConn.readLines(nlines, true, false), RDataFactory.COMPLETE_VECTOR);
+            List<String> lines = new ArrayList<>(nlines);
+            int totalLines = 0;
+            while (totalLines < nlines) {
+                String[] readLines = openConn.readLines(nlines - totalLines, true, skipNull);
+                if (readLines.length == 0) {
+                    break;
+                }
+
+                for (int i = 0; i < readLines.length; i++) {
+                    postprocessLine(lines, readLines[i], commentChar, blankLinesSkip, quote, sep);
+                }
+                totalLines += lines.size();
+            }
+
+            return RDataFactory.createStringVector(lines.toArray(new String[0]), RDataFactory.COMPLETE_VECTOR);
         } catch (IOException ex) {
             throw error(RError.Message.ERROR_READING_CONNECTION, ex.getMessage());
         }
     }
+
+    private static void postprocessLine(List<String> lines, String string, String commentChar, boolean blankLinesSkip, @SuppressWarnings("unused") String quote,
+                    @SuppressWarnings("unused") String sep) {
+        // TODO quote, sep
+        if (blankLinesSkip && string.isEmpty()) {
+            return;
+        }
+
+        if (commentChar != null && !commentChar.isEmpty() && string.startsWith(commentChar)) {
+            return;
+        }
+
+        // no reason why not to add
+        lines.add(string);
+    }
 }
-- 
GitLab


From 3e768cde8b959fdc617b12007dd5b5f4dd837cfb Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 31 Mar 2017 16:55:33 +0200
Subject: [PATCH 214/402] suppress messages in TestR5

---
 .../truffle/r/test/ExpectedTestOutput.test    | 116 +++++++++++-------
 .../com/oracle/truffle/r/test/S4/TestR5.java  |  34 +++--
 2 files changed, 96 insertions(+), 54 deletions(-)

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 d2b8d348af..98500f6ccb 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
@@ -60,11 +60,24 @@ Error: invalid assignment for reference class field ‘a’, should be from clas
 [1] TRUE
 [1] TRUE
 
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.IgnoreWhitespace#
+#print(suppressMessages({clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo')}))
+function() NULL
+attr(,"mayCall")
+character(0)
+attr(,"name")
+[1] "foo"
+attr(,"refClassName")
+[1] "Foo20R5"
+attr(,"superClassMethod")
+[1] ""
+attr(,"class")
+[1] "refMethodDef"
+attr(,"class")attr(,"package")
+[1] "methods"
+
 ##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
-#clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)
-code for methods in class “Foo21R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-NULL
-code for methods in class “Foo21R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+#print(suppressMessages({clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)}))
 [1] 3
 
 ##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
@@ -94,13 +107,6 @@ Warning message:
 In .getMethodDefs(methodDefs[[1]], methodsEnv) :
   Methods not found: “.objectPackage”, “.objectParent”, “callSuper”, “copy”, “export”, “field”, “getClass”, “getRefClass”, “import”, “initFields”, “show”, “trace”, “untrace”, “usingMethods”
 
-##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.IgnoreWhitespace#
-#{ clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo') }
-code for methods in class “Foo20R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-Class method definition for method foo()
-function ()
-NULL
-
 ##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#
 #{ clazz <- setRefClass('Foo22R5'); clazz$fields() }
 NULL
@@ -138,29 +144,58 @@ Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
 [1] 1
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
-#A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()
-code for methods in class “A1R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+#A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0)
+
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
+#print(suppressMessages({A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()}))
+[1] "hello"
 [1] "hello"
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
-#A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()
-code for methods in class “A2R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-code for methods in class “B2R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+#print(suppressMessages({A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()}))
+[1] "world"
 [1] "world"
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
-#A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()
-code for methods in class “A3R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-code for methods in class “B3R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+#print(suppressMessages({A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()}))
 [1] "hello"
 [1] "world"
+[1] "world"
 
-##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
-#A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0)
+##com.oracle.truffle.r.test.S4.TestR5.testInheritance#Ignored.OutputFormatting#
+#print(suppressMessages({{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }}))
+function (...)
+new("B4R5", ...)
+attr(,"className")
+[1] "B4R5"
+attr(,"className")attr(,"package")
+[1] ".GlobalEnv"
+attr(,"package")
+[1] ".GlobalEnv"
+attr(,"generator")
+Reference class object of class "refGeneratorSlot"
+Field "def":
+Reference Class "B4R5":
 
-##com.oracle.truffle.r.test.S4.TestR5.testInheritance#
-#{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }
-code for methods in class “B4R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+Class fields:
+
+Name:    a
+Class: ANY
+
+Class Methods:
+     "set_a", "import", ".objectParent", "usingMethods", "show", "getClass",
+     "untrace", "export", ".objectPackage", "callSuper", "copy", "initFields",
+     "getRefClass", "trace", "field"
+
+Reference Superclasses:
+     "A4R5", "envRefClass"
+
+Field "className":
+[1] "B4R5"
+attr(,"class")
+[1] "refObjectGenerator"
+attr(,"class")attr(,"package")
+[1] "methods"
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
 #clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')
@@ -176,25 +211,30 @@ Field "b":
 [1] 6
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }
-code for methods in class “Foo0R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+#print(suppressMessages({{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }}))
 [1] 3
 
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }
-code for methods in class “Foo12R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
+#print(suppressMessages({{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }}))
+[1] 1
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#print(suppressMessages({{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }}))
+[1] 123
+
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#print(suppressMessages({{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }}))
 [1] 1
 
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
+#print(suppressMessages({{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }}))
+[1] "hello"
+
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
 #{ clazz <- setRefClass('Foo13R5'); obj <- clazz$new(); obj$inexistingMethod() }
 Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
   ‘inexistingMethod’ is not a valid field or method name for reference class “Foo13R5”
 
-##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }
-code for methods in class “Foo15R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-[1] 123
-
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Ignored.Unknown#
 #{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }
 code for methods in class “Foo18R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
@@ -208,11 +248,6 @@ Vcells 455966  3.5    1023718  7.9   784463  6.0
 #{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}
 [1] 1
 
-##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }
-code for methods in class “Foo28R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-[1] 1
-
 ##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Output.IgnoreErrorContext#
 #{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }
 Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
@@ -224,11 +259,6 @@ Error in `substr<-`(`*tmp*`, 1, 1, value = character(0)) :
 attr(,"package")
 [1] ".GlobalEnv"
 
-##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#
-#{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }
-code for methods in class “A6R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
-[1] "hello"
-
 ##com.oracle.truffle.r.test.S4.TestR5.testReferenceSemantics#
 #fooClass <- setRefClass('Foo12R5', fields = list( a = 'numeric')); obj0 <- fooClass$new(a = 1); obj1 <- obj0; obj0$a; obj1$a; obj0$a <- 999; obj0$a; obj1$a
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index fc5c557832..9d31793e24 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -25,11 +25,23 @@ package com.oracle.truffle.r.test.S4;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import com.oracle.truffle.r.test.TestTrait;
 
 // Checkstyle: stop LineLength
 
 public class TestR5 extends TestBase {
 
+    /**
+     * {@code suppressMessages} is needed to suppress messages about codetools not being available.
+     */
+    private void assertSuppress(String test) {
+        assertEval("print(suppressMessages({" + test + "}))");
+    }
+
+    private void assertSuppress(TestTrait trait, String test) {
+        assertEval(trait, "print(suppressMessages({" + test + "}))");
+    }
+
     @Test
     public void testAllocation() {
         assertEval("{ DummyClass0 <- setRefClass('DummyClass0'); DummyClass0$new() }");
@@ -53,19 +65,19 @@ public class TestR5 extends TestBase {
 
     @Test
     public void testInstanceMethods() {
-        assertEval("{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }");
+        assertSuppress("{ clazz <- setRefClass('Foo0R5', c('a', 'b')); clazz$methods(mean = function() { (a + b) / 2 }); obj <- clazz$new(a = 1, b = 5); obj$mean() }");
         assertEval("{ clazz <- setRefClass('Foo1R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); cobj <- obj$copy(); obj$a; cobj$a; obj$a <- 10; obj$a; cobj$a}");
         assertEval("clazz <- setRefClass('Foo2R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); obj$field('a'); obj$field('b')");
         assertEval("clazz <- setRefClass('Foo3R5', c('a', 'b')); obj <- clazz$new(); obj$initFields(a = 5, b = 6)");
         assertEval(Output.IgnoreErrorContext, "{ clazz <- setRefClass('Foo4R5', c('a', 'b')); clazz$accessors() }");
         assertEval("{ clazz <- setRefClass('Foo5R5', c('a', 'b')); obj <- clazz$new(a = 1, b = 5); attributes(obj$getRefClass())$className }");
-        assertEval("{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
+        assertSuppress("{ clazz <- setRefClass('Foo12R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
         assertEval("{ clazz <- setRefClass('Foo13R5'); obj <- clazz$new(); obj$inexistingMethod() }");
-        assertEval("{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
+        assertSuppress("{ clazz <- setRefClass('Foo28R5', fields = list(a = 'numeric'), methods = list(inc = function() { a <<- a+1 })); obj <- clazz$new(a = 0); obj$inc(); obj$a }");
 
         // constructor
-        assertEval("{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }");
-        assertEval("{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }");
+        assertSuppress("{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }");
+        assertSuppress("{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }");
 
         assertEval(Ignored.Unknown,
                         "{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }");
@@ -87,8 +99,8 @@ public class TestR5 extends TestBase {
 
         // list/modify methods
         assertEval("{ clazz <- setRefClass('Foo19R5'); clazz$methods('inexistingMethod') }");
-        assertEval(Output.IgnoreWhitespace, "{ clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo') }");
-        assertEval("clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)");
+        assertSuppress(Ignored.OutputFormatting, "clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo')");
+        assertSuppress("clazz <- setRefClass('Foo21R5', methods = list(foo = function() NULL)); clazz$new()$foo(); clazz$methods(foo = function(x) x); clazz$new()$foo(3)");
 
         // list available fields
         assertEval("{ clazz <- setRefClass('Foo22R5'); clazz$fields() }");
@@ -107,10 +119,10 @@ public class TestR5 extends TestBase {
     @Test
     public void testInheritance() {
         assertEval("A0R5 <- setRefClass('A0R5', field = list(a = 'numeric')); B0R5 <- setRefClass('B0R5', contains = 'A0R5'); obj <- B0R5$new(a = 1); obj$a");
-        assertEval("A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()");
-        assertEval("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()");
-        assertEval("A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
-        assertEval("{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }");
+        assertSuppress("A1R5 <- setRefClass('A1R5', methods = list(foo = function() { print('hello') })); B1R5 <- setRefClass('B1R5', contains = 'A1R5'); obj <- B1R5$new(); obj$foo()");
+        assertSuppress("A2R5 <- setRefClass('A2R5', methods = list(foo = function() { print('hello') })); B2R5 <- setRefClass('B2R5', methods = list(foo = function() { print('world') }), contains = 'A2R5'); obj <- B2R5$new(); obj$foo()");
+        assertSuppress("A3R5 <- setRefClass('A3R5', methods = list(foo = function() { print('hello') })); B3R5 <- setRefClass('B3R5', methods = list(foo = function() { callSuper(); print('world') }), contains = 'A3R5'); obj <- B3R5$new(); obj$foo()");
+        assertSuppress(Ignored.OutputFormatting, "{ setRefClass('A4R5', fields = c('a')); setRefClass('B4R5', contains = 'A4R5', methods = list(set_a = function(a){ a <<- a })) }");
         assertEval("A5R5 <- setRefClass('A5R5', field = c('a'), methods = list(initialize <- function() { a <<- 0 })); B5R5 <- setRefClass('B5R5', field = c('a'), methods = list(initialize <- function() { a <<- 'hello' })); C5R5 <- setRefClass('C5R5', contains = c('A5R5', 'B5R5')); obj <- C5R5$new(); obj$a <- raw(0)");
     }
 }
-- 
GitLab


From c1fff0aaaa7104323c2f9a90d9cff709448eaa34 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 30 Mar 2017 14:18:16 +0200
Subject: [PATCH 215/402] FastR Grid: do not put nulls in RLists

---
 .../r/library/fastrGrid/DoSetViewPort.java    |  2 ++
 .../r/library/fastrGrid/GridLinesNode.java    | 14 +++++----
 .../r/library/fastrGrid/GridState.java        |  2 ++
 .../r/library/fastrGrid/LGridDirty.java       | 22 +++++++-------
 .../truffle/r/library/fastrGrid/LNewPage.java | 29 +++++++++++++++----
 .../r/library/fastrGrid/LUnsetViewPort.java   |  2 +-
 6 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index f61ea60f85..0d83e296f4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -74,6 +74,8 @@ final class DoSetViewPort extends RBaseNode {
         pushedVPData[ViewPort.PVP_CLIPRECT] = RDataFactory.createDoubleVector(new double[]{0, 0, 0, 0}, RDataFactory.COMPLETE_VECTOR);
         pushedVPData[ViewPort.PVP_DEVWIDTHCM] = scalar(Unit.inchesToCm(currentDevice.getWidth()));
         pushedVPData[ViewPort.PVP_DEVHEIGHTCM] = scalar(Unit.inchesToCm(currentDevice.getHeight()));
+
+        assert pushedViewPort.verify();
         return pushedViewPort;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 8db8ff46c3..dd85870df0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -90,15 +90,17 @@ public abstract class GridLinesNode extends Node {
                     // (1) current is invalid point. Note: in (one of) the next iteration(s), the
                     // oldIsFinite will be false and we will update the start and start a new series
                     // (2) we are in the last iteration
-                    if (lastIter || i - start > 1) {
-                        // we draw only if the previous series of points was at least of length 3 or
-                        // it's last iteration. This seems slightly weird, but that's how GnuR seems
-                        // to work
-                        drawPolylines(dev, drawingCtx, yy, xx, start, (i - start) + 1);
+                    int length = i - start;
+                    if (currIsFinite) {
+                        // the length either includes the last only if it is finite (last iteration)
+                        length++;
+                    }
+                    if (length > 1) {
+                        drawPolylines(dev, drawingCtx, yy, xx, start, length);
                         if (arrow != null) {
                             // Can draw an arrow at the start if the points include the first point.
                             // Draw an arrow at the end only if this is the last series
-                            drawArrowsNode.drawArrows(xx, yy, start, (i - start) + 1, unitIndex, arrow, start == 0, lastIter, conversionCtx);
+                            drawArrowsNode.drawArrows(xx, yy, start, length, unitIndex, arrow, start == 0, lastIter, conversionCtx);
                         }
                     }
                 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 321e0a022b..8da78932bd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -82,6 +82,7 @@ public final class GridState {
 
     void initGPar(GridDevice currentDevice) {
         devState.gpar = GPar.createNew(currentDevice);
+        assert devState.gpar.verify();
     }
 
     /**
@@ -120,6 +121,7 @@ public final class GridState {
     }
 
     public void setViewPort(RList viewPort) {
+        assert viewPort.verify();
         devState.viewPort = viewPort;
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
index d24bea0560..8d865b9172 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java
@@ -19,6 +19,13 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
+/**
+ * {@code L_gridDirty} is external that gets called before any grid operation, this is ensured by
+ * routing all external calls at R level through {@code grid.Call} function, which first invokes
+ * {@code L_gridDirty} before invoking the requested external. LGridDirty is responsible for delayed
+ * initialization of the grid state and device specific grid state if the device has changed since
+ * the last time.
+ */
 final class LGridDirty extends RExternalBuiltinNode {
     @Child private InitViewPortNode initViewPort = new InitViewPortNode();
 
@@ -39,28 +46,23 @@ final class LGridDirty extends RExternalBuiltinNode {
         // if no device has been opened yet, open the default one and make it current
         if (GridContext.getContext().getCurrentDevice() == null) {
             GridContext.getContext().openDefaultDevice();
-            gridState = GridContext.getContext().getGridState();    // grid state is device
-                                                                    // dependent
+            // grid state is device dependent
+            gridState = GridContext.getContext().getGridState();
         }
 
         // the current device has not been initialized yet...
         GridDevice device = GridContext.getContext().getCurrentDevice();
         device.openNewPage();
+        gridState.initGPar(device);
         gridState.setViewPort(initViewPort.execute(frame));
-        gridState.setDeviceInitialized();
-        if (gridState.getGpar() == null) {
-            gridState.initGPar(device);
-        }
-        if (gridState.getViewPort() == null) {
-            gridState.setViewPort(initViewPort.execute(frame));
-        }
         DisplayList.initDisplayList(gridState);
+        gridState.setDeviceInitialized();
         return RNull.instance;
     }
 
     @Override
     protected Object call(RArgsValuesAndNames args) {
-        // shadowed by the VirtualFrame overload
+        assert false : "should be shadowed by the overload with frame";
         return null;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 917154715f..2f491ea4cc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -11,19 +11,36 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-final class LNewPage extends RExternalBuiltinNode.Arg0 {
+final class LNewPage extends RExternalBuiltinNode {
     static {
         Casts.noCasts(LNewPage.class);
     }
 
+    @Child private LGridDirty gridDirty = new LGridDirty();
+
+    @Override
+    public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
+        GridDevice device = GridContext.getContext().getCurrentDevice();
+        if (GridContext.getContext().getGridState().isDeviceInitialized()) {
+            device.openNewPage();
+            return RNull.instance;
+        }
+        // There are some exceptions to the rule that any external call from grid R code is
+        // preceeded by L_gridDirty call, L_newpage is one of them.
+        CompilerDirectives.transferToInterpreter();
+        return gridDirty.call(frame, RArgsValuesAndNames.EMPTY);
+    }
+
     @Override
-    @TruffleBoundary
-    public Object execute() {
-        GridContext.getContext().getCurrentDevice().openNewPage();
-        return RNull.instance;
+    protected Object call(RArgsValuesAndNames args) {
+        assert false : "should be shadowed by the overload with frame";
+        return null;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
index 0416b1f674..f23564cd26 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -76,7 +76,7 @@ public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
         gridState.setViewPort(newVp);
 
         // remove the parent link from the old viewport
-        gvp.setDataAt(gvp.getInternalStore(), ViewPort.PVP_PARENT, null);
+        gvp.setDataAt(gvp.getInternalStore(), ViewPort.PVP_PARENT, RNull.instance);
         return RNull.instance;
     }
 
-- 
GitLab


From cfd60a1056d47e3bc6bde12aeabe14d442b094e6 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 30 Mar 2017 14:52:54 +0200
Subject: [PATCH 216/402] FastR Grid: devices support width/height parameters

---
 .../r/library/fastrGrid/GridContext.java      |  2 +-
 .../r/library/fastrGrid/GridLinesNode.java    |  2 +-
 .../library/fastrGrid/device/GridDevice.java  |  3 +++
 .../device/awt/BufferedImageDevice.java       |  4 ++-
 .../device/awt/BufferedJFrameDevice.java      |  2 +-
 .../device/awt/Graphics2DDevice.java          |  6 +++++
 .../fastrGrid/device/awt/JFrameDevice.java    | 20 +++++---------
 .../grDevices/InitWindowedDevice.java         | 27 +++++++++++++++----
 .../fastrGrid/grDevices/R/fastrGridDevices.R  |  4 +--
 9 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 356fc3173b..4f14e7b14e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -82,7 +82,7 @@ public final class GridContext {
     public void openDefaultDevice() {
         String defaultDev = RGridGraphicsAdapter.getDefaultDevice();
         if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) {
-            BufferedJFrameDevice result = new BufferedJFrameDevice(JFrameDevice.create());
+            BufferedJFrameDevice result = new BufferedJFrameDevice(JFrameDevice.create(GridDevice.DEFAULT_WIDTH, GridDevice.DEFAULT_HEIGHT));
             setCurrentDevice(defaultDev, result);
         } else {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'.");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index dd85870df0..32c5d9c52b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -92,7 +92,7 @@ public abstract class GridLinesNode extends Node {
                     // (2) we are in the last iteration
                     int length = i - start;
                     if (currIsFinite) {
-                        // the length either includes the last only if it is finite (last iteration)
+                        // the length includes the last point only if the point is finite
                         length++;
                     }
                     if (length > 1) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index f893a5b02b..2ea6e4468e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -27,6 +27,9 @@ package com.oracle.truffle.r.library.fastrGrid.device;
  * in inches and angles in radians unless stated otherwise.
  */
 public interface GridDevice {
+    int DEFAULT_WIDTH = 720;
+    int DEFAULT_HEIGHT = 720;
+
     void openNewPage();
 
     /**
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
index 485ad25161..5777844618 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
@@ -51,7 +51,9 @@ public final class BufferedImageDevice extends Graphics2DDevice {
             throw new NotSupportedImageFormatException();
         }
         BufferedImage image = new BufferedImage(width, height, TYPE_INT_RGB);
-        return new BufferedImageDevice(filename, fileType, image, (Graphics2D) image.getGraphics(), width, height);
+        Graphics2D graphics = (Graphics2D) image.getGraphics();
+        defaultInitGraphics(graphics);
+        return new BufferedImageDevice(filename, fileType, image, graphics, width, height);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
index b94f4e39aa..607b0ad8b0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
@@ -189,7 +189,7 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
     }
 
     private void setGraphics(Graphics graphics) {
-        JFrameDevice.defaultInitGraphics((Graphics2D) graphics);
+        Graphics2DDevice.defaultInitGraphics((Graphics2D) graphics);
         inner.getGraphics2D().dispose();
         inner.setGraphics2D((Graphics2D) graphics);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
index 055084a451..877ad16225 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
@@ -31,6 +31,7 @@ import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics2D;
 import java.awt.Paint;
+import java.awt.RenderingHints;
 import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
@@ -83,6 +84,11 @@ public class Graphics2DDevice implements GridDevice {
         this.graphicsIsExclusive = graphicsIsExclusive;
     }
 
+    static void defaultInitGraphics(Graphics2D graphics) {
+        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+        graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+    }
+
     @Override
     public void openNewPage() {
         graphics.clearRect(0, 0, width, height);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
index 93c4f700aa..7571ced32f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
@@ -26,7 +26,6 @@ import java.awt.BorderLayout;
 import java.awt.Dimension;
 import java.awt.Graphics2D;
 import java.awt.HeadlessException;
-import java.awt.RenderingHints;
 import java.awt.Toolkit;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
@@ -35,6 +34,7 @@ import javax.swing.JFrame;
 import javax.swing.JPanel;
 
 public final class JFrameDevice extends Graphics2DDevice {
+
     private final JFrame currentFrame;
     private final boolean disposeResources;
 
@@ -55,8 +55,8 @@ public final class JFrameDevice extends Graphics2DDevice {
      * Creates a standalone device that manages the window itself and closes it once
      * {@link #close()} gets called.
      */
-    public static JFrameDevice create() {
-        FastRFrame frame = new FastRFrame();
+    public static JFrameDevice create(int width, int height) {
+        FastRFrame frame = new FastRFrame(width, height);
         frame.setVisible(true);
         frame.pack();
         Graphics2D graphics = (Graphics2D) frame.getGraphics();
@@ -76,26 +76,20 @@ public final class JFrameDevice extends Graphics2DDevice {
         return currentFrame;
     }
 
-    static void defaultInitGraphics(Graphics2D graphics) {
-        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-        graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
-    }
-
     static class FastRFrame extends JFrame {
         private static final long serialVersionUID = 1L;
-        private final Dimension framePreferredSize = new Dimension(720, 720);
         private final JPanel fastRComponent = new JPanel();
 
-        FastRFrame() throws HeadlessException {
+        FastRFrame(int width, int height) throws HeadlessException {
             super("FastR");
             addCloseListener();
-            createUI();
+            createUI(width, height);
             center();
         }
 
-        private void createUI() {
+        private void createUI(int width, int height) {
             setLayout(new BorderLayout());
-            setSize(framePreferredSize);
+            setSize(new Dimension(width, height));
             add(fastRComponent, BorderLayout.CENTER);
             fastRComponent.setPreferredSize(getSize());
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 5048fe9411..40ceb214b5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
@@ -40,6 +41,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
  * . The arguments determine which device should be opened.
  */
 public final class InitWindowedDevice extends RExternalBuiltinNode {
+
     static {
         Casts.noCasts(InitWindowedDevice.class);
     }
@@ -47,28 +49,43 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
     @Override
     @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
+        int width = getIntOrDefault(args, 1, GridDevice.DEFAULT_WIDTH);
+        int height = getIntOrDefault(args, 2, GridDevice.DEFAULT_HEIGHT);
         // if the first argument is a String, then it may describes the image format and filename to
         // use, the format is e.g. "jpeg::quality:filename"
         if (args.getLength() >= 1) {
             String name = RRuntime.asString(args.getArgument(0));
             if (!RRuntime.isNA(name) && name.contains("::")) {
-                return openImageDevice(name);
+                return openImageDevice(name, width, height);
             }
         }
-        // otherwise the
-        GridContext.getContext().setCurrentDevice(args.getLength() == 0 ? "awt" : "X11cairo", new BufferedJFrameDevice(JFrameDevice.create()));
+        // otherwise the windowed device
+        BufferedJFrameDevice device = new BufferedJFrameDevice(JFrameDevice.create(width, height));
+        String name = args.getArgument(0).equals(".FASTR.AWT") ? "awt" : "X11cairo";
+        GridContext.getContext().setCurrentDevice(name, device);
         return RNull.instance;
     }
 
-    private Object openImageDevice(String name) {
+    private Object openImageDevice(String name, int width, int height) {
         String formatName = name.substring(0, name.indexOf("::"));
         String filename = name.substring(name.lastIndexOf(':') + 1);
         try {
-            BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, 700, 700);
+            BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, width, height);
             GridContext.getContext().setCurrentDevice(formatName, device);
         } catch (NotSupportedImageFormatException e) {
             throw error(Message.GENERIC, String.format("Format '%s' is not supported.", formatName));
         }
         return RNull.instance;
     }
+
+    private static int getIntOrDefault(RArgsValuesAndNames args, int index, int defaultValue) {
+        if (index >= args.getLength()) {
+            return defaultValue;
+        }
+        int value = RRuntime.asInteger(args.getArgument(index));
+        if (RRuntime.isNA(value)) {
+            return defaultValue;
+        }
+        return value;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
index 390bdacd81..a1bc97886a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
@@ -24,8 +24,8 @@ eval(expression({
     # For compatibility reasons, both X11 and awt end up calling C_X11.
     # In the future, this function may support extra parameters like a
     # reference to java 2D graphics object, which will be used for the drawing.
-    awt <- function(...) {
-        .External2(grDevices:::C_X11)
+    awt <- function(width = NULL, height = NULL) {
+        .External2(grDevices:::C_X11, ".FASTR.AWT", width, height)
     }
     # GnuR version only works with "X11cairo" device. Our version of savePlot
     # works with "awt" device and "X11cairo", which is for us only alias for
-- 
GitLab


From 0dcf6ed7cb8c367205aa5326fbf5b78fda56a0f6 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 31 Mar 2017 18:33:02 +0200
Subject: [PATCH 217/402] FastR Grid: more units support

---
 .../truffle/r/library/fastrGrid/Unit.java     | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index a4287304d1..2eccf77f90 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -163,6 +163,16 @@ public final class Unit {
                 return value;
             case POINTS:
                 return value * INCH_TO_POINTS_FACTOR;
+            case PICAS:
+                return value / 12 * INCH_TO_POINTS_FACTOR;
+            case BIGPOINTS:
+                return value * 72;
+            case DIDA:
+                return value / 1238 * 1157 * INCH_TO_POINTS_FACTOR;
+            case CICERO:
+                return value / 1238 * 1157 * INCH_TO_POINTS_FACTOR / 12;
+            case SCALEDPOINTS:
+                return value * 65536 * INCH_TO_POINTS_FACTOR;
             case LINES:
                 return (value * INCH_TO_POINTS_FACTOR) / (drawingCtx.getFontSize() * drawingCtx.getLineHeight());
             // following units are not supported even by original grid
@@ -184,6 +194,7 @@ public final class Unit {
     }
 
     private static double convertToInches(double value, int index, int unitId, RList data, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+        // Note: grob units are converted in a dedicated node
         double vpSize = ctx.getViewPortSize(axisOrDim);
         String str;
         String[] lines;
@@ -202,6 +213,16 @@ public final class Unit {
                 return value / CM_IN_INCH;
             case MM:
                 return value / (CM_IN_INCH * 10);
+            case PICAS:
+                return (value * 12) / INCH_TO_POINTS_FACTOR;
+            case BIGPOINTS:
+                return value / 72;
+            case DIDA:
+                return value / 1157 * 1238 / INCH_TO_POINTS_FACTOR;
+            case CICERO:
+                return value * 12 / 1157 * 1238 / INCH_TO_POINTS_FACTOR;
+            case SCALEDPOINTS:
+                return value / 65536 / INCH_TO_POINTS_FACTOR;
             case CHAR:
             case MYCHAR:
                 return (value * ctx.gpar.getDrawingContext(index).getFontSize()) / INCH_TO_POINTS_FACTOR;
-- 
GitLab


From 6b1da343efc475cf97efb7685ae793e026d077c9 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 31 Mar 2017 20:30:42 +0200
Subject: [PATCH 218/402] FastR Grid: implement L_validUnit

---
 .../fastrGrid/FastRGridExternalLookup.java    |    7 +-
 .../r/library/fastrGrid/GridColorUtils.java   | 1332 ++++++++---------
 .../r/library/fastrGrid/LValidUnit.java       |  116 ++
 .../truffle/r/library/fastrGrid/Unit.java     |   36 +-
 mx.fastr/copyrights/overrides                 |    1 +
 5 files changed, 802 insertions(+), 690 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index dc2ca5e33d..e8711d0537 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -87,6 +87,8 @@ public final class FastRGridExternalLookup {
                 return new LNewPage();
             case "L_convert":
                 return LConvert.create();
+            case "L_validUnits":
+                return LValidUnit.create();
 
             // Viewport management
             case "L_upviewport":
@@ -155,11 +157,6 @@ public final class FastRGridExternalLookup {
             case "L_newpagerecording":
                 return new IgnoredGridExternal(RNull.instance);
 
-            // These methods do not use graphics system or any global state. For now,
-            // we can re-use the native implementation, which in the future should be rewritten
-            // to managed code.
-            case "L_validUnits":
-                return null;
             default:
                 if (name.startsWith("L_")) {
                     throw RInternalError.shouldNotReachHere("Unimplemented grid external " + name);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
index 07a01a98c4..939a90546e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
@@ -19,8 +19,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 
 public final class GridColorUtils {
-    private static HashMap<String, Object> synonymToColor;
-
     private GridColorUtils() {
         // only static members
     }
@@ -67,10 +65,7 @@ public final class GridColorUtils {
     }
 
     private static Object findByName(String synonym) {
-        if (synonymToColor == null) {
-            initialize();
-        }
-        return synonymToColor.get(normalizeColorName(synonym));
+        return NamesHolder.NAMES.get(normalizeColorName(synonym));
     }
 
     // GnuR compares the user given color name to the dictionary ignoring spaces and case. We remove
@@ -84,666 +79,669 @@ public final class GridColorUtils {
         return isNormalized ? synonym : synonym.replace(" ", "").toLowerCase(Locale.ROOT);
     }
 
-    private static void initialize() {
-        synonymToColor = new HashMap<>(700);
-        synonymToColor.put("transparent", GridColor.TRANSPARENT);
-        synonymToColor.put("NA", GridColor.TRANSPARENT);
-        synonymToColor.put("white", "#FFFFFF");
-        synonymToColor.put("aliceblue", "#F0F8FF");
-        synonymToColor.put("antiquewhite", "#FAEBD7");
-        synonymToColor.put("antiquewhite1", "#FFEFDB");
-        synonymToColor.put("antiquewhite2", "#EEDFCC");
-        synonymToColor.put("antiquewhite3", "#CDC0B0");
-        synonymToColor.put("antiquewhite4", "#8B8378");
-        synonymToColor.put("aquamarine", "#7FFFD4");
-        synonymToColor.put("aquamarine1", "#7FFFD4");
-        synonymToColor.put("aquamarine2", "#76EEC6");
-        synonymToColor.put("aquamarine3", "#66CDAA");
-        synonymToColor.put("aquamarine4", "#458B74");
-        synonymToColor.put("azure", "#F0FFFF");
-        synonymToColor.put("azure1", "#F0FFFF");
-        synonymToColor.put("azure2", "#E0EEEE");
-        synonymToColor.put("azure3", "#C1CDCD");
-        synonymToColor.put("azure4", "#838B8B");
-        synonymToColor.put("beige", "#F5F5DC");
-        synonymToColor.put("bisque", "#FFE4C4");
-        synonymToColor.put("bisque1", "#FFE4C4");
-        synonymToColor.put("bisque2", "#EED5B7");
-        synonymToColor.put("bisque3", "#CDB79E");
-        synonymToColor.put("bisque4", "#8B7D6B");
-        synonymToColor.put("black", "#000000");
-        synonymToColor.put("blanchedalmond", "#FFEBCD");
-        synonymToColor.put("blue", "#0000FF");
-        synonymToColor.put("blue1", "#0000FF");
-        synonymToColor.put("blue2", "#0000EE");
-        synonymToColor.put("blue3", "#0000CD");
-        synonymToColor.put("blue4", "#00008B");
-        synonymToColor.put("blueviolet", "#8A2BE2");
-        synonymToColor.put("brown", "#A52A2A");
-        synonymToColor.put("brown1", "#FF4040");
-        synonymToColor.put("brown2", "#EE3B3B");
-        synonymToColor.put("brown3", "#CD3333");
-        synonymToColor.put("brown4", "#8B2323");
-        synonymToColor.put("burlywood", "#DEB887");
-        synonymToColor.put("burlywood1", "#FFD39B");
-        synonymToColor.put("burlywood2", "#EEC591");
-        synonymToColor.put("burlywood3", "#CDAA7D");
-        synonymToColor.put("burlywood4", "#8B7355");
-        synonymToColor.put("cadetblue", "#5F9EA0");
-        synonymToColor.put("cadetblue1", "#98F5FF");
-        synonymToColor.put("cadetblue2", "#8EE5EE");
-        synonymToColor.put("cadetblue3", "#7AC5CD");
-        synonymToColor.put("cadetblue4", "#53868B");
-        synonymToColor.put("chartreuse", "#7FFF00");
-        synonymToColor.put("chartreuse1", "#7FFF00");
-        synonymToColor.put("chartreuse2", "#76EE00");
-        synonymToColor.put("chartreuse3", "#66CD00");
-        synonymToColor.put("chartreuse4", "#458B00");
-        synonymToColor.put("chocolate", "#D2691E");
-        synonymToColor.put("chocolate1", "#FF7F24");
-        synonymToColor.put("chocolate2", "#EE7621");
-        synonymToColor.put("chocolate3", "#CD661D");
-        synonymToColor.put("chocolate4", "#8B4513");
-        synonymToColor.put("coral", "#FF7F50");
-        synonymToColor.put("coral1", "#FF7256");
-        synonymToColor.put("coral2", "#EE6A50");
-        synonymToColor.put("coral3", "#CD5B45");
-        synonymToColor.put("coral4", "#8B3E2F");
-        synonymToColor.put("cornflowerblue", "#6495ED");
-        synonymToColor.put("cornsilk", "#FFF8DC");
-        synonymToColor.put("cornsilk1", "#FFF8DC");
-        synonymToColor.put("cornsilk2", "#EEE8CD");
-        synonymToColor.put("cornsilk3", "#CDC8B1");
-        synonymToColor.put("cornsilk4", "#8B8878");
-        synonymToColor.put("cyan", "#00FFFF");
-        synonymToColor.put("cyan1", "#00FFFF");
-        synonymToColor.put("cyan2", "#00EEEE");
-        synonymToColor.put("cyan3", "#00CDCD");
-        synonymToColor.put("cyan4", "#008B8B");
-        synonymToColor.put("darkblue", "#00008B");
-        synonymToColor.put("darkcyan", "#008B8B");
-        synonymToColor.put("darkgoldenrod", "#B8860B");
-        synonymToColor.put("darkgoldenrod1", "#FFB90F");
-        synonymToColor.put("darkgoldenrod2", "#EEAD0E");
-        synonymToColor.put("darkgoldenrod3", "#CD950C");
-        synonymToColor.put("darkgoldenrod4", "#8B6508");
-        synonymToColor.put("darkgray", "#A9A9A9");
-        synonymToColor.put("darkgreen", "#006400");
-        synonymToColor.put("darkgrey", "#A9A9A9");
-        synonymToColor.put("darkkhaki", "#BDB76B");
-        synonymToColor.put("darkmagenta", "#8B008B");
-        synonymToColor.put("darkolivegreen", "#556B2F");
-        synonymToColor.put("darkolivegreen1", "#CAFF70");
-        synonymToColor.put("darkolivegreen2", "#BCEE68");
-        synonymToColor.put("darkolivegreen3", "#A2CD5A");
-        synonymToColor.put("darkolivegreen4", "#6E8B3D");
-        synonymToColor.put("darkorange", "#FF8C00");
-        synonymToColor.put("darkorange1", "#FF7F00");
-        synonymToColor.put("darkorange2", "#EE7600");
-        synonymToColor.put("darkorange3", "#CD6600");
-        synonymToColor.put("darkorange4", "#8B4500");
-        synonymToColor.put("darkorchid", "#9932CC");
-        synonymToColor.put("darkorchid1", "#BF3EFF");
-        synonymToColor.put("darkorchid2", "#B23AEE");
-        synonymToColor.put("darkorchid3", "#9A32CD");
-        synonymToColor.put("darkorchid4", "#68228B");
-        synonymToColor.put("darkred", "#8B0000");
-        synonymToColor.put("darksalmon", "#E9967A");
-        synonymToColor.put("darkseagreen", "#8FBC8F");
-        synonymToColor.put("darkseagreen1", "#C1FFC1");
-        synonymToColor.put("darkseagreen2", "#B4EEB4");
-        synonymToColor.put("darkseagreen3", "#9BCD9B");
-        synonymToColor.put("darkseagreen4", "#698B69");
-        synonymToColor.put("darkslateblue", "#483D8B");
-        synonymToColor.put("darkslategray", "#2F4F4F");
-        synonymToColor.put("darkslategray1", "#97FFFF");
-        synonymToColor.put("darkslategray2", "#8DEEEE");
-        synonymToColor.put("darkslategray3", "#79CDCD");
-        synonymToColor.put("darkslategray4", "#528B8B");
-        synonymToColor.put("darkslategrey", "#2F4F4F");
-        synonymToColor.put("darkturquoise", "#00CED1");
-        synonymToColor.put("darkviolet", "#9400D3");
-        synonymToColor.put("deeppink", "#FF1493");
-        synonymToColor.put("deeppink1", "#FF1493");
-        synonymToColor.put("deeppink2", "#EE1289");
-        synonymToColor.put("deeppink3", "#CD1076");
-        synonymToColor.put("deeppink4", "#8B0A50");
-        synonymToColor.put("deepskyblue", "#00BFFF");
-        synonymToColor.put("deepskyblue1", "#00BFFF");
-        synonymToColor.put("deepskyblue2", "#00B2EE");
-        synonymToColor.put("deepskyblue3", "#009ACD");
-        synonymToColor.put("deepskyblue4", "#00688B");
-        synonymToColor.put("dimgray", "#696969");
-        synonymToColor.put("dimgrey", "#696969");
-        synonymToColor.put("dodgerblue", "#1E90FF");
-        synonymToColor.put("dodgerblue1", "#1E90FF");
-        synonymToColor.put("dodgerblue2", "#1C86EE");
-        synonymToColor.put("dodgerblue3", "#1874CD");
-        synonymToColor.put("dodgerblue4", "#104E8B");
-        synonymToColor.put("firebrick", "#B22222");
-        synonymToColor.put("firebrick1", "#FF3030");
-        synonymToColor.put("firebrick2", "#EE2C2C");
-        synonymToColor.put("firebrick3", "#CD2626");
-        synonymToColor.put("firebrick4", "#8B1A1A");
-        synonymToColor.put("floralwhite", "#FFFAF0");
-        synonymToColor.put("forestgreen", "#228B22");
-        synonymToColor.put("gainsboro", "#DCDCDC");
-        synonymToColor.put("ghostwhite", "#F8F8FF");
-        synonymToColor.put("gold", "#FFD700");
-        synonymToColor.put("gold1", "#FFD700");
-        synonymToColor.put("gold2", "#EEC900");
-        synonymToColor.put("gold3", "#CDAD00");
-        synonymToColor.put("gold4", "#8B7500");
-        synonymToColor.put("goldenrod", "#DAA520");
-        synonymToColor.put("goldenrod1", "#FFC125");
-        synonymToColor.put("goldenrod2", "#EEB422");
-        synonymToColor.put("goldenrod3", "#CD9B1D");
-        synonymToColor.put("goldenrod4", "#8B6914");
-        synonymToColor.put("gray", "#BEBEBE");
-        synonymToColor.put("gray0", "#000000");
-        synonymToColor.put("gray1", "#030303");
-        synonymToColor.put("gray2", "#050505");
-        synonymToColor.put("gray3", "#080808");
-        synonymToColor.put("gray4", "#0A0A0A");
-        synonymToColor.put("gray5", "#0D0D0D");
-        synonymToColor.put("gray6", "#0F0F0F");
-        synonymToColor.put("gray7", "#121212");
-        synonymToColor.put("gray8", "#141414");
-        synonymToColor.put("gray9", "#171717");
-        synonymToColor.put("gray10", "#1A1A1A");
-        synonymToColor.put("gray11", "#1C1C1C");
-        synonymToColor.put("gray12", "#1F1F1F");
-        synonymToColor.put("gray13", "#212121");
-        synonymToColor.put("gray14", "#242424");
-        synonymToColor.put("gray15", "#262626");
-        synonymToColor.put("gray16", "#292929");
-        synonymToColor.put("gray17", "#2B2B2B");
-        synonymToColor.put("gray18", "#2E2E2E");
-        synonymToColor.put("gray19", "#303030");
-        synonymToColor.put("gray20", "#333333");
-        synonymToColor.put("gray21", "#363636");
-        synonymToColor.put("gray22", "#383838");
-        synonymToColor.put("gray23", "#3B3B3B");
-        synonymToColor.put("gray24", "#3D3D3D");
-        synonymToColor.put("gray25", "#404040");
-        synonymToColor.put("gray26", "#424242");
-        synonymToColor.put("gray27", "#454545");
-        synonymToColor.put("gray28", "#474747");
-        synonymToColor.put("gray29", "#4A4A4A");
-        synonymToColor.put("gray30", "#4D4D4D");
-        synonymToColor.put("gray31", "#4F4F4F");
-        synonymToColor.put("gray32", "#525252");
-        synonymToColor.put("gray33", "#545454");
-        synonymToColor.put("gray34", "#575757");
-        synonymToColor.put("gray35", "#595959");
-        synonymToColor.put("gray36", "#5C5C5C");
-        synonymToColor.put("gray37", "#5E5E5E");
-        synonymToColor.put("gray38", "#616161");
-        synonymToColor.put("gray39", "#636363");
-        synonymToColor.put("gray40", "#666666");
-        synonymToColor.put("gray41", "#696969");
-        synonymToColor.put("gray42", "#6B6B6B");
-        synonymToColor.put("gray43", "#6E6E6E");
-        synonymToColor.put("gray44", "#707070");
-        synonymToColor.put("gray45", "#737373");
-        synonymToColor.put("gray46", "#757575");
-        synonymToColor.put("gray47", "#787878");
-        synonymToColor.put("gray48", "#7A7A7A");
-        synonymToColor.put("gray49", "#7D7D7D");
-        synonymToColor.put("gray50", "#7F7F7F");
-        synonymToColor.put("gray51", "#828282");
-        synonymToColor.put("gray52", "#858585");
-        synonymToColor.put("gray53", "#878787");
-        synonymToColor.put("gray54", "#8A8A8A");
-        synonymToColor.put("gray55", "#8C8C8C");
-        synonymToColor.put("gray56", "#8F8F8F");
-        synonymToColor.put("gray57", "#919191");
-        synonymToColor.put("gray58", "#949494");
-        synonymToColor.put("gray59", "#969696");
-        synonymToColor.put("gray60", "#999999");
-        synonymToColor.put("gray61", "#9C9C9C");
-        synonymToColor.put("gray62", "#9E9E9E");
-        synonymToColor.put("gray63", "#A1A1A1");
-        synonymToColor.put("gray64", "#A3A3A3");
-        synonymToColor.put("gray65", "#A6A6A6");
-        synonymToColor.put("gray66", "#A8A8A8");
-        synonymToColor.put("gray67", "#ABABAB");
-        synonymToColor.put("gray68", "#ADADAD");
-        synonymToColor.put("gray69", "#B0B0B0");
-        synonymToColor.put("gray70", "#B3B3B3");
-        synonymToColor.put("gray71", "#B5B5B5");
-        synonymToColor.put("gray72", "#B8B8B8");
-        synonymToColor.put("gray73", "#BABABA");
-        synonymToColor.put("gray74", "#BDBDBD");
-        synonymToColor.put("gray75", "#BFBFBF");
-        synonymToColor.put("gray76", "#C2C2C2");
-        synonymToColor.put("gray77", "#C4C4C4");
-        synonymToColor.put("gray78", "#C7C7C7");
-        synonymToColor.put("gray79", "#C9C9C9");
-        synonymToColor.put("gray80", "#CCCCCC");
-        synonymToColor.put("gray81", "#CFCFCF");
-        synonymToColor.put("gray82", "#D1D1D1");
-        synonymToColor.put("gray83", "#D4D4D4");
-        synonymToColor.put("gray84", "#D6D6D6");
-        synonymToColor.put("gray85", "#D9D9D9");
-        synonymToColor.put("gray86", "#DBDBDB");
-        synonymToColor.put("gray87", "#DEDEDE");
-        synonymToColor.put("gray88", "#E0E0E0");
-        synonymToColor.put("gray89", "#E3E3E3");
-        synonymToColor.put("gray90", "#E5E5E5");
-        synonymToColor.put("gray91", "#E8E8E8");
-        synonymToColor.put("gray92", "#EBEBEB");
-        synonymToColor.put("gray93", "#EDEDED");
-        synonymToColor.put("gray94", "#F0F0F0");
-        synonymToColor.put("gray95", "#F2F2F2");
-        synonymToColor.put("gray96", "#F5F5F5");
-        synonymToColor.put("gray97", "#F7F7F7");
-        synonymToColor.put("gray98", "#FAFAFA");
-        synonymToColor.put("gray99", "#FCFCFC");
-        synonymToColor.put("gray100", "#FFFFFF");
-        synonymToColor.put("green", "#00FF00");
-        synonymToColor.put("green1", "#00FF00");
-        synonymToColor.put("green2", "#00EE00");
-        synonymToColor.put("green3", "#00CD00");
-        synonymToColor.put("green4", "#008B00");
-        synonymToColor.put("greenyellow", "#ADFF2F");
-        synonymToColor.put("grey", "#BEBEBE");
-        synonymToColor.put("grey0", "#000000");
-        synonymToColor.put("grey1", "#030303");
-        synonymToColor.put("grey2", "#050505");
-        synonymToColor.put("grey3", "#080808");
-        synonymToColor.put("grey4", "#0A0A0A");
-        synonymToColor.put("grey5", "#0D0D0D");
-        synonymToColor.put("grey6", "#0F0F0F");
-        synonymToColor.put("grey7", "#121212");
-        synonymToColor.put("grey8", "#141414");
-        synonymToColor.put("grey9", "#171717");
-        synonymToColor.put("grey10", "#1A1A1A");
-        synonymToColor.put("grey11", "#1C1C1C");
-        synonymToColor.put("grey12", "#1F1F1F");
-        synonymToColor.put("grey13", "#212121");
-        synonymToColor.put("grey14", "#242424");
-        synonymToColor.put("grey15", "#262626");
-        synonymToColor.put("grey16", "#292929");
-        synonymToColor.put("grey17", "#2B2B2B");
-        synonymToColor.put("grey18", "#2E2E2E");
-        synonymToColor.put("grey19", "#303030");
-        synonymToColor.put("grey20", "#333333");
-        synonymToColor.put("grey21", "#363636");
-        synonymToColor.put("grey22", "#383838");
-        synonymToColor.put("grey23", "#3B3B3B");
-        synonymToColor.put("grey24", "#3D3D3D");
-        synonymToColor.put("grey25", "#404040");
-        synonymToColor.put("grey26", "#424242");
-        synonymToColor.put("grey27", "#454545");
-        synonymToColor.put("grey28", "#474747");
-        synonymToColor.put("grey29", "#4A4A4A");
-        synonymToColor.put("grey30", "#4D4D4D");
-        synonymToColor.put("grey31", "#4F4F4F");
-        synonymToColor.put("grey32", "#525252");
-        synonymToColor.put("grey33", "#545454");
-        synonymToColor.put("grey34", "#575757");
-        synonymToColor.put("grey35", "#595959");
-        synonymToColor.put("grey36", "#5C5C5C");
-        synonymToColor.put("grey37", "#5E5E5E");
-        synonymToColor.put("grey38", "#616161");
-        synonymToColor.put("grey39", "#636363");
-        synonymToColor.put("grey40", "#666666");
-        synonymToColor.put("grey41", "#696969");
-        synonymToColor.put("grey42", "#6B6B6B");
-        synonymToColor.put("grey43", "#6E6E6E");
-        synonymToColor.put("grey44", "#707070");
-        synonymToColor.put("grey45", "#737373");
-        synonymToColor.put("grey46", "#757575");
-        synonymToColor.put("grey47", "#787878");
-        synonymToColor.put("grey48", "#7A7A7A");
-        synonymToColor.put("grey49", "#7D7D7D");
-        synonymToColor.put("grey50", "#7F7F7F");
-        synonymToColor.put("grey51", "#828282");
-        synonymToColor.put("grey52", "#858585");
-        synonymToColor.put("grey53", "#878787");
-        synonymToColor.put("grey54", "#8A8A8A");
-        synonymToColor.put("grey55", "#8C8C8C");
-        synonymToColor.put("grey56", "#8F8F8F");
-        synonymToColor.put("grey57", "#919191");
-        synonymToColor.put("grey58", "#949494");
-        synonymToColor.put("grey59", "#969696");
-        synonymToColor.put("grey60", "#999999");
-        synonymToColor.put("grey61", "#9C9C9C");
-        synonymToColor.put("grey62", "#9E9E9E");
-        synonymToColor.put("grey63", "#A1A1A1");
-        synonymToColor.put("grey64", "#A3A3A3");
-        synonymToColor.put("grey65", "#A6A6A6");
-        synonymToColor.put("grey66", "#A8A8A8");
-        synonymToColor.put("grey67", "#ABABAB");
-        synonymToColor.put("grey68", "#ADADAD");
-        synonymToColor.put("grey69", "#B0B0B0");
-        synonymToColor.put("grey70", "#B3B3B3");
-        synonymToColor.put("grey71", "#B5B5B5");
-        synonymToColor.put("grey72", "#B8B8B8");
-        synonymToColor.put("grey73", "#BABABA");
-        synonymToColor.put("grey74", "#BDBDBD");
-        synonymToColor.put("grey75", "#BFBFBF");
-        synonymToColor.put("grey76", "#C2C2C2");
-        synonymToColor.put("grey77", "#C4C4C4");
-        synonymToColor.put("grey78", "#C7C7C7");
-        synonymToColor.put("grey79", "#C9C9C9");
-        synonymToColor.put("grey80", "#CCCCCC");
-        synonymToColor.put("grey81", "#CFCFCF");
-        synonymToColor.put("grey82", "#D1D1D1");
-        synonymToColor.put("grey83", "#D4D4D4");
-        synonymToColor.put("grey84", "#D6D6D6");
-        synonymToColor.put("grey85", "#D9D9D9");
-        synonymToColor.put("grey86", "#DBDBDB");
-        synonymToColor.put("grey87", "#DEDEDE");
-        synonymToColor.put("grey88", "#E0E0E0");
-        synonymToColor.put("grey89", "#E3E3E3");
-        synonymToColor.put("grey90", "#E5E5E5");
-        synonymToColor.put("grey91", "#E8E8E8");
-        synonymToColor.put("grey92", "#EBEBEB");
-        synonymToColor.put("grey93", "#EDEDED");
-        synonymToColor.put("grey94", "#F0F0F0");
-        synonymToColor.put("grey95", "#F2F2F2");
-        synonymToColor.put("grey96", "#F5F5F5");
-        synonymToColor.put("grey97", "#F7F7F7");
-        synonymToColor.put("grey98", "#FAFAFA");
-        synonymToColor.put("grey99", "#FCFCFC");
-        synonymToColor.put("grey100", "#FFFFFF");
-        synonymToColor.put("honeydew", "#F0FFF0");
-        synonymToColor.put("honeydew1", "#F0FFF0");
-        synonymToColor.put("honeydew2", "#E0EEE0");
-        synonymToColor.put("honeydew3", "#C1CDC1");
-        synonymToColor.put("honeydew4", "#838B83");
-        synonymToColor.put("hotpink", "#FF69B4");
-        synonymToColor.put("hotpink1", "#FF6EB4");
-        synonymToColor.put("hotpink2", "#EE6AA7");
-        synonymToColor.put("hotpink3", "#CD6090");
-        synonymToColor.put("hotpink4", "#8B3A62");
-        synonymToColor.put("indianred", "#CD5C5C");
-        synonymToColor.put("indianred1", "#FF6A6A");
-        synonymToColor.put("indianred2", "#EE6363");
-        synonymToColor.put("indianred3", "#CD5555");
-        synonymToColor.put("indianred4", "#8B3A3A");
-        synonymToColor.put("ivory", "#FFFFF0");
-        synonymToColor.put("ivory1", "#FFFFF0");
-        synonymToColor.put("ivory2", "#EEEEE0");
-        synonymToColor.put("ivory3", "#CDCDC1");
-        synonymToColor.put("ivory4", "#8B8B83");
-        synonymToColor.put("khaki", "#F0E68C");
-        synonymToColor.put("khaki1", "#FFF68F");
-        synonymToColor.put("khaki2", "#EEE685");
-        synonymToColor.put("khaki3", "#CDC673");
-        synonymToColor.put("khaki4", "#8B864E");
-        synonymToColor.put("lavender", "#E6E6FA");
-        synonymToColor.put("lavenderblush", "#FFF0F5");
-        synonymToColor.put("lavenderblush1", "#FFF0F5");
-        synonymToColor.put("lavenderblush2", "#EEE0E5");
-        synonymToColor.put("lavenderblush3", "#CDC1C5");
-        synonymToColor.put("lavenderblush4", "#8B8386");
-        synonymToColor.put("lawngreen", "#7CFC00");
-        synonymToColor.put("lemonchiffon", "#FFFACD");
-        synonymToColor.put("lemonchiffon1", "#FFFACD");
-        synonymToColor.put("lemonchiffon2", "#EEE9BF");
-        synonymToColor.put("lemonchiffon3", "#CDC9A5");
-        synonymToColor.put("lemonchiffon4", "#8B8970");
-        synonymToColor.put("lightblue", "#ADD8E6");
-        synonymToColor.put("lightblue1", "#BFEFFF");
-        synonymToColor.put("lightblue2", "#B2DFEE");
-        synonymToColor.put("lightblue3", "#9AC0CD");
-        synonymToColor.put("lightblue4", "#68838B");
-        synonymToColor.put("lightcoral", "#F08080");
-        synonymToColor.put("lightcyan", "#E0FFFF");
-        synonymToColor.put("lightcyan1", "#E0FFFF");
-        synonymToColor.put("lightcyan2", "#D1EEEE");
-        synonymToColor.put("lightcyan3", "#B4CDCD");
-        synonymToColor.put("lightcyan4", "#7A8B8B");
-        synonymToColor.put("lightgoldenrod", "#EEDD82");
-        synonymToColor.put("lightgoldenrod1", "#FFEC8B");
-        synonymToColor.put("lightgoldenrod2", "#EEDC82");
-        synonymToColor.put("lightgoldenrod3", "#CDBE70");
-        synonymToColor.put("lightgoldenrod4", "#8B814C");
-        synonymToColor.put("lightgoldenrodyellow", "#FAFAD2");
-        synonymToColor.put("lightgray", "#D3D3D3");
-        synonymToColor.put("lightgreen", "#90EE90");
-        synonymToColor.put("lightgrey", "#D3D3D3");
-        synonymToColor.put("lightpink", "#FFB6C1");
-        synonymToColor.put("lightpink1", "#FFAEB9");
-        synonymToColor.put("lightpink2", "#EEA2AD");
-        synonymToColor.put("lightpink3", "#CD8C95");
-        synonymToColor.put("lightpink4", "#8B5F65");
-        synonymToColor.put("lightsalmon", "#FFA07A");
-        synonymToColor.put("lightsalmon1", "#FFA07A");
-        synonymToColor.put("lightsalmon2", "#EE9572");
-        synonymToColor.put("lightsalmon3", "#CD8162");
-        synonymToColor.put("lightsalmon4", "#8B5742");
-        synonymToColor.put("lightseagreen", "#20B2AA");
-        synonymToColor.put("lightskyblue", "#87CEFA");
-        synonymToColor.put("lightskyblue1", "#B0E2FF");
-        synonymToColor.put("lightskyblue2", "#A4D3EE");
-        synonymToColor.put("lightskyblue3", "#8DB6CD");
-        synonymToColor.put("lightskyblue4", "#607B8B");
-        synonymToColor.put("lightslateblue", "#8470FF");
-        synonymToColor.put("lightslategray", "#778899");
-        synonymToColor.put("lightslategrey", "#778899");
-        synonymToColor.put("lightsteelblue", "#B0C4DE");
-        synonymToColor.put("lightsteelblue1", "#CAE1FF");
-        synonymToColor.put("lightsteelblue2", "#BCD2EE");
-        synonymToColor.put("lightsteelblue3", "#A2B5CD");
-        synonymToColor.put("lightsteelblue4", "#6E7B8B");
-        synonymToColor.put("lightyellow", "#FFFFE0");
-        synonymToColor.put("lightyellow1", "#FFFFE0");
-        synonymToColor.put("lightyellow2", "#EEEED1");
-        synonymToColor.put("lightyellow3", "#CDCDB4");
-        synonymToColor.put("lightyellow4", "#8B8B7A");
-        synonymToColor.put("limegreen", "#32CD32");
-        synonymToColor.put("linen", "#FAF0E6");
-        synonymToColor.put("magenta", "#FF00FF");
-        synonymToColor.put("magenta1", "#FF00FF");
-        synonymToColor.put("magenta2", "#EE00EE");
-        synonymToColor.put("magenta3", "#CD00CD");
-        synonymToColor.put("magenta4", "#8B008B");
-        synonymToColor.put("maroon", "#B03060");
-        synonymToColor.put("maroon1", "#FF34B3");
-        synonymToColor.put("maroon2", "#EE30A7");
-        synonymToColor.put("maroon3", "#CD2990");
-        synonymToColor.put("maroon4", "#8B1C62");
-        synonymToColor.put("mediumaquamarine", "#66CDAA");
-        synonymToColor.put("mediumblue", "#0000CD");
-        synonymToColor.put("mediumorchid", "#BA55D3");
-        synonymToColor.put("mediumorchid1", "#E066FF");
-        synonymToColor.put("mediumorchid2", "#D15FEE");
-        synonymToColor.put("mediumorchid3", "#B452CD");
-        synonymToColor.put("mediumorchid4", "#7A378B");
-        synonymToColor.put("mediumpurple", "#9370DB");
-        synonymToColor.put("mediumpurple1", "#AB82FF");
-        synonymToColor.put("mediumpurple2", "#9F79EE");
-        synonymToColor.put("mediumpurple3", "#8968CD");
-        synonymToColor.put("mediumpurple4", "#5D478B");
-        synonymToColor.put("mediumseagreen", "#3CB371");
-        synonymToColor.put("mediumslateblue", "#7B68EE");
-        synonymToColor.put("mediumspringgreen", "#00FA9A");
-        synonymToColor.put("mediumturquoise", "#48D1CC");
-        synonymToColor.put("mediumvioletred", "#C71585");
-        synonymToColor.put("midnightblue", "#191970");
-        synonymToColor.put("mintcream", "#F5FFFA");
-        synonymToColor.put("mistyrose", "#FFE4E1");
-        synonymToColor.put("mistyrose1", "#FFE4E1");
-        synonymToColor.put("mistyrose2", "#EED5D2");
-        synonymToColor.put("mistyrose3", "#CDB7B5");
-        synonymToColor.put("mistyrose4", "#8B7D7B");
-        synonymToColor.put("moccasin", "#FFE4B5");
-        synonymToColor.put("navajowhite", "#FFDEAD");
-        synonymToColor.put("navajowhite1", "#FFDEAD");
-        synonymToColor.put("navajowhite2", "#EECFA1");
-        synonymToColor.put("navajowhite3", "#CDB38B");
-        synonymToColor.put("navajowhite4", "#8B795E");
-        synonymToColor.put("navy", "#000080");
-        synonymToColor.put("navyblue", "#000080");
-        synonymToColor.put("oldlace", "#FDF5E6");
-        synonymToColor.put("olivedrab", "#6B8E23");
-        synonymToColor.put("olivedrab1", "#C0FF3E");
-        synonymToColor.put("olivedrab2", "#B3EE3A");
-        synonymToColor.put("olivedrab3", "#9ACD32");
-        synonymToColor.put("olivedrab4", "#698B22");
-        synonymToColor.put("orange", "#FFA500");
-        synonymToColor.put("orange1", "#FFA500");
-        synonymToColor.put("orange2", "#EE9A00");
-        synonymToColor.put("orange3", "#CD8500");
-        synonymToColor.put("orange4", "#8B5A00");
-        synonymToColor.put("orangered", "#FF4500");
-        synonymToColor.put("orangered1", "#FF4500");
-        synonymToColor.put("orangered2", "#EE4000");
-        synonymToColor.put("orangered3", "#CD3700");
-        synonymToColor.put("orangered4", "#8B2500");
-        synonymToColor.put("orchid", "#DA70D6");
-        synonymToColor.put("orchid1", "#FF83FA");
-        synonymToColor.put("orchid2", "#EE7AE9");
-        synonymToColor.put("orchid3", "#CD69C9");
-        synonymToColor.put("orchid4", "#8B4789");
-        synonymToColor.put("palegoldenrod", "#EEE8AA");
-        synonymToColor.put("palegreen", "#98FB98");
-        synonymToColor.put("palegreen1", "#9AFF9A");
-        synonymToColor.put("palegreen2", "#90EE90");
-        synonymToColor.put("palegreen3", "#7CCD7C");
-        synonymToColor.put("palegreen4", "#548B54");
-        synonymToColor.put("paleturquoise", "#AFEEEE");
-        synonymToColor.put("paleturquoise1", "#BBFFFF");
-        synonymToColor.put("paleturquoise2", "#AEEEEE");
-        synonymToColor.put("paleturquoise3", "#96CDCD");
-        synonymToColor.put("paleturquoise4", "#668B8B");
-        synonymToColor.put("palevioletred", "#DB7093");
-        synonymToColor.put("palevioletred1", "#FF82AB");
-        synonymToColor.put("palevioletred2", "#EE799F");
-        synonymToColor.put("palevioletred3", "#CD6889");
-        synonymToColor.put("palevioletred4", "#8B475D");
-        synonymToColor.put("papayawhip", "#FFEFD5");
-        synonymToColor.put("peachpuff", "#FFDAB9");
-        synonymToColor.put("peachpuff1", "#FFDAB9");
-        synonymToColor.put("peachpuff2", "#EECBAD");
-        synonymToColor.put("peachpuff3", "#CDAF95");
-        synonymToColor.put("peachpuff4", "#8B7765");
-        synonymToColor.put("peru", "#CD853F");
-        synonymToColor.put("pink", "#FFC0CB");
-        synonymToColor.put("pink1", "#FFB5C5");
-        synonymToColor.put("pink2", "#EEA9B8");
-        synonymToColor.put("pink3", "#CD919E");
-        synonymToColor.put("pink4", "#8B636C");
-        synonymToColor.put("plum", "#DDA0DD");
-        synonymToColor.put("plum1", "#FFBBFF");
-        synonymToColor.put("plum2", "#EEAEEE");
-        synonymToColor.put("plum3", "#CD96CD");
-        synonymToColor.put("plum4", "#8B668B");
-        synonymToColor.put("powderblue", "#B0E0E6");
-        synonymToColor.put("purple", "#A020F0");
-        synonymToColor.put("purple1", "#9B30FF");
-        synonymToColor.put("purple2", "#912CEE");
-        synonymToColor.put("purple3", "#7D26CD");
-        synonymToColor.put("purple4", "#551A8B");
-        synonymToColor.put("red", "#FF0000");
-        synonymToColor.put("red1", "#FF0000");
-        synonymToColor.put("red2", "#EE0000");
-        synonymToColor.put("red3", "#CD0000");
-        synonymToColor.put("red4", "#8B0000");
-        synonymToColor.put("rosybrown", "#BC8F8F");
-        synonymToColor.put("rosybrown1", "#FFC1C1");
-        synonymToColor.put("rosybrown2", "#EEB4B4");
-        synonymToColor.put("rosybrown3", "#CD9B9B");
-        synonymToColor.put("rosybrown4", "#8B6969");
-        synonymToColor.put("royalblue", "#4169E1");
-        synonymToColor.put("royalblue1", "#4876FF");
-        synonymToColor.put("royalblue2", "#436EEE");
-        synonymToColor.put("royalblue3", "#3A5FCD");
-        synonymToColor.put("royalblue4", "#27408B");
-        synonymToColor.put("snewData.addlebrown", "#8B4513");
-        synonymToColor.put("salmon", "#FA8072");
-        synonymToColor.put("salmon1", "#FF8C69");
-        synonymToColor.put("salmon2", "#EE8262");
-        synonymToColor.put("salmon3", "#CD7054");
-        synonymToColor.put("salmon4", "#8B4C39");
-        synonymToColor.put("sandybrown", "#F4A460");
-        synonymToColor.put("seagreen", "#2E8B57");
-        synonymToColor.put("seagreen1", "#54FF9F");
-        synonymToColor.put("seagreen2", "#4EEE94");
-        synonymToColor.put("seagreen3", "#43CD80");
-        synonymToColor.put("seagreen4", "#2E8B57");
-        synonymToColor.put("seashell", "#FFF5EE");
-        synonymToColor.put("seashell1", "#FFF5EE");
-        synonymToColor.put("seashell2", "#EEE5DE");
-        synonymToColor.put("seashell3", "#CDC5BF");
-        synonymToColor.put("seashell4", "#8B8682");
-        synonymToColor.put("sienna", "#A0522D");
-        synonymToColor.put("sienna1", "#FF8247");
-        synonymToColor.put("sienna2", "#EE7942");
-        synonymToColor.put("sienna3", "#CD6839");
-        synonymToColor.put("sienna4", "#8B4726");
-        synonymToColor.put("skyblue", "#87CEEB");
-        synonymToColor.put("skyblue1", "#87CEFF");
-        synonymToColor.put("skyblue2", "#7EC0EE");
-        synonymToColor.put("skyblue3", "#6CA6CD");
-        synonymToColor.put("skyblue4", "#4A708B");
-        synonymToColor.put("slateblue", "#6A5ACD");
-        synonymToColor.put("slateblue1", "#836FFF");
-        synonymToColor.put("slateblue2", "#7A67EE");
-        synonymToColor.put("slateblue3", "#6959CD");
-        synonymToColor.put("slateblue4", "#473C8B");
-        synonymToColor.put("slategray", "#708090");
-        synonymToColor.put("slategray1", "#C6E2FF");
-        synonymToColor.put("slategray2", "#B9D3EE");
-        synonymToColor.put("slategray3", "#9FB6CD");
-        synonymToColor.put("slategray4", "#6C7B8B");
-        synonymToColor.put("slategrey", "#708090");
-        synonymToColor.put("snow", "#FFFAFA");
-        synonymToColor.put("snow1", "#FFFAFA");
-        synonymToColor.put("snow2", "#EEE9E9");
-        synonymToColor.put("snow3", "#CDC9C9");
-        synonymToColor.put("snow4", "#8B8989");
-        synonymToColor.put("springgreen", "#00FF7F");
-        synonymToColor.put("springgreen1", "#00FF7F");
-        synonymToColor.put("springgreen2", "#00EE76");
-        synonymToColor.put("springgreen3", "#00CD66");
-        synonymToColor.put("springgreen4", "#008B45");
-        synonymToColor.put("steelblue", "#4682B4");
-        synonymToColor.put("steelblue1", "#63B8FF");
-        synonymToColor.put("steelblue2", "#5CACEE");
-        synonymToColor.put("steelblue3", "#4F94CD");
-        synonymToColor.put("steelblue4", "#36648B");
-        synonymToColor.put("tan", "#D2B48C");
-        synonymToColor.put("tan1", "#FFA54F");
-        synonymToColor.put("tan2", "#EE9A49");
-        synonymToColor.put("tan3", "#CD853F");
-        synonymToColor.put("tan4", "#8B5A2B");
-        synonymToColor.put("thistle", "#D8BFD8");
-        synonymToColor.put("thistle1", "#FFE1FF");
-        synonymToColor.put("thistle2", "#EED2EE");
-        synonymToColor.put("thistle3", "#CDB5CD");
-        synonymToColor.put("thistle4", "#8B7B8B");
-        synonymToColor.put("tomato", "#FF6347");
-        synonymToColor.put("tomato1", "#FF6347");
-        synonymToColor.put("tomato2", "#EE5C42");
-        synonymToColor.put("tomato3", "#CD4F39");
-        synonymToColor.put("tomato4", "#8B3626");
-        synonymToColor.put("turquoise", "#40E0D0");
-        synonymToColor.put("turquoise1", "#00F5FF");
-        synonymToColor.put("turquoise2", "#00E5EE");
-        synonymToColor.put("turquoise3", "#00C5CD");
-        synonymToColor.put("turquoise4", "#00868B");
-        synonymToColor.put("violet", "#EE82EE");
-        synonymToColor.put("violetred", "#D02090");
-        synonymToColor.put("violetred1", "#FF3E96");
-        synonymToColor.put("violetred2", "#EE3A8C");
-        synonymToColor.put("violetred3", "#CD3278");
-        synonymToColor.put("violetred4", "#8B2252");
-        synonymToColor.put("wheat", "#F5DEB3");
-        synonymToColor.put("wheat1", "#FFE7BA");
-        synonymToColor.put("wheat2", "#EED8AE");
-        synonymToColor.put("wheat3", "#CDBA96");
-        synonymToColor.put("wheat4", "#8B7E66");
-        synonymToColor.put("whitesmoke", "#F5F5F5");
-        synonymToColor.put("yellow", "#FFFF00");
-        synonymToColor.put("yellow1", "#FFFF00");
-        synonymToColor.put("yellow2", "#EEEE00");
-        synonymToColor.put("yellow3", "#CDCD00");
-        synonymToColor.put("yellow4", "#8B8B00");
-        synonymToColor.put("yellowgreen", "#9ACD32");
+    private static final class NamesHolder {
+        private static final HashMap<String, Object> NAMES = new HashMap<>(700);
+
+        static {
+            NAMES.put("transparent", GridColor.TRANSPARENT);
+            NAMES.put("NA", GridColor.TRANSPARENT);
+            NAMES.put("white", "#FFFFFF");
+            NAMES.put("aliceblue", "#F0F8FF");
+            NAMES.put("antiquewhite", "#FAEBD7");
+            NAMES.put("antiquewhite1", "#FFEFDB");
+            NAMES.put("antiquewhite2", "#EEDFCC");
+            NAMES.put("antiquewhite3", "#CDC0B0");
+            NAMES.put("antiquewhite4", "#8B8378");
+            NAMES.put("aquamarine", "#7FFFD4");
+            NAMES.put("aquamarine1", "#7FFFD4");
+            NAMES.put("aquamarine2", "#76EEC6");
+            NAMES.put("aquamarine3", "#66CDAA");
+            NAMES.put("aquamarine4", "#458B74");
+            NAMES.put("azure", "#F0FFFF");
+            NAMES.put("azure1", "#F0FFFF");
+            NAMES.put("azure2", "#E0EEEE");
+            NAMES.put("azure3", "#C1CDCD");
+            NAMES.put("azure4", "#838B8B");
+            NAMES.put("beige", "#F5F5DC");
+            NAMES.put("bisque", "#FFE4C4");
+            NAMES.put("bisque1", "#FFE4C4");
+            NAMES.put("bisque2", "#EED5B7");
+            NAMES.put("bisque3", "#CDB79E");
+            NAMES.put("bisque4", "#8B7D6B");
+            NAMES.put("black", "#000000");
+            NAMES.put("blanchedalmond", "#FFEBCD");
+            NAMES.put("blue", "#0000FF");
+            NAMES.put("blue1", "#0000FF");
+            NAMES.put("blue2", "#0000EE");
+            NAMES.put("blue3", "#0000CD");
+            NAMES.put("blue4", "#00008B");
+            NAMES.put("blueviolet", "#8A2BE2");
+            NAMES.put("brown", "#A52A2A");
+            NAMES.put("brown1", "#FF4040");
+            NAMES.put("brown2", "#EE3B3B");
+            NAMES.put("brown3", "#CD3333");
+            NAMES.put("brown4", "#8B2323");
+            NAMES.put("burlywood", "#DEB887");
+            NAMES.put("burlywood1", "#FFD39B");
+            NAMES.put("burlywood2", "#EEC591");
+            NAMES.put("burlywood3", "#CDAA7D");
+            NAMES.put("burlywood4", "#8B7355");
+            NAMES.put("cadetblue", "#5F9EA0");
+            NAMES.put("cadetblue1", "#98F5FF");
+            NAMES.put("cadetblue2", "#8EE5EE");
+            NAMES.put("cadetblue3", "#7AC5CD");
+            NAMES.put("cadetblue4", "#53868B");
+            NAMES.put("chartreuse", "#7FFF00");
+            NAMES.put("chartreuse1", "#7FFF00");
+            NAMES.put("chartreuse2", "#76EE00");
+            NAMES.put("chartreuse3", "#66CD00");
+            NAMES.put("chartreuse4", "#458B00");
+            NAMES.put("chocolate", "#D2691E");
+            NAMES.put("chocolate1", "#FF7F24");
+            NAMES.put("chocolate2", "#EE7621");
+            NAMES.put("chocolate3", "#CD661D");
+            NAMES.put("chocolate4", "#8B4513");
+            NAMES.put("coral", "#FF7F50");
+            NAMES.put("coral1", "#FF7256");
+            NAMES.put("coral2", "#EE6A50");
+            NAMES.put("coral3", "#CD5B45");
+            NAMES.put("coral4", "#8B3E2F");
+            NAMES.put("cornflowerblue", "#6495ED");
+            NAMES.put("cornsilk", "#FFF8DC");
+            NAMES.put("cornsilk1", "#FFF8DC");
+            NAMES.put("cornsilk2", "#EEE8CD");
+            NAMES.put("cornsilk3", "#CDC8B1");
+            NAMES.put("cornsilk4", "#8B8878");
+            NAMES.put("cyan", "#00FFFF");
+            NAMES.put("cyan1", "#00FFFF");
+            NAMES.put("cyan2", "#00EEEE");
+            NAMES.put("cyan3", "#00CDCD");
+            NAMES.put("cyan4", "#008B8B");
+            NAMES.put("darkblue", "#00008B");
+            NAMES.put("darkcyan", "#008B8B");
+            NAMES.put("darkgoldenrod", "#B8860B");
+            NAMES.put("darkgoldenrod1", "#FFB90F");
+            NAMES.put("darkgoldenrod2", "#EEAD0E");
+            NAMES.put("darkgoldenrod3", "#CD950C");
+            NAMES.put("darkgoldenrod4", "#8B6508");
+            NAMES.put("darkgray", "#A9A9A9");
+            NAMES.put("darkgreen", "#006400");
+            NAMES.put("darkgrey", "#A9A9A9");
+            NAMES.put("darkkhaki", "#BDB76B");
+            NAMES.put("darkmagenta", "#8B008B");
+            NAMES.put("darkolivegreen", "#556B2F");
+            NAMES.put("darkolivegreen1", "#CAFF70");
+            NAMES.put("darkolivegreen2", "#BCEE68");
+            NAMES.put("darkolivegreen3", "#A2CD5A");
+            NAMES.put("darkolivegreen4", "#6E8B3D");
+            NAMES.put("darkorange", "#FF8C00");
+            NAMES.put("darkorange1", "#FF7F00");
+            NAMES.put("darkorange2", "#EE7600");
+            NAMES.put("darkorange3", "#CD6600");
+            NAMES.put("darkorange4", "#8B4500");
+            NAMES.put("darkorchid", "#9932CC");
+            NAMES.put("darkorchid1", "#BF3EFF");
+            NAMES.put("darkorchid2", "#B23AEE");
+            NAMES.put("darkorchid3", "#9A32CD");
+            NAMES.put("darkorchid4", "#68228B");
+            NAMES.put("darkred", "#8B0000");
+            NAMES.put("darksalmon", "#E9967A");
+            NAMES.put("darkseagreen", "#8FBC8F");
+            NAMES.put("darkseagreen1", "#C1FFC1");
+            NAMES.put("darkseagreen2", "#B4EEB4");
+            NAMES.put("darkseagreen3", "#9BCD9B");
+            NAMES.put("darkseagreen4", "#698B69");
+            NAMES.put("darkslateblue", "#483D8B");
+            NAMES.put("darkslategray", "#2F4F4F");
+            NAMES.put("darkslategray1", "#97FFFF");
+            NAMES.put("darkslategray2", "#8DEEEE");
+            NAMES.put("darkslategray3", "#79CDCD");
+            NAMES.put("darkslategray4", "#528B8B");
+            NAMES.put("darkslategrey", "#2F4F4F");
+            NAMES.put("darkturquoise", "#00CED1");
+            NAMES.put("darkviolet", "#9400D3");
+            NAMES.put("deeppink", "#FF1493");
+            NAMES.put("deeppink1", "#FF1493");
+            NAMES.put("deeppink2", "#EE1289");
+            NAMES.put("deeppink3", "#CD1076");
+            NAMES.put("deeppink4", "#8B0A50");
+            NAMES.put("deepskyblue", "#00BFFF");
+            NAMES.put("deepskyblue1", "#00BFFF");
+            NAMES.put("deepskyblue2", "#00B2EE");
+            NAMES.put("deepskyblue3", "#009ACD");
+            NAMES.put("deepskyblue4", "#00688B");
+            NAMES.put("dimgray", "#696969");
+            NAMES.put("dimgrey", "#696969");
+            NAMES.put("dodgerblue", "#1E90FF");
+            NAMES.put("dodgerblue1", "#1E90FF");
+            NAMES.put("dodgerblue2", "#1C86EE");
+            NAMES.put("dodgerblue3", "#1874CD");
+            NAMES.put("dodgerblue4", "#104E8B");
+            NAMES.put("firebrick", "#B22222");
+            NAMES.put("firebrick1", "#FF3030");
+            NAMES.put("firebrick2", "#EE2C2C");
+            NAMES.put("firebrick3", "#CD2626");
+            NAMES.put("firebrick4", "#8B1A1A");
+            NAMES.put("floralwhite", "#FFFAF0");
+            NAMES.put("forestgreen", "#228B22");
+            NAMES.put("gainsboro", "#DCDCDC");
+            NAMES.put("ghostwhite", "#F8F8FF");
+            NAMES.put("gold", "#FFD700");
+            NAMES.put("gold1", "#FFD700");
+            NAMES.put("gold2", "#EEC900");
+            NAMES.put("gold3", "#CDAD00");
+            NAMES.put("gold4", "#8B7500");
+            NAMES.put("goldenrod", "#DAA520");
+            NAMES.put("goldenrod1", "#FFC125");
+            NAMES.put("goldenrod2", "#EEB422");
+            NAMES.put("goldenrod3", "#CD9B1D");
+            NAMES.put("goldenrod4", "#8B6914");
+            NAMES.put("gray", "#BEBEBE");
+            NAMES.put("gray0", "#000000");
+            NAMES.put("gray1", "#030303");
+            NAMES.put("gray2", "#050505");
+            NAMES.put("gray3", "#080808");
+            NAMES.put("gray4", "#0A0A0A");
+            NAMES.put("gray5", "#0D0D0D");
+            NAMES.put("gray6", "#0F0F0F");
+            NAMES.put("gray7", "#121212");
+            NAMES.put("gray8", "#141414");
+            NAMES.put("gray9", "#171717");
+            NAMES.put("gray10", "#1A1A1A");
+            NAMES.put("gray11", "#1C1C1C");
+            NAMES.put("gray12", "#1F1F1F");
+            NAMES.put("gray13", "#212121");
+            NAMES.put("gray14", "#242424");
+            NAMES.put("gray15", "#262626");
+            NAMES.put("gray16", "#292929");
+            NAMES.put("gray17", "#2B2B2B");
+            NAMES.put("gray18", "#2E2E2E");
+            NAMES.put("gray19", "#303030");
+            NAMES.put("gray20", "#333333");
+            NAMES.put("gray21", "#363636");
+            NAMES.put("gray22", "#383838");
+            NAMES.put("gray23", "#3B3B3B");
+            NAMES.put("gray24", "#3D3D3D");
+            NAMES.put("gray25", "#404040");
+            NAMES.put("gray26", "#424242");
+            NAMES.put("gray27", "#454545");
+            NAMES.put("gray28", "#474747");
+            NAMES.put("gray29", "#4A4A4A");
+            NAMES.put("gray30", "#4D4D4D");
+            NAMES.put("gray31", "#4F4F4F");
+            NAMES.put("gray32", "#525252");
+            NAMES.put("gray33", "#545454");
+            NAMES.put("gray34", "#575757");
+            NAMES.put("gray35", "#595959");
+            NAMES.put("gray36", "#5C5C5C");
+            NAMES.put("gray37", "#5E5E5E");
+            NAMES.put("gray38", "#616161");
+            NAMES.put("gray39", "#636363");
+            NAMES.put("gray40", "#666666");
+            NAMES.put("gray41", "#696969");
+            NAMES.put("gray42", "#6B6B6B");
+            NAMES.put("gray43", "#6E6E6E");
+            NAMES.put("gray44", "#707070");
+            NAMES.put("gray45", "#737373");
+            NAMES.put("gray46", "#757575");
+            NAMES.put("gray47", "#787878");
+            NAMES.put("gray48", "#7A7A7A");
+            NAMES.put("gray49", "#7D7D7D");
+            NAMES.put("gray50", "#7F7F7F");
+            NAMES.put("gray51", "#828282");
+            NAMES.put("gray52", "#858585");
+            NAMES.put("gray53", "#878787");
+            NAMES.put("gray54", "#8A8A8A");
+            NAMES.put("gray55", "#8C8C8C");
+            NAMES.put("gray56", "#8F8F8F");
+            NAMES.put("gray57", "#919191");
+            NAMES.put("gray58", "#949494");
+            NAMES.put("gray59", "#969696");
+            NAMES.put("gray60", "#999999");
+            NAMES.put("gray61", "#9C9C9C");
+            NAMES.put("gray62", "#9E9E9E");
+            NAMES.put("gray63", "#A1A1A1");
+            NAMES.put("gray64", "#A3A3A3");
+            NAMES.put("gray65", "#A6A6A6");
+            NAMES.put("gray66", "#A8A8A8");
+            NAMES.put("gray67", "#ABABAB");
+            NAMES.put("gray68", "#ADADAD");
+            NAMES.put("gray69", "#B0B0B0");
+            NAMES.put("gray70", "#B3B3B3");
+            NAMES.put("gray71", "#B5B5B5");
+            NAMES.put("gray72", "#B8B8B8");
+            NAMES.put("gray73", "#BABABA");
+            NAMES.put("gray74", "#BDBDBD");
+            NAMES.put("gray75", "#BFBFBF");
+            NAMES.put("gray76", "#C2C2C2");
+            NAMES.put("gray77", "#C4C4C4");
+            NAMES.put("gray78", "#C7C7C7");
+            NAMES.put("gray79", "#C9C9C9");
+            NAMES.put("gray80", "#CCCCCC");
+            NAMES.put("gray81", "#CFCFCF");
+            NAMES.put("gray82", "#D1D1D1");
+            NAMES.put("gray83", "#D4D4D4");
+            NAMES.put("gray84", "#D6D6D6");
+            NAMES.put("gray85", "#D9D9D9");
+            NAMES.put("gray86", "#DBDBDB");
+            NAMES.put("gray87", "#DEDEDE");
+            NAMES.put("gray88", "#E0E0E0");
+            NAMES.put("gray89", "#E3E3E3");
+            NAMES.put("gray90", "#E5E5E5");
+            NAMES.put("gray91", "#E8E8E8");
+            NAMES.put("gray92", "#EBEBEB");
+            NAMES.put("gray93", "#EDEDED");
+            NAMES.put("gray94", "#F0F0F0");
+            NAMES.put("gray95", "#F2F2F2");
+            NAMES.put("gray96", "#F5F5F5");
+            NAMES.put("gray97", "#F7F7F7");
+            NAMES.put("gray98", "#FAFAFA");
+            NAMES.put("gray99", "#FCFCFC");
+            NAMES.put("gray100", "#FFFFFF");
+            NAMES.put("green", "#00FF00");
+            NAMES.put("green1", "#00FF00");
+            NAMES.put("green2", "#00EE00");
+            NAMES.put("green3", "#00CD00");
+            NAMES.put("green4", "#008B00");
+            NAMES.put("greenyellow", "#ADFF2F");
+            NAMES.put("grey", "#BEBEBE");
+            NAMES.put("grey0", "#000000");
+            NAMES.put("grey1", "#030303");
+            NAMES.put("grey2", "#050505");
+            NAMES.put("grey3", "#080808");
+            NAMES.put("grey4", "#0A0A0A");
+            NAMES.put("grey5", "#0D0D0D");
+            NAMES.put("grey6", "#0F0F0F");
+            NAMES.put("grey7", "#121212");
+            NAMES.put("grey8", "#141414");
+            NAMES.put("grey9", "#171717");
+            NAMES.put("grey10", "#1A1A1A");
+            NAMES.put("grey11", "#1C1C1C");
+            NAMES.put("grey12", "#1F1F1F");
+            NAMES.put("grey13", "#212121");
+            NAMES.put("grey14", "#242424");
+            NAMES.put("grey15", "#262626");
+            NAMES.put("grey16", "#292929");
+            NAMES.put("grey17", "#2B2B2B");
+            NAMES.put("grey18", "#2E2E2E");
+            NAMES.put("grey19", "#303030");
+            NAMES.put("grey20", "#333333");
+            NAMES.put("grey21", "#363636");
+            NAMES.put("grey22", "#383838");
+            NAMES.put("grey23", "#3B3B3B");
+            NAMES.put("grey24", "#3D3D3D");
+            NAMES.put("grey25", "#404040");
+            NAMES.put("grey26", "#424242");
+            NAMES.put("grey27", "#454545");
+            NAMES.put("grey28", "#474747");
+            NAMES.put("grey29", "#4A4A4A");
+            NAMES.put("grey30", "#4D4D4D");
+            NAMES.put("grey31", "#4F4F4F");
+            NAMES.put("grey32", "#525252");
+            NAMES.put("grey33", "#545454");
+            NAMES.put("grey34", "#575757");
+            NAMES.put("grey35", "#595959");
+            NAMES.put("grey36", "#5C5C5C");
+            NAMES.put("grey37", "#5E5E5E");
+            NAMES.put("grey38", "#616161");
+            NAMES.put("grey39", "#636363");
+            NAMES.put("grey40", "#666666");
+            NAMES.put("grey41", "#696969");
+            NAMES.put("grey42", "#6B6B6B");
+            NAMES.put("grey43", "#6E6E6E");
+            NAMES.put("grey44", "#707070");
+            NAMES.put("grey45", "#737373");
+            NAMES.put("grey46", "#757575");
+            NAMES.put("grey47", "#787878");
+            NAMES.put("grey48", "#7A7A7A");
+            NAMES.put("grey49", "#7D7D7D");
+            NAMES.put("grey50", "#7F7F7F");
+            NAMES.put("grey51", "#828282");
+            NAMES.put("grey52", "#858585");
+            NAMES.put("grey53", "#878787");
+            NAMES.put("grey54", "#8A8A8A");
+            NAMES.put("grey55", "#8C8C8C");
+            NAMES.put("grey56", "#8F8F8F");
+            NAMES.put("grey57", "#919191");
+            NAMES.put("grey58", "#949494");
+            NAMES.put("grey59", "#969696");
+            NAMES.put("grey60", "#999999");
+            NAMES.put("grey61", "#9C9C9C");
+            NAMES.put("grey62", "#9E9E9E");
+            NAMES.put("grey63", "#A1A1A1");
+            NAMES.put("grey64", "#A3A3A3");
+            NAMES.put("grey65", "#A6A6A6");
+            NAMES.put("grey66", "#A8A8A8");
+            NAMES.put("grey67", "#ABABAB");
+            NAMES.put("grey68", "#ADADAD");
+            NAMES.put("grey69", "#B0B0B0");
+            NAMES.put("grey70", "#B3B3B3");
+            NAMES.put("grey71", "#B5B5B5");
+            NAMES.put("grey72", "#B8B8B8");
+            NAMES.put("grey73", "#BABABA");
+            NAMES.put("grey74", "#BDBDBD");
+            NAMES.put("grey75", "#BFBFBF");
+            NAMES.put("grey76", "#C2C2C2");
+            NAMES.put("grey77", "#C4C4C4");
+            NAMES.put("grey78", "#C7C7C7");
+            NAMES.put("grey79", "#C9C9C9");
+            NAMES.put("grey80", "#CCCCCC");
+            NAMES.put("grey81", "#CFCFCF");
+            NAMES.put("grey82", "#D1D1D1");
+            NAMES.put("grey83", "#D4D4D4");
+            NAMES.put("grey84", "#D6D6D6");
+            NAMES.put("grey85", "#D9D9D9");
+            NAMES.put("grey86", "#DBDBDB");
+            NAMES.put("grey87", "#DEDEDE");
+            NAMES.put("grey88", "#E0E0E0");
+            NAMES.put("grey89", "#E3E3E3");
+            NAMES.put("grey90", "#E5E5E5");
+            NAMES.put("grey91", "#E8E8E8");
+            NAMES.put("grey92", "#EBEBEB");
+            NAMES.put("grey93", "#EDEDED");
+            NAMES.put("grey94", "#F0F0F0");
+            NAMES.put("grey95", "#F2F2F2");
+            NAMES.put("grey96", "#F5F5F5");
+            NAMES.put("grey97", "#F7F7F7");
+            NAMES.put("grey98", "#FAFAFA");
+            NAMES.put("grey99", "#FCFCFC");
+            NAMES.put("grey100", "#FFFFFF");
+            NAMES.put("honeydew", "#F0FFF0");
+            NAMES.put("honeydew1", "#F0FFF0");
+            NAMES.put("honeydew2", "#E0EEE0");
+            NAMES.put("honeydew3", "#C1CDC1");
+            NAMES.put("honeydew4", "#838B83");
+            NAMES.put("hotpink", "#FF69B4");
+            NAMES.put("hotpink1", "#FF6EB4");
+            NAMES.put("hotpink2", "#EE6AA7");
+            NAMES.put("hotpink3", "#CD6090");
+            NAMES.put("hotpink4", "#8B3A62");
+            NAMES.put("indianred", "#CD5C5C");
+            NAMES.put("indianred1", "#FF6A6A");
+            NAMES.put("indianred2", "#EE6363");
+            NAMES.put("indianred3", "#CD5555");
+            NAMES.put("indianred4", "#8B3A3A");
+            NAMES.put("ivory", "#FFFFF0");
+            NAMES.put("ivory1", "#FFFFF0");
+            NAMES.put("ivory2", "#EEEEE0");
+            NAMES.put("ivory3", "#CDCDC1");
+            NAMES.put("ivory4", "#8B8B83");
+            NAMES.put("khaki", "#F0E68C");
+            NAMES.put("khaki1", "#FFF68F");
+            NAMES.put("khaki2", "#EEE685");
+            NAMES.put("khaki3", "#CDC673");
+            NAMES.put("khaki4", "#8B864E");
+            NAMES.put("lavender", "#E6E6FA");
+            NAMES.put("lavenderblush", "#FFF0F5");
+            NAMES.put("lavenderblush1", "#FFF0F5");
+            NAMES.put("lavenderblush2", "#EEE0E5");
+            NAMES.put("lavenderblush3", "#CDC1C5");
+            NAMES.put("lavenderblush4", "#8B8386");
+            NAMES.put("lawngreen", "#7CFC00");
+            NAMES.put("lemonchiffon", "#FFFACD");
+            NAMES.put("lemonchiffon1", "#FFFACD");
+            NAMES.put("lemonchiffon2", "#EEE9BF");
+            NAMES.put("lemonchiffon3", "#CDC9A5");
+            NAMES.put("lemonchiffon4", "#8B8970");
+            NAMES.put("lightblue", "#ADD8E6");
+            NAMES.put("lightblue1", "#BFEFFF");
+            NAMES.put("lightblue2", "#B2DFEE");
+            NAMES.put("lightblue3", "#9AC0CD");
+            NAMES.put("lightblue4", "#68838B");
+            NAMES.put("lightcoral", "#F08080");
+            NAMES.put("lightcyan", "#E0FFFF");
+            NAMES.put("lightcyan1", "#E0FFFF");
+            NAMES.put("lightcyan2", "#D1EEEE");
+            NAMES.put("lightcyan3", "#B4CDCD");
+            NAMES.put("lightcyan4", "#7A8B8B");
+            NAMES.put("lightgoldenrod", "#EEDD82");
+            NAMES.put("lightgoldenrod1", "#FFEC8B");
+            NAMES.put("lightgoldenrod2", "#EEDC82");
+            NAMES.put("lightgoldenrod3", "#CDBE70");
+            NAMES.put("lightgoldenrod4", "#8B814C");
+            NAMES.put("lightgoldenrodyellow", "#FAFAD2");
+            NAMES.put("lightgray", "#D3D3D3");
+            NAMES.put("lightgreen", "#90EE90");
+            NAMES.put("lightgrey", "#D3D3D3");
+            NAMES.put("lightpink", "#FFB6C1");
+            NAMES.put("lightpink1", "#FFAEB9");
+            NAMES.put("lightpink2", "#EEA2AD");
+            NAMES.put("lightpink3", "#CD8C95");
+            NAMES.put("lightpink4", "#8B5F65");
+            NAMES.put("lightsalmon", "#FFA07A");
+            NAMES.put("lightsalmon1", "#FFA07A");
+            NAMES.put("lightsalmon2", "#EE9572");
+            NAMES.put("lightsalmon3", "#CD8162");
+            NAMES.put("lightsalmon4", "#8B5742");
+            NAMES.put("lightseagreen", "#20B2AA");
+            NAMES.put("lightskyblue", "#87CEFA");
+            NAMES.put("lightskyblue1", "#B0E2FF");
+            NAMES.put("lightskyblue2", "#A4D3EE");
+            NAMES.put("lightskyblue3", "#8DB6CD");
+            NAMES.put("lightskyblue4", "#607B8B");
+            NAMES.put("lightslateblue", "#8470FF");
+            NAMES.put("lightslategray", "#778899");
+            NAMES.put("lightslategrey", "#778899");
+            NAMES.put("lightsteelblue", "#B0C4DE");
+            NAMES.put("lightsteelblue1", "#CAE1FF");
+            NAMES.put("lightsteelblue2", "#BCD2EE");
+            NAMES.put("lightsteelblue3", "#A2B5CD");
+            NAMES.put("lightsteelblue4", "#6E7B8B");
+            NAMES.put("lightyellow", "#FFFFE0");
+            NAMES.put("lightyellow1", "#FFFFE0");
+            NAMES.put("lightyellow2", "#EEEED1");
+            NAMES.put("lightyellow3", "#CDCDB4");
+            NAMES.put("lightyellow4", "#8B8B7A");
+            NAMES.put("limegreen", "#32CD32");
+            NAMES.put("linen", "#FAF0E6");
+            NAMES.put("magenta", "#FF00FF");
+            NAMES.put("magenta1", "#FF00FF");
+            NAMES.put("magenta2", "#EE00EE");
+            NAMES.put("magenta3", "#CD00CD");
+            NAMES.put("magenta4", "#8B008B");
+            NAMES.put("maroon", "#B03060");
+            NAMES.put("maroon1", "#FF34B3");
+            NAMES.put("maroon2", "#EE30A7");
+            NAMES.put("maroon3", "#CD2990");
+            NAMES.put("maroon4", "#8B1C62");
+            NAMES.put("mediumaquamarine", "#66CDAA");
+            NAMES.put("mediumblue", "#0000CD");
+            NAMES.put("mediumorchid", "#BA55D3");
+            NAMES.put("mediumorchid1", "#E066FF");
+            NAMES.put("mediumorchid2", "#D15FEE");
+            NAMES.put("mediumorchid3", "#B452CD");
+            NAMES.put("mediumorchid4", "#7A378B");
+            NAMES.put("mediumpurple", "#9370DB");
+            NAMES.put("mediumpurple1", "#AB82FF");
+            NAMES.put("mediumpurple2", "#9F79EE");
+            NAMES.put("mediumpurple3", "#8968CD");
+            NAMES.put("mediumpurple4", "#5D478B");
+            NAMES.put("mediumseagreen", "#3CB371");
+            NAMES.put("mediumslateblue", "#7B68EE");
+            NAMES.put("mediumspringgreen", "#00FA9A");
+            NAMES.put("mediumturquoise", "#48D1CC");
+            NAMES.put("mediumvioletred", "#C71585");
+            NAMES.put("midnightblue", "#191970");
+            NAMES.put("mintcream", "#F5FFFA");
+            NAMES.put("mistyrose", "#FFE4E1");
+            NAMES.put("mistyrose1", "#FFE4E1");
+            NAMES.put("mistyrose2", "#EED5D2");
+            NAMES.put("mistyrose3", "#CDB7B5");
+            NAMES.put("mistyrose4", "#8B7D7B");
+            NAMES.put("moccasin", "#FFE4B5");
+            NAMES.put("navajowhite", "#FFDEAD");
+            NAMES.put("navajowhite1", "#FFDEAD");
+            NAMES.put("navajowhite2", "#EECFA1");
+            NAMES.put("navajowhite3", "#CDB38B");
+            NAMES.put("navajowhite4", "#8B795E");
+            NAMES.put("navy", "#000080");
+            NAMES.put("navyblue", "#000080");
+            NAMES.put("oldlace", "#FDF5E6");
+            NAMES.put("olivedrab", "#6B8E23");
+            NAMES.put("olivedrab1", "#C0FF3E");
+            NAMES.put("olivedrab2", "#B3EE3A");
+            NAMES.put("olivedrab3", "#9ACD32");
+            NAMES.put("olivedrab4", "#698B22");
+            NAMES.put("orange", "#FFA500");
+            NAMES.put("orange1", "#FFA500");
+            NAMES.put("orange2", "#EE9A00");
+            NAMES.put("orange3", "#CD8500");
+            NAMES.put("orange4", "#8B5A00");
+            NAMES.put("orangered", "#FF4500");
+            NAMES.put("orangered1", "#FF4500");
+            NAMES.put("orangered2", "#EE4000");
+            NAMES.put("orangered3", "#CD3700");
+            NAMES.put("orangered4", "#8B2500");
+            NAMES.put("orchid", "#DA70D6");
+            NAMES.put("orchid1", "#FF83FA");
+            NAMES.put("orchid2", "#EE7AE9");
+            NAMES.put("orchid3", "#CD69C9");
+            NAMES.put("orchid4", "#8B4789");
+            NAMES.put("palegoldenrod", "#EEE8AA");
+            NAMES.put("palegreen", "#98FB98");
+            NAMES.put("palegreen1", "#9AFF9A");
+            NAMES.put("palegreen2", "#90EE90");
+            NAMES.put("palegreen3", "#7CCD7C");
+            NAMES.put("palegreen4", "#548B54");
+            NAMES.put("paleturquoise", "#AFEEEE");
+            NAMES.put("paleturquoise1", "#BBFFFF");
+            NAMES.put("paleturquoise2", "#AEEEEE");
+            NAMES.put("paleturquoise3", "#96CDCD");
+            NAMES.put("paleturquoise4", "#668B8B");
+            NAMES.put("palevioletred", "#DB7093");
+            NAMES.put("palevioletred1", "#FF82AB");
+            NAMES.put("palevioletred2", "#EE799F");
+            NAMES.put("palevioletred3", "#CD6889");
+            NAMES.put("palevioletred4", "#8B475D");
+            NAMES.put("papayawhip", "#FFEFD5");
+            NAMES.put("peachpuff", "#FFDAB9");
+            NAMES.put("peachpuff1", "#FFDAB9");
+            NAMES.put("peachpuff2", "#EECBAD");
+            NAMES.put("peachpuff3", "#CDAF95");
+            NAMES.put("peachpuff4", "#8B7765");
+            NAMES.put("peru", "#CD853F");
+            NAMES.put("pink", "#FFC0CB");
+            NAMES.put("pink1", "#FFB5C5");
+            NAMES.put("pink2", "#EEA9B8");
+            NAMES.put("pink3", "#CD919E");
+            NAMES.put("pink4", "#8B636C");
+            NAMES.put("plum", "#DDA0DD");
+            NAMES.put("plum1", "#FFBBFF");
+            NAMES.put("plum2", "#EEAEEE");
+            NAMES.put("plum3", "#CD96CD");
+            NAMES.put("plum4", "#8B668B");
+            NAMES.put("powderblue", "#B0E0E6");
+            NAMES.put("purple", "#A020F0");
+            NAMES.put("purple1", "#9B30FF");
+            NAMES.put("purple2", "#912CEE");
+            NAMES.put("purple3", "#7D26CD");
+            NAMES.put("purple4", "#551A8B");
+            NAMES.put("red", "#FF0000");
+            NAMES.put("red1", "#FF0000");
+            NAMES.put("red2", "#EE0000");
+            NAMES.put("red3", "#CD0000");
+            NAMES.put("red4", "#8B0000");
+            NAMES.put("rosybrown", "#BC8F8F");
+            NAMES.put("rosybrown1", "#FFC1C1");
+            NAMES.put("rosybrown2", "#EEB4B4");
+            NAMES.put("rosybrown3", "#CD9B9B");
+            NAMES.put("rosybrown4", "#8B6969");
+            NAMES.put("royalblue", "#4169E1");
+            NAMES.put("royalblue1", "#4876FF");
+            NAMES.put("royalblue2", "#436EEE");
+            NAMES.put("royalblue3", "#3A5FCD");
+            NAMES.put("royalblue4", "#27408B");
+            NAMES.put("snewData.addlebrown", "#8B4513");
+            NAMES.put("salmon", "#FA8072");
+            NAMES.put("salmon1", "#FF8C69");
+            NAMES.put("salmon2", "#EE8262");
+            NAMES.put("salmon3", "#CD7054");
+            NAMES.put("salmon4", "#8B4C39");
+            NAMES.put("sandybrown", "#F4A460");
+            NAMES.put("seagreen", "#2E8B57");
+            NAMES.put("seagreen1", "#54FF9F");
+            NAMES.put("seagreen2", "#4EEE94");
+            NAMES.put("seagreen3", "#43CD80");
+            NAMES.put("seagreen4", "#2E8B57");
+            NAMES.put("seashell", "#FFF5EE");
+            NAMES.put("seashell1", "#FFF5EE");
+            NAMES.put("seashell2", "#EEE5DE");
+            NAMES.put("seashell3", "#CDC5BF");
+            NAMES.put("seashell4", "#8B8682");
+            NAMES.put("sienna", "#A0522D");
+            NAMES.put("sienna1", "#FF8247");
+            NAMES.put("sienna2", "#EE7942");
+            NAMES.put("sienna3", "#CD6839");
+            NAMES.put("sienna4", "#8B4726");
+            NAMES.put("skyblue", "#87CEEB");
+            NAMES.put("skyblue1", "#87CEFF");
+            NAMES.put("skyblue2", "#7EC0EE");
+            NAMES.put("skyblue3", "#6CA6CD");
+            NAMES.put("skyblue4", "#4A708B");
+            NAMES.put("slateblue", "#6A5ACD");
+            NAMES.put("slateblue1", "#836FFF");
+            NAMES.put("slateblue2", "#7A67EE");
+            NAMES.put("slateblue3", "#6959CD");
+            NAMES.put("slateblue4", "#473C8B");
+            NAMES.put("slategray", "#708090");
+            NAMES.put("slategray1", "#C6E2FF");
+            NAMES.put("slategray2", "#B9D3EE");
+            NAMES.put("slategray3", "#9FB6CD");
+            NAMES.put("slategray4", "#6C7B8B");
+            NAMES.put("slategrey", "#708090");
+            NAMES.put("snow", "#FFFAFA");
+            NAMES.put("snow1", "#FFFAFA");
+            NAMES.put("snow2", "#EEE9E9");
+            NAMES.put("snow3", "#CDC9C9");
+            NAMES.put("snow4", "#8B8989");
+            NAMES.put("springgreen", "#00FF7F");
+            NAMES.put("springgreen1", "#00FF7F");
+            NAMES.put("springgreen2", "#00EE76");
+            NAMES.put("springgreen3", "#00CD66");
+            NAMES.put("springgreen4", "#008B45");
+            NAMES.put("steelblue", "#4682B4");
+            NAMES.put("steelblue1", "#63B8FF");
+            NAMES.put("steelblue2", "#5CACEE");
+            NAMES.put("steelblue3", "#4F94CD");
+            NAMES.put("steelblue4", "#36648B");
+            NAMES.put("tan", "#D2B48C");
+            NAMES.put("tan1", "#FFA54F");
+            NAMES.put("tan2", "#EE9A49");
+            NAMES.put("tan3", "#CD853F");
+            NAMES.put("tan4", "#8B5A2B");
+            NAMES.put("thistle", "#D8BFD8");
+            NAMES.put("thistle1", "#FFE1FF");
+            NAMES.put("thistle2", "#EED2EE");
+            NAMES.put("thistle3", "#CDB5CD");
+            NAMES.put("thistle4", "#8B7B8B");
+            NAMES.put("tomato", "#FF6347");
+            NAMES.put("tomato1", "#FF6347");
+            NAMES.put("tomato2", "#EE5C42");
+            NAMES.put("tomato3", "#CD4F39");
+            NAMES.put("tomato4", "#8B3626");
+            NAMES.put("turquoise", "#40E0D0");
+            NAMES.put("turquoise1", "#00F5FF");
+            NAMES.put("turquoise2", "#00E5EE");
+            NAMES.put("turquoise3", "#00C5CD");
+            NAMES.put("turquoise4", "#00868B");
+            NAMES.put("violet", "#EE82EE");
+            NAMES.put("violetred", "#D02090");
+            NAMES.put("violetred1", "#FF3E96");
+            NAMES.put("violetred2", "#EE3A8C");
+            NAMES.put("violetred3", "#CD3278");
+            NAMES.put("violetred4", "#8B2252");
+            NAMES.put("wheat", "#F5DEB3");
+            NAMES.put("wheat1", "#FFE7BA");
+            NAMES.put("wheat2", "#EED8AE");
+            NAMES.put("wheat3", "#CDBA96");
+            NAMES.put("wheat4", "#8B7E66");
+            NAMES.put("whitesmoke", "#F5F5F5");
+            NAMES.put("yellow", "#FFFF00");
+            NAMES.put("yellow1", "#FFFF00");
+            NAMES.put("yellow2", "#EEEE00");
+            NAMES.put("yellow3", "#CDCD00");
+            NAMES.put("yellow4", "#8B8B00");
+            NAMES.put("yellowgreen", "#9ACD32");
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
new file mode 100644
index 0000000000..e7d405b43f
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
@@ -0,0 +1,116 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+
+import java.util.HashMap;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+/**
+ * External builtin that converts the string representation of a unit, e.g. "cm", to internal
+ * numerical value. This values are then stored in special attribute "valid.unit".
+ */
+public abstract class LValidUnit extends RExternalBuiltinNode.Arg1 {
+    static {
+        Casts casts = new Casts(LValidUnit.class);
+        casts.arg(0).mustBe(stringValue(), Message.GENERIC, "'units' must be character").asStringVector().mustBe(notEmpty(), Message.GENERIC, "'units' must be of length > 0");
+    }
+
+    public static LValidUnit create() {
+        return LValidUnitNodeGen.create();
+    }
+
+    @Specialization
+    RIntVector convert(RAbstractStringVector units) {
+        int[] result = new int[units.getLength()];
+        for (int i = 0; i < units.getLength(); i++) {
+            result[i] = convertSingle(units.getDataAt(i));
+        }
+        return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
+    }
+
+    protected int convertSingle(String name) {
+        if (name.equals("npc")) {
+            // seems to be by far the most common unit
+            return Unit.NPC;
+        }
+        return convertSingleSlowPath(name);
+    }
+
+    @TruffleBoundary
+    private int convertSingleSlowPath(String name) {
+        Integer result = NamesHolder.NAMES.get(name);
+        if (result == null) {
+            error(Message.GENERIC, "invalid unit");
+        }
+        return result;
+    }
+
+    private static final class NamesHolder {
+        private static final HashMap<String, Integer> NAMES = new HashMap<>(30);
+        static {
+            NAMES.put("npc", Unit.NPC);
+            NAMES.put("cm", Unit.CM);
+            NAMES.put("inches", Unit.INCHES);
+            NAMES.put("lines", Unit.LINES);
+            NAMES.put("native", Unit.NATIVE);
+            NAMES.put("null", Unit.NULL);
+            NAMES.put("snpc", Unit.SNPC);
+            NAMES.put("mm", Unit.MM);
+            NAMES.put("points", Unit.POINTS);
+            NAMES.put("picas", Unit.PICAS);
+            NAMES.put("bigpts", Unit.BIGPOINTS);
+            NAMES.put("dida", Unit.DIDA);
+            NAMES.put("cicero", Unit.CICERO);
+            NAMES.put("scaledpts", Unit.SCALEDPOINTS);
+            NAMES.put("strwidth", Unit.STRINGWIDTH);
+            NAMES.put("strheight", Unit.STRINGHEIGHT);
+            NAMES.put("strascent", Unit.STRINGASCENT);
+            NAMES.put("strdescent", Unit.STRINGDESCENT);
+
+            NAMES.put("char", Unit.CHAR);
+            NAMES.put("grobx", Unit.GROBX);
+            NAMES.put("groby", Unit.GROBY);
+            NAMES.put("grobwidth", Unit.GROBWIDTH);
+            NAMES.put("grobheight", Unit.GROBHEIGHT);
+            NAMES.put("grobascent", Unit.GROBASCENT);
+            NAMES.put("grobdescent", Unit.GROBDESCENT);
+            NAMES.put("mylines", Unit.MYLINES);
+            NAMES.put("mychar", Unit.MYCHAR);
+            NAMES.put("mystrwidth", Unit.MYSTRINGWIDTH);
+            NAMES.put("mystrheight", Unit.MYSTRINGHEIGHT);
+            // Some pseudonyms
+            NAMES.put("centimetre", Unit.CM);
+            NAMES.put("centimetres", Unit.CM);
+            NAMES.put("centimeter", Unit.CM);
+            NAMES.put("centimeters", Unit.CM);
+            NAMES.put("in", Unit.INCHES);
+            NAMES.put("inch", Unit.INCHES);
+            NAMES.put("line", Unit.LINES);
+            NAMES.put("millimetre", Unit.MM);
+            NAMES.put("millimetres", Unit.MM);
+            NAMES.put("millimeter", Unit.MM);
+            NAMES.put("millimeters", Unit.MM);
+            NAMES.put("point", Unit.POINTS);
+            NAMES.put("pt", Unit.POINTS);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 2eccf77f90..295d97a42e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -63,17 +63,17 @@ public final class Unit {
     static final String VALID_UNIT_ATTR = "valid.unit";
 
     public static final int NPC = 0;
-    private static final int CM = 1;
+    public static final int CM = 1;
     public static final int INCHES = 2;
-    private static final int LINES = 3;
+    public static final int LINES = 3;
     public static final int NATIVE = 4;
-    private static final int NULL = 5; /* only used in layout specifications */
-    private static final int SNPC = 6;
-    private static final int MM = 7;
+    public static final int NULL = 5; /* only used in layout specifications */
+    public static final int SNPC = 6;
+    public static final int MM = 7;
     /*
      * Some units based on TeX's definition thereof
      */
-    private static final int POINTS = 8; /* 72.27 pt = 1 in */
+    public static final int POINTS = 8; /* 72.27 pt = 1 in */
     public static final int PICAS = 9; /* 1 pc = 12 pt */
     public static final int BIGPOINTS = 10; /* 72 bp = 1 in */
     public static final int DIDA = 11; /* 1157 dd = 1238 pt */
@@ -82,28 +82,28 @@ public final class Unit {
     /*
      * Some units which require an object to query for a value.
      */
-    private static final int STRINGWIDTH = 14;
-    private static final int STRINGHEIGHT = 15;
+    public static final int STRINGWIDTH = 14;
+    public static final int STRINGHEIGHT = 15;
     public static final int STRINGASCENT = 16;
     public static final int STRINGDESCENT = 17;
     /*
      * LINES now means multiples of the line height. This is multiples of the font size.
      */
-    private static final int CHAR = 18;
-    private static final int GROBX = 19;
-    private static final int GROBY = 20;
-    private static final int GROBWIDTH = 21;
-    private static final int GROBHEIGHT = 22;
+    public static final int CHAR = 18;
+    public static final int GROBX = 19;
+    public static final int GROBY = 20;
+    public static final int GROBWIDTH = 21;
+    public static final int GROBHEIGHT = 22;
     public static final int GROBASCENT = 23;
-    private static final int GROBDESCENT = 24;
+    public static final int GROBDESCENT = 24;
     private static final int LAST_NORMAL_UNIT = GROBDESCENT;
     /*
      * No longer used
      */
-    private static final int MYLINES = 103;
-    private static final int MYCHAR = 104;
-    private static final int MYSTRINGWIDTH = 105;
-    private static final int MYSTRINGHEIGHT = 106;
+    public static final int MYLINES = 103;
+    public static final int MYCHAR = 104;
+    public static final int MYSTRINGWIDTH = 105;
+    public static final int MYSTRINGHEIGHT = 106;
 
     // null layout arithmetic mode
     private static final int L_adding = 1;
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index a09bd8bac8..fca7942c32 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -757,6 +757,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetVi
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java,gnu_r_murrel_core.copyright
-- 
GitLab


From ac616fa90c013ad0159279affcac684c3ba9f053 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 31 Mar 2017 17:04:19 +0200
Subject: [PATCH 219/402] FastR Grid: implement L_downvppath

---
 .../fastrGrid/FastRGridExternalLookup.java    |  1 +
 .../truffle/r/library/fastrGrid/fastrGrid.R   | 45 ++++++++++++++-----
 2 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index e8711d0537..80d6a41600 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -99,6 +99,7 @@ public final class FastRGridExternalLookup {
                 return LUnsetViewPort.create();
             case "L_setviewport":
             case "L_downviewport":
+            case "L_downvppath":
                 return getExternalFastRGridBuiltinNode(name);
 
             // Drawing primitives
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index 30a16598ea..e41d42f3be 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -1,26 +1,44 @@
+#
+# This material is distributed under the GNU General Public License
+# Version 2. You may review the terms of this license at
+# http://www.gnu.org/licenses/gpl-2.0.html
+#
+# Copyright (C) 2001-3 Paul Murrell
+# Copyright (c) 1998-2015, The R Core Team
+# Copyright (c) 2017, Oracle and/or its affiliates
+#
+# All rights reserved.
+#
+
+# This file contains internal R helper functions that are invoked from grid externals implementations.
+# Where original grid implementation uses many Rf_eval calls to call back to R, we rewrite the whole
+# logic to R. Some functions implement whole externals, like L_downvppath, some implement coherent
+# parts of the logic and the rest is in Java.
 
 # Returns list with elements [[1]] - depth, zero if not found, [[2]] - the viewport, NULL if not found
-find.viewport <- function(name, strict, pvp, depth) {
+# We are searching for child "name" in "pvp", if the "path" is not missing,
+# then also pathMatch(path, currPath) must hold.
+find.viewport <- function(path, name, strict, currPath, pvp, depth) {
     if (length(ls(env=pvp$children)) == 0) {
         return(list(FALSE, NULL))
-    } else if (exists(name, env=pvp$children, inherits=FALSE)) {
+    } else if (exists(name, env=pvp$children, inherits=FALSE) && (missing(path) || grid:::pathMatch(path, currPath, strict))) {
         return(list(depth, get(name, env=pvp$children, inherits=FALSE)))
-    } else if (strict) {
+    } else if (strict && missing(path)) {
         return(list(FALSE, NULL))
     } else {
-        return(find.in.children(name, pvp$children, depth + 1L))
+        return(find.in.children(path, name, strict, currPath, pvp$children, depth + 1L))
     }
 }
 
-# Note: in GnuR this takes "strict" from find.viewport and forwards it to recursive calls to find.viewport,
-# however, strict must be constant FALSE if find.in.children is called, so we leave it out.
-find.in.children <- function(name, children, depth) {
+find.in.children <- function(path, name, strict, currPath, children, depth) {
   cpvps <- ls(env=children)
   ncpvp <- length(cpvps)
   count <- 0L
   found <- FALSE
   while (count < ncpvp && !found) {
-    result <- find.viewport(name, FALSE, get(cpvps[count + 1L], env=children), depth)
+    child <- get(cpvps[count + 1L], env=children)
+    nextCurrPath <- if (missing(path)) NULL else grid:::growPath(currPath, child$name)
+    result <- find.viewport(path, name, strict, nextCurrPath, child, depth)
     if (result[[1L]]) {
         return(result);
     }
@@ -29,9 +47,11 @@ find.in.children <- function(name, children, depth) {
   list(FALSE, NULL) # not found
 }
 
-L_downviewport <- function(name, strict) {
+# path is a string, e.g. "A::B::C", or NULL if we are not searching for particular path
+# name is a string, the name of child we are looking for
+L_downvppath <- function(path, name, strict) {
     currVp <- .Call(grid:::L_currentViewport)
-    result <- find.viewport(name, strict, currVp, 1L);
+    result <- find.viewport(path, name, strict, NULL, currVp, 1L);
     if (result[[1]]) {
         .Internal(.fastr.grid.doSetViewPort(result[[2L]], FALSE, FALSE));
         return(result[[1L]])
@@ -40,6 +60,11 @@ L_downviewport <- function(name, strict) {
     }
 }
 
+L_downviewport <- function(name, strict) {
+    # note: first argument is "missing"
+    L_downvppath(, name, strict)
+}
+
 L_setviewport <- function(vp, hasParent) {
     pushedVP <- grid:::pushedvp(vp);
     .Internal(.fastr.grid.doSetViewPort(pushedVP, hasParent, TRUE));
-- 
GitLab


From f5e70eee418d2e51d436e6cb89402a5dc1050f13 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 16 Feb 2017 13:18:55 -0800
Subject: [PATCH 220/402] implement RFFI for Truffle NFI

---
 ci.hocon                                      |    8 +
 .../r/engine/interop/UnsafeAdapter.java       |    4 +-
 .../interop/ffi/nfi/TruffleNFI_Base.java      |  395 +++++
 .../interop/ffi/nfi/TruffleNFI_CAccess.java   |   75 +
 .../interop/ffi/nfi/TruffleNFI_Call.java      |  466 ++++++
 .../interop/ffi/nfi/TruffleNFI_DLL.java       |  119 ++
 .../interop/ffi/nfi/TruffleNFI_Lapack.java    |  318 ++++
 .../ffi/nfi/TruffleNFI_NativeArray.java       |  168 +++
 .../interop/ffi/nfi/TruffleNFI_PCRE.java      |  214 +++
 .../interop/ffi/nfi/TruffleNFI_PkgInit.java   |  158 ++
 .../interop/ffi/nfi/TruffleNFI_RAppl.java     |  146 ++
 .../ffi/nfi/TruffleNFI_RFFIFactory.java       |  168 +++
 .../interop/ffi/nfi/TruffleNFI_Stats.java     |  108 ++
 .../interop/ffi/nfi/TruffleNFI_Tools.java     |   99 ++
 .../ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java   |  100 ++
 .../interop/ffi/nfi/TruffleNFI_UserRng.java   |  124 ++
 .../interop/ffi/nfi/TruffleNFI_Utils.java     |  119 ++
 .../interop/ffi/nfi/TruffleNFI_Zip.java       |  103 ++
 com.oracle.truffle.r.native/Makefile          |    4 +
 com.oracle.truffle.r.native/fficall/Makefile  |   60 +-
 .../fficall/src/caccess/Makefile              |   34 +
 .../fficall/src/caccess/caccess.c             |   38 +
 .../fficall/src/truffle_nfi/Makefile          |   63 +
 .../fficall/src/truffle_nfi/Memory.c          |  123 ++
 .../fficall/src/truffle_nfi/Rdynload_fastr.c  |  134 ++
 .../fficall/src/truffle_nfi/Rembedded.c       |   29 +
 .../fficall/src/truffle_nfi/Riconv.c          |   39 +
 .../fficall/src/truffle_nfi/Rinternals.c      | 1281 +++++++++++++++++
 .../fficall/src/truffle_nfi/Rmath.c           |  704 +++++++++
 .../fficall/src/truffle_nfi/Utils.c           |   44 +
 .../fficall/src/truffle_nfi/appl_rffi.c       |   40 +
 .../fficall/src/truffle_nfi/base_rffi.c       |   71 +
 .../fficall/src/truffle_nfi/call_rffi.c.not   |   26 +
 .../fficall/src/truffle_nfi/lapack_rffi.c     |  128 ++
 .../fficall/src/truffle_nfi/pcre_rffi.c       |   65 +
 .../fficall/src/truffle_nfi/rffi_callbacks.h  |  409 ++++++
 .../fficall/src/truffle_nfi/rffiutils.h       |   35 +
 .../fficall/src/truffle_nfi/variables.c       |  390 +++++
 .../gnur/Makefile.gnur                        |    4 +-
 com.oracle.truffle.r.native/library/lib.mk    |    6 +-
 .../library/tools/Makefile                    |   23 +-
 .../library/tools/src/{ => jni}/gramRd_jni.c  |    4 +-
 .../tools/src/truffle_nfi/gramRd_nfi.c        |   33 +
 com.oracle.truffle.r.native/version.source    |    2 +-
 .../r/nodes/builtin/base/LaFunctions.java     |    1 +
 .../r/runtime/ffi/generic/Generic_Tools.java  |    6 +-
 .../com/oracle/truffle/r/runtime/ffi/DLL.java |    6 +-
 .../truffle/r/runtime/ffi/RFFIFactory.java    |    2 +-
 com.oracle.truffle.r.test.native/Makefile     |    4 +
 .../test/tools/RFFIUpCallMethodGenerate.java  |   33 +-
 documentation/dev/ffi.md                      |   12 +-
 mx.fastr/copyrights/overrides                 |    3 +
 mx.fastr/mx_fastr.py                          |    2 +-
 mx.fastr/mx_fastr_dists.py                    |   68 -
 mx.fastr/suite.py                             |   40 +-
 55 files changed, 6717 insertions(+), 141 deletions(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java
 create mode 100644 com.oracle.truffle.r.native/fficall/src/caccess/Makefile
 create mode 100644 com.oracle.truffle.r.native/fficall/src/caccess/caccess.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
 rename com.oracle.truffle.r.native/library/tools/src/{ => jni}/gramRd_jni.c (94%)
 create mode 100644 com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c

diff --git a/ci.hocon b/ci.hocon
index 94646dd855..b49df18470 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -106,6 +106,13 @@ gateTestDarwin : ${gateTestCommon} ${darwinEnvironment} {
   }
 }
 
+gateTestLinuxNFI : ${gateTestCommon} {
+  environment :  {
+      FASTR_RFFI : "nfi"
+  }
+}
+
+
 # This performs a number of "style" checks on the code to ensure it confirms to the project standards.
 
 gateStyle : ${common} {
@@ -146,6 +153,7 @@ internalPkgtest: ${common} {
 
 builds = [
   ${gateTestLinux}            {capabilities : [linux, amd64, fast],  targets : [gate, post-merge], name: "gate-test-linux-amd64"}
+#  ${gateTestLinuxNFI}         {capabilities : [linux, amd64, fast],  targets : [gate, post-merge], name: "gate-test-linux-nfi-amd64"}
   ${gateTestNoSpecialsLinux}  {capabilities : [linux, amd64, fast],  targets : [gate, post-merge], name: "gate-test-linux-amd64-nospecials"}
   ${gateTestDarwin}           {capabilities : [darwin, amd64], targets : [gate, post-merge], name: "gate-test-darwin-amd64"}
   ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-style-linux-amd64"}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java
index 1306e9bc7c..7ef0df76f7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java
@@ -26,8 +26,8 @@ import java.lang.reflect.Field;
 
 import sun.misc.Unsafe;
 
-class UnsafeAdapter {
-    static final Unsafe UNSAFE = initUnsafe();
+public class UnsafeAdapter {
+    public static final Unsafe UNSAFE = initUnsafe();
 
     private static Unsafe initUnsafe() {
         try {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
new file mode 100644
index 0000000000..33ab050e3c
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+
+public class TruffleNFI_Base implements BaseRFFI {
+
+    private enum Function {
+        getpid("(): sint32", true),
+        getcwd("([uint8], sint32): sint32", true),
+        chdir("(string): sint32", true),
+        mkdir("(string, sint32): sint32", true),
+        call_readlink("((string, sint32): void, string): void", false),
+        mkdtemp("([uint8]): sint32", true),
+        chmod("(string, sint32): sint32", true),
+        call_strtol("((sint64, sint32): void, string, sint32): void", false),
+        call_uname("((string, string, string, string, string): void): void", false),
+        call_glob("(string, (string): void): void", false);
+
+        private final int argCount;
+        private final String signature;
+        private final boolean useDefaultLibrary;
+        private Node message;
+        private TruffleObject function;
+
+        Function() {
+            this(null, true);
+        }
+
+        Function(String signature, boolean useDefaultLibrary) {
+            this.argCount = TruffleNFI_Utils.getArgCount(signature);
+            this.signature = signature;
+            this.useDefaultLibrary = useDefaultLibrary;
+        }
+
+        private void initialize() {
+            if (message == null) {
+                message = Message.createExecute(argCount).createNode();
+            }
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind(name(), useDefaultLibrary, signature);
+            }
+        }
+    }
+
+    public static class TruffleNFI_GetpidNode extends GetpidNode {
+        @Override
+        public int execute() {
+            Function.getpid.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.getpid.message, Function.getpid.function);
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+
+        }
+    }
+
+    public static class TruffleNFI_GetwdNode extends GetwdNode {
+        @Override
+        public String execute() {
+            byte[] buf = new byte[4096];
+            Function.getcwd.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.getcwd.message, Function.getcwd.function, JavaInterop.asTruffleObject(buf), buf.length);
+                if (result == 0) {
+                    return null;
+                } else {
+                    int i = 0;
+                    while (buf[i] != 0 && i < buf.length) {
+                        i++;
+                    }
+                    return new String(buf, 0, i);
+                }
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_SetwdNode extends SetwdNode {
+        @Override
+        public int execute(String dir) {
+            Function.chdir.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.chdir.message, Function.chdir.function, dir);
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_MkdirNode extends MkdirNode {
+        @Override
+        public void execute(String dir, int mode) throws IOException {
+            Function.mkdir.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.mkdir.message, Function.mkdir.function, dir, mode);
+                if (result != 0) {
+                    throw new IOException("mkdir " + dir + " failed");
+                }
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_ReadlinkNode extends ReadlinkNode {
+        private static final int EINVAL = 22;
+
+        interface SetResult {
+            void setResult(String link, int errno);
+        }
+
+        private static class SetResultImpl implements SetResult {
+            private String link;
+            private int errno;
+
+            @Override
+            public void setResult(String link, int errno) {
+                this.link = link;
+                this.errno = errno;
+            }
+
+        }
+
+        @Override
+        public String execute(String path) throws IOException {
+            Function.call_readlink.initialize();
+            try {
+                SetResultImpl setResultImpl = new SetResultImpl();
+                ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, JavaInterop.asTruffleFunction(SetResult.class, setResultImpl), path);
+                if (setResultImpl.link == null) {
+                    if (setResultImpl.errno == EINVAL) {
+                        return path;
+                    } else {
+                        // some other error
+                        throw new IOException("readlink failed: " + setResultImpl.errno);
+                    }
+                }
+                return setResultImpl.link;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_MkdtempNode extends MkdtempNode {
+        @Override
+        public String execute(String template) {
+            /*
+             * Not only must the (C) string end in XXXXXX it must also be null-terminated. Since it
+             * is modified by mkdtemp we must make a copy.
+             */
+            byte[] bytes = template.getBytes();
+            byte[] ztbytes = new byte[bytes.length + 1];
+            System.arraycopy(bytes, 0, ztbytes, 0, bytes.length);
+            ztbytes[bytes.length] = 0;
+            Function.mkdtemp.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.mkdtemp.message, Function.mkdtemp.function, JavaInterop.asTruffleObject(ztbytes));
+                if (result == 0) {
+                    return null;
+                } else {
+                    return new String(ztbytes, 0, bytes.length);
+                }
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_ChmodNode extends ChmodNode {
+        @Override
+        public int execute(String path, int mode) {
+            Function.chmod.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.chmod.message, Function.chmod.function, path, mode);
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_StrolNode extends StrolNode {
+        interface SetResult {
+            void setResult(long result, int errno);
+        }
+
+        private static class SetResultImpl implements SetResult {
+            private long result;
+            private int errno;
+
+            @Override
+            public void setResult(long result, int errno) {
+                this.result = result;
+                this.errno = errno;
+            }
+        }
+
+        @Override
+        public long execute(String s, int base) throws IllegalArgumentException {
+            Function.call_strtol.initialize();
+            try {
+                SetResultImpl setResultImpl = new SetResultImpl();
+                ForeignAccess.sendExecute(Function.call_strtol.message, Function.call_strtol.function, JavaInterop.asTruffleFunction(SetResult.class, setResultImpl), s, base);
+                if (setResultImpl.errno != 0) {
+                    throw new IllegalArgumentException("strtol failure");
+                } else {
+                    return setResultImpl.result;
+                }
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static class TruffleNFI_UnameNode extends UnameNode {
+        private static UnameUpCallImpl unameUpCallImpl;
+
+        private interface UnameUpCall {
+            void unameUpCall(String sysname, String release, String version, String machine, String nodename);
+        }
+
+        private class UnameUpCallImpl implements UnameUpCall, UtsName {
+            private String sysname;
+            private String release;
+            private String version;
+            private String machine;
+            private String nodename;
+
+            @Override
+            public void unameUpCall(String sysnameA, String releaseA, String versionA, String machineA, String nodenameA) {
+                sysname = sysnameA;
+                release = releaseA;
+                version = versionA;
+                machine = machineA;
+                nodename = nodenameA;
+            }
+
+            @Override
+            public String sysname() {
+                return sysname;
+            }
+
+            @Override
+            public String release() {
+                return release;
+            }
+
+            @Override
+            public String version() {
+                return version;
+            }
+
+            @Override
+            public String machine() {
+                return machine;
+            }
+
+            @Override
+            public String nodename() {
+                return nodename;
+            }
+
+        }
+
+        @Override
+        public UtsName execute() {
+            Function.call_uname.initialize();
+            if (unameUpCallImpl == null) {
+                unameUpCallImpl = new UnameUpCallImpl();
+                try {
+                    ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, JavaInterop.asTruffleFunction(UnameUpCall.class, unameUpCallImpl));
+                } catch (InteropException e) {
+                    throw RInternalError.shouldNotReachHere(e);
+                }
+            }
+            return unameUpCallImpl;
+        }
+    }
+
+    public static class TruffleNFI_GlobNode extends GlobNode {
+        private interface GlobUpCall {
+            void addPath(String path);
+        }
+
+        private static class GlobUpCallImpl implements GlobUpCall {
+            private ArrayList<String> paths = new ArrayList<>();
+
+            @Override
+            public void addPath(String path) {
+                paths.add(path);
+            }
+        }
+
+        @Override
+        public ArrayList<String> glob(String pattern) {
+            Function.call_glob.initialize();
+            GlobUpCallImpl globUpCallImpl = new GlobUpCallImpl();
+            try {
+                ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, JavaInterop.asTruffleFunction(GlobUpCall.class, globUpCallImpl));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+            return globUpCallImpl.paths;
+        }
+
+    }
+
+    @Override
+    public GetpidNode createGetpidNode() {
+        return new TruffleNFI_GetpidNode();
+    }
+
+    @Override
+    public GetwdNode createGetwdNode() {
+        return new TruffleNFI_GetwdNode();
+    }
+
+    @Override
+    public SetwdNode createSetwdNode() {
+        return new TruffleNFI_SetwdNode();
+    }
+
+    @Override
+    public MkdirNode createMkdirNode() {
+        return new TruffleNFI_MkdirNode();
+    }
+
+    @Override
+    public ReadlinkNode createReadlinkNode() {
+        return new TruffleNFI_ReadlinkNode();
+    }
+
+    @Override
+    public MkdtempNode createMkdtempNode() {
+        return new TruffleNFI_MkdtempNode();
+    }
+
+    @Override
+    public ChmodNode createChmodNode() {
+        return new TruffleNFI_ChmodNode();
+    }
+
+    @Override
+    public StrolNode createStrolNode() {
+        return new TruffleNFI_StrolNode();
+    }
+
+    @Override
+    public UnameNode createUnameNode() {
+        return new TruffleNFI_UnameNode();
+    }
+
+    @Override
+    public GlobNode createGlobNode() {
+        return new TruffleNFI_GlobNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java
new file mode 100644
index 0000000000..a01fd2b14c
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+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.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LibPaths;
+
+public class TruffleNFI_CAccess {
+    private static TruffleNFI_DLL.NFIHandle handle;
+
+    public enum Function {
+        READ_POINTER_INT("(pointer): sint32"),
+        READ_ARRAY_INT("(pointer, sint64): sint32"),
+        READ_POINTER_DOUBLE("(pointer): double"),
+        READ_ARRAY_DOUBLE("(pointer, sint32): double");
+
+        private TruffleObject symbolFunction;
+        private final String signature;
+
+        Function(String signature) {
+            this.signature = signature;
+
+        }
+
+        public TruffleObject getSymbolFunction() {
+            if (handle == null) {
+                handle = (TruffleNFI_DLL.NFIHandle) DLLRFFI.DLOpenRootNode.create().getCallTarget().call(LibPaths.getBuiltinLibPath("caccess"), true, true);
+            }
+            if (symbolFunction == null) {
+                DLL.SymbolHandle symbolHandle = (DLL.SymbolHandle) DLLRFFI.DLSymRootNode.create().getCallTarget().call(handle, cName());
+                assert symbolHandle != null;
+                Node bind = Message.createInvoke(1).createNode();
+                try {
+                    symbolFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", signature);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+
+            }
+            return symbolFunction;
+        }
+
+        public String cName() {
+            return "caccess_" + name().toLowerCase();
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
new file mode 100644
index 0000000000..acefb85638
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen;
+import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
+import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
+import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+
+public class TruffleNFI_Call implements CallRFFI {
+
+    private enum INIT_VAR_FUN {
+        OBJ("(sint32, object) : void"),
+        DOUBLE("(sint32, double): void"),
+        STRING("(sint32, string): void"),
+        INT("(sint32, sint32) : void");
+
+        private final String funName;
+        private TruffleObject initFunction;
+        private final String signature;
+
+        INIT_VAR_FUN(String signature) {
+            this.signature = signature;
+            funName = "Call_initvar_" + name().toLowerCase();
+        }
+    }
+
+    /**
+     * Nesting of native calls is rare but can happen and the cleanup needs to be per call.
+     */
+    private static int callDepth;
+
+    public TruffleNFI_Call() {
+        initialize();
+        TruffleNFI_PkgInit.initialize();
+    }
+
+    private static void initVariables() {
+        Node bind = Message.createInvoke(1).createNode();
+        for (INIT_VAR_FUN initVarFun : INIT_VAR_FUN.values()) {
+            SymbolHandle symbolHandle = DLL.findSymbol(initVarFun.funName, null); // libR
+            try {
+                initVarFun.initFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", initVarFun.signature);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere(t);
+            }
+        }
+        Node executeNode = Message.createExecute(2).createNode();
+        RFFIVariables[] variables = RFFIVariables.values();
+        for (int i = 0; i < variables.length; i++) {
+            RFFIVariables var = variables[i];
+            Object value = var.getValue();
+            if (value == null) {
+                continue;
+            }
+            try {
+                if (value instanceof Double) {
+                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.DOUBLE.initFunction, i, value);
+                } else if (value instanceof Integer) {
+                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.INT.initFunction, i, value);
+                } else if (value instanceof String) {
+                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.STRING.initFunction, i, value);
+                } else {
+                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.OBJ.initFunction, i, value);
+                }
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere(t);
+            }
+        }
+    }
+
+    private static void initCallbacks(UpCallsRFFI upCallsImpl) {
+        Node bind = Message.createInvoke(1).createNode();
+        Node executeNode = Message.createExecute(1).createNode();
+        SymbolHandle symbolHandle = DLL.findSymbol("Rinternals_addCallback", null);
+        TruffleObject upCallsObject = JavaInterop.asTruffleObject(upCallsImpl);
+        Node readNode = Message.READ.createNode();
+        try {
+            for (RFFIUpCallMethod upCallMethod : RFFIUpCallMethod.values()) {
+                Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCallMethod.name());
+                String addCallbackSignature = String.format("(sint32, %s): void", upCallMethod.nfiSignature);
+                TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
+                ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCallMethod.ordinal(), upCallMethodObject);
+            }
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    private enum ReturnArray {
+        INTEGER_CREATE("([sint32], sint32): uint64", 2),
+        DOUBLE_CREATE("([double], sint32): uint64", 2),
+        BYTE_CREATE("([uint8], sint32, sint32): uint64", 3),
+        INTEGER_EXISTING("(uint64): void", 1),
+        DOUBLE_EXISTING("(uint64): void", 1),
+        BYTE_EXISTING("(uint64): void", 1),
+        FREE("(uint64): void", 1);
+
+        private final String signature;
+        private final String funName;
+        private TruffleObject function;
+        private final Node executeNode;
+
+        ReturnArray(String signature, int numArgs) {
+            this.signature = signature;
+            this.funName = "return_" + name();
+            this.executeNode = Message.createExecute(numArgs).createNode();
+        }
+
+    }
+
+    private static void initReturnArray() {
+        Node bind = Message.createInvoke(1).createNode();
+        for (ReturnArray returnArrayFun : ReturnArray.values()) {
+            SymbolHandle symbolHandle = DLL.findSymbol(returnArrayFun.funName, null); // libR
+            try {
+                returnArrayFun.function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", returnArrayFun.signature);
+            } catch (InteropException t) {
+                throw RInternalError.shouldNotReachHere(t);
+            }
+        }
+    }
+
+    // TODO Nodify?
+    static long returnArrayCreate(Object array, boolean isString) {
+        try {
+            if (array instanceof int[]) {
+                return (long) ForeignAccess.sendExecute(ReturnArray.INTEGER_CREATE.executeNode, ReturnArray.INTEGER_CREATE.function, JavaInterop.asTruffleObject(array), ((int[]) array).length);
+            } else if (array instanceof double[]) {
+                return (long) ForeignAccess.sendExecute(ReturnArray.DOUBLE_CREATE.executeNode, ReturnArray.DOUBLE_CREATE.function, JavaInterop.asTruffleObject(array), ((double[]) array).length);
+            } else if (array instanceof byte[]) {
+                return (long) ForeignAccess.sendExecute(ReturnArray.BYTE_CREATE.executeNode, ReturnArray.BYTE_CREATE.function, JavaInterop.asTruffleObject(array), ((byte[]) array).length,
+                                isString ? 1 : 0);
+            } else {
+                throw RInternalError.shouldNotReachHere();
+            }
+        } catch (InteropException t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    static void returnArrayExisting(SEXPTYPE type, long address) {
+        try {
+            switch (type) {
+                case INTSXP:
+                case LGLSXP:
+                    ForeignAccess.sendExecute(ReturnArray.INTEGER_EXISTING.executeNode, ReturnArray.INTEGER_EXISTING.function, address);
+                    break;
+                case REALSXP:
+                    ForeignAccess.sendExecute(ReturnArray.DOUBLE_EXISTING.executeNode, ReturnArray.DOUBLE_EXISTING.function, address);
+                    break;
+                case CHARSXP:
+                case RAWSXP:
+                    ForeignAccess.sendExecute(ReturnArray.BYTE_EXISTING.executeNode, ReturnArray.BYTE_EXISTING.function, address);
+                    break;
+                default:
+                    throw RInternalError.shouldNotReachHere();
+
+            }
+        } catch (InteropException t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    static void freeArray(long address) {
+        Node executeNode = Message.createExecute(1).createNode();
+        try {
+            ForeignAccess.sendExecute(executeNode, ReturnArray.FREE.function, address);
+        } catch (InteropException t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    private static void initialize() {
+        UpCallsRFFI upCallsImpl = RFFIUtils.initialize(new TruffleNFI_UpCallsRFFIImpl());
+        if (traceEnabled()) {
+            traceDownCall("initialize");
+        }
+        try {
+            initVariables();
+            initCallbacks(upCallsImpl);
+            initReturnArray();
+        } finally {
+            if (traceEnabled()) {
+                traceDownCallReturn("initialize", null);
+            }
+        }
+    }
+
+    public abstract static class TruffleNFI_InvokeCallNode extends InvokeCallNode {
+        @Child Node bindNode = Message.createInvoke(1).createNode();
+
+        @Specialization(guards = "args.length == 0")
+        protected Object invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 1")
+        protected Object invokeCall1(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 2")
+        protected Object invokeCall2(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 3")
+        protected Object invokeCall3(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 4")
+        protected Object invokeCall4(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]),
+                                    JavaInterop.asTruffleObject(args[3]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 5")
+        protected Object invokeCall5(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 6")
+        protected Object invokeCall6(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 7")
+        protected Object invokeCall7(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]),
+                                    JavaInterop.asTruffleObject(args[6]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 8")
+        protected Object invokeCall8(NativeCallInfo nativeCallInfo, Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                Object result = null;
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object");
+                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]),
+                                    JavaInterop.asTruffleObject(args[6]), JavaInterop.asTruffleObject(args[7]));
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, result);
+                }
+            }
+        }
+
+        public static Node createExecute(int n) {
+            return Message.createExecute(n).createNode();
+        }
+
+    }
+
+    public static class TruffleNFI_InvokeVoidCallNode extends InvokeVoidCallNode {
+        private static final String CallVoid1Sig = "(object): void";
+        private static final String CallVoid0Sig = "(): void";
+        @Child Node bindNode = Message.createInvoke(1).createNode();
+        @Child Node execute0Node = Message.createExecute(0).createNode();
+        @Child Node execute1Node = Message.createExecute(1).createNode();
+
+        @Override
+        public void execute(NativeCallInfo nativeCallInfo, Object[] args) {
+            synchronized (TruffleNFI_Call.class) {
+                prepareCall(nativeCallInfo.name, args);
+                try {
+                    switch (args.length) {
+                        case 0:
+                            TruffleObject callVoid0Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                            nativeCallInfo.address.asTruffleObject(), "bind", CallVoid0Sig);
+                            ForeignAccess.sendExecute(execute0Node, callVoid0Function);
+                            break;
+                        case 1:
+                            TruffleObject callVoid1Function = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                            nativeCallInfo.address.asTruffleObject(), "bind", CallVoid1Sig);
+                            ForeignAccess.sendExecute(execute1Node, callVoid1Function, args[0]);
+                            break;
+                    }
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                } finally {
+                    prepareReturn(nativeCallInfo.name, null);
+                }
+            }
+        }
+    }
+
+    private static void prepareCall(String name, Object[] args) {
+        if (traceEnabled()) {
+            traceDownCall(name, args);
+        }
+        TruffleNFI_NativeArray.callEnter(callDepth);
+        callDepth++;
+    }
+
+    private static void prepareReturn(String name, Object result) {
+        if (traceEnabled()) {
+            traceDownCallReturn(name, result);
+        }
+        TruffleNFI_NativeArray.callEnter(callDepth);
+        callDepth--;
+    }
+
+    @Override
+    public InvokeCallNode createInvokeCallNode() {
+        return TruffleNFI_InvokeCallNodeGen.create();
+    }
+
+    @Override
+    public InvokeVoidCallNode createInvokeVoidCallNode() {
+        return new TruffleNFI_InvokeVoidCallNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
new file mode 100644
index 0000000000..21ca2496f3
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+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.UnknownIdentifierException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+
+public class TruffleNFI_DLL implements DLLRFFI {
+
+    static class NFIHandle {
+        @SuppressWarnings("unused") private final String libName;
+        final TruffleObject libHandle;
+
+        NFIHandle(String libName, TruffleObject libHandle) {
+            this.libName = libName;
+            this.libHandle = libHandle;
+        }
+    }
+
+    private static class TruffleNFI_DLOpenNode extends DLLRFFI.DLOpenNode {
+
+        @Override
+        public Object execute(String path, boolean local, boolean now) {
+            String libName = DLL.libName(path);
+            PolyglotEngine engine = RContext.getInstance().getVM();
+            TruffleObject libHandle = engine.eval(Source.newBuilder(prepareLibraryOpen(path, local, now)).name(path).mimeType("application/x-native").build()).as(TruffleObject.class);
+            return new NFIHandle(libName, libHandle);
+        }
+    }
+
+    @TruffleBoundary
+    private static String prepareLibraryOpen(String path, boolean local, boolean now) {
+        StringBuilder sb = new StringBuilder("load");
+        sb.append("(");
+        sb.append(local ? "RTLD_LOCAL" : "RTLD_GLOBAL");
+        sb.append('|');
+        sb.append(now ? "RTLD_NOW" : "RTLD_LAZY");
+        sb.append(")");
+        sb.append(' ');
+        sb.append(path);
+        return sb.toString();
+    }
+
+    private static class TruffleNFI_DLSymNode extends DLLRFFI.DLSymNode {
+
+        @Override
+        public SymbolHandle execute(Object handle, String symbol) {
+            assert handle instanceof NFIHandle;
+            NFIHandle nfiHandle = (NFIHandle) handle;
+            Node lookupSymbol = Message.READ.createNode();
+            try {
+                TruffleObject result = (TruffleObject) ForeignAccess.sendRead(lookupSymbol, nfiHandle.libHandle, symbol);
+                return new SymbolHandle(result);
+            } catch (UnknownIdentifierException e) {
+                return null;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static class TruffleNFI_DLCloseNode extends DLLRFFI.DLCloseNode {
+
+        @Override
+        public int execute(Object handle) {
+            assert handle instanceof NFIHandle;
+            // TODO
+            return 0;
+        }
+
+    }
+
+    @Override
+    public DLOpenNode createDLOpenNode() {
+        return new TruffleNFI_DLOpenNode();
+    }
+
+    @Override
+    public DLSymNode createDLSymNode() {
+        return new TruffleNFI_DLSymNode();
+    }
+
+    @Override
+    public DLCloseNode createDLCloseNode() {
+        return new TruffleNFI_DLCloseNode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
new file mode 100644
index 0000000000..66b2d2c0be
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+
+public class TruffleNFI_Lapack implements LapackRFFI {
+    enum Function {
+        ilaver("([sint32]): void"),
+        dgeev("(uint8, uint8, sint32, [double], sint32, [double], [double], [double], sint32, [double], sint32, [double], sint32) : sint32"),
+        dgeqp3("(sint32, sint32, [double], sint32, [sint32], [double], [double], sint32) : sint32"),
+        dormq("(uint8, uint8, sint32, sint32, sint32, [double], sint32, [double], [double], sint32, [double], sint32) : sint32"),
+        dtrtrs("(uint8, uint8, uint8, sint32, sint32, [double], sint32, [double], sint32) : sint32"),
+        dgetr("(sint32, sint32, [double], sint32, [sint32]) : sint32"),
+        dpotrf("(uint8, sint32, [double], sint32) : sint32"),
+        dpotri("(uint8, sint32, [double], sint32) : sint32"),
+        dpstrf("uint8, sint32, [double], sint32, [sint32], [sint32], double, [double]) : sint32"),
+        dgesv("(sint32, sint32, [double], sint32, [sint32], [double], sint32) : sint32"),
+        dlange("(uint8, sint32, sint32, [double], sint32, [double]) : double"),
+        dgecon("(uint8, sint32, [double], sint32, double, [double], [double], [sint32]) : sint32"),
+        dsyevr("(uint8, uint8, uint8, sint32, [double], sint32, double, double, sint32, sint32, double, [sint32], [double], [double], sint32, [sint32], [double], sint32, [sint32], sint32) : sint32");
+
+        private final int argCount;
+        private final String signature;
+        @CompilationFinal private Node executeNode;
+        @CompilationFinal private TruffleObject function;
+
+        Function(String signature) {
+            this.argCount = TruffleNFI_Utils.getArgCount(signature);
+            this.signature = signature;
+        }
+
+        private void initialize() {
+            if (executeNode == null) {
+                executeNode = Message.createExecute(argCount).createNode();
+            }
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind("call_" + name(), false, signature);
+            }
+        }
+    }
+
+    private static class TruffleNFI_IlaverNode extends IlaverNode {
+
+        @Override
+        public void execute(int[] version) {
+            Function.ilaver.initialize();
+            try {
+                ForeignAccess.sendExecute(Function.ilaver.executeNode, Function.ilaver.function, JavaInterop.asTruffleObject(version));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+
+        }
+    }
+
+    private static class TruffleNFI_DgeevNode extends DgeevNode {
+
+        @Override
+        public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
+            Function.dgeev.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dgeev.executeNode, Function.dgeev.function, jobVL, jobVR, n, JavaInterop.asTruffleObject(a), lda,
+                                JavaInterop.asTruffleObject(wr), JavaInterop.asTruffleObject(wi), JavaInterop.asTruffleObject(vl), ldvl,
+                                JavaInterop.asTruffleObject(vr), ldvr, JavaInterop.asTruffleObject(work), lwork);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_Dgeqp3Node extends Dgeqp3Node {
+
+        @Override
+        public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
+            Function.dgeqp3.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dgeqp3.executeNode, Function.dgeqp3.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(jpvt),
+                                JavaInterop.asTruffleObject(tau), JavaInterop.asTruffleObject(work), lwork);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DormqrNode extends DormqrNode {
+
+        @Override
+        public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+            Function.dormq.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dormq.executeNode, Function.dormq.function, side, trans, m, n, k, JavaInterop.asTruffleObject(a), lda,
+                                JavaInterop.asTruffleObject(tau), JavaInterop.asTruffleObject(c), ldc, JavaInterop.asTruffleObject(work), lwork);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DtrtrsNode extends DtrtrsNode {
+
+        @Override
+        public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+            Function.dtrtrs.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dtrtrs.executeNode, Function.dtrtrs.function, uplo, trans, diag, n, nrhs, JavaInterop.asTruffleObject(a), lda,
+                                JavaInterop.asTruffleObject(b), ldb);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DgetrfNode extends DgetrfNode {
+
+        @Override
+        public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
+            Function.dgetr.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dgetr.executeNode, Function.dgetr.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DpotrfNode extends DpotrfNode {
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda) {
+            Function.dpotrf.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dpotrf.executeNode, Function.dpotrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DpotriNode extends DpotriNode {
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda) {
+            Function.dpotri.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dpotri.executeNode, Function.dpotrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DpstrfNode extends DpstrfNode {
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
+            Function.dpstrf.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dpstrf.executeNode, Function.dpstrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda,
+                                JavaInterop.asTruffleObject(piv), JavaInterop.asTruffleObject(rank), tol, JavaInterop.asTruffleObject(work));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DgesvNode extends DgesvNode {
+
+        @Override
+        public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
+            Function.dgesv.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dgesv.executeNode, Function.dgesv.function, n, nrhs, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv),
+                                JavaInterop.asTruffleObject(b), ldb);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DlangeNode extends DlangeNode {
+
+        @Override
+        public double execute(char norm, int m, int n, double[] a, int lda, double[] work) {
+            Function.dlange.initialize();
+            try {
+                return (double) ForeignAccess.sendExecute(Function.dlange.executeNode, Function.dlange.function, norm, m, n, JavaInterop.asTruffleObject(a), lda,
+                                JavaInterop.asTruffleObject(work));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DgeconNode extends DgeconNode {
+
+        @Override
+        public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
+            Function.dgecon.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dgecon.executeNode, Function.dgecon.function, norm, n, JavaInterop.asTruffleObject(a), lda, anorm, JavaInterop.asTruffleObject(rcond),
+                                JavaInterop.asTruffleObject(work), JavaInterop.asTruffleObject(iwork));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_DsyevrNode extends DsyevrNode {
+
+        @Override
+        public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz,
+                        double[] work, int lwork, int[] iwork, int liwork) {
+            Function.dsyevr.initialize();
+            try {
+                return (int) ForeignAccess.sendExecute(Function.dsyevr.executeNode, Function.dsyevr.function, jobz, range, uplo, n, JavaInterop.asTruffleObject(a),
+                                lda, vl, vu, il, iu, abstol, JavaInterop.asTruffleObject(m), JavaInterop.asTruffleObject(w), JavaInterop.asTruffleObject(z), ldz,
+                                JavaInterop.asTruffleObject(isuppz), JavaInterop.asTruffleObject(work), lwork, JavaInterop.asTruffleObject(iwork), liwork);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    @Override
+    public IlaverNode createIlaverNode() {
+        return new TruffleNFI_IlaverNode();
+    }
+
+    @Override
+    public DgeevNode createDgeevNode() {
+        return new TruffleNFI_DgeevNode();
+    }
+
+    @Override
+    public Dgeqp3Node createDgeqp3Node() {
+        return new TruffleNFI_Dgeqp3Node();
+    }
+
+    @Override
+    public DormqrNode createDormqrNode() {
+        return new TruffleNFI_DormqrNode();
+    }
+
+    @Override
+    public DtrtrsNode createDtrtrsNode() {
+        return new TruffleNFI_DtrtrsNode();
+    }
+
+    @Override
+    public DgetrfNode createDgetrfNode() {
+        return new TruffleNFI_DgetrfNode();
+    }
+
+    @Override
+    public DpotrfNode createDpotrfNode() {
+        return new TruffleNFI_DpotrfNode();
+    }
+
+    @Override
+    public DpotriNode createDpotriNode() {
+        return new TruffleNFI_DpotriNode();
+    }
+
+    @Override
+    public DpstrfNode createDpstrfNode() {
+        return new TruffleNFI_DpstrfNode();
+    }
+
+    @Override
+    public DgesvNode createDgesvNode() {
+        return new TruffleNFI_DgesvNode();
+    }
+
+    @Override
+    public DlangeNode createDlangeNode() {
+        return new TruffleNFI_DlangeNode();
+    }
+
+    @Override
+    public DgeconNode createDgeconNode() {
+        return new TruffleNFI_DgeconNode();
+    }
+
+    @Override
+    public DsyevrNode createDsyevrNode() {
+        return new TruffleNFI_DsyevrNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
new file mode 100644
index 0000000000..39eeb2a3ea
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import java.util.Arrays;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+
+/**
+ * Support for the {@code INTEGER, LOGICAL, ...} functions in the RFFI, which must return the same
+ * array while an FFI call is in progress.
+ */
+public class TruffleNFI_NativeArray {
+    private static int tableHwm;
+    private static int[] hwmStack = new int[16];
+    private static Info[] table = new Info[64];
+
+    static {
+        initTableElements(0);
+    }
+
+    private static class Info {
+        /**
+         * E.g., {@link RIntVector}.
+         */
+        Object x;
+        /**
+         * internal array, e.g. {@code int[]}.
+         */
+        Object array;
+        /**
+         * {@code null} unless {@code x} is an {@link RLogicalVector}, in which case it is the
+         * underlying {@code byte[]}.
+         */
+        byte[] logicalByteArray;
+
+        long arrayAddress;
+    }
+
+    private static void initTableElements(int startIndex) {
+        for (int i = startIndex; i < table.length; i++) {
+            table[i] = new Info();
+        }
+    }
+
+    static void callEnter(int callDepth) {
+        hwmStack[callDepth] = tableHwm;
+    }
+
+    static void callExit(int callDepth) {
+        int oldHwm = hwmStack[callDepth - 1];
+        for (int i = oldHwm; i < tableHwm; i++) {
+            Info info = table[i];
+            if (info.x != null) {
+                if (info.logicalByteArray != null) {
+                    boolean seenNA = false;
+                    int[] xai = (int[]) info.array;
+                    for (int j = 0; j < xai.length; j++) {
+                        int xaival = xai[j];
+                        byte xal;
+                        if (xaival == RRuntime.INT_NA) {
+                            seenNA = true;
+                            xal = RRuntime.LOGICAL_NA;
+                        } else {
+                            xal = (byte) xaival;
+                        }
+                        info.logicalByteArray[j] = xal;
+                    }
+                    if (seenNA) {
+                        RLogicalVector lv = (RLogicalVector) info.x;
+                        lv.setComplete(false);
+                    }
+                }
+                TruffleNFI_Call.freeArray(info.arrayAddress);
+            }
+        }
+        tableHwm = oldHwm;
+    }
+
+    /**
+     * Searches table for an entry matching {@code x}.
+     *
+     * @return the associated native array address or {@code 0} if not found.
+     */
+    static long findArray(Object x) {
+        for (int i = 0; i < tableHwm; i++) {
+            if (table[i].x == x) {
+                return table[i].arrayAddress;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Records that the {@code array} associated with object {@code x} has been requested by the
+     * native code from, e.g., an {@code INTEGER(x)} function.
+     *
+     * @return the native array address
+     */
+    static long recordArray(Object x, Object array, SEXPTYPE type) {
+        Object xa;
+        byte[] logicalByteArray = null;
+        boolean isString = false;
+        switch (type) {
+            case INTSXP:
+            case REALSXP:
+            case RAWSXP:
+            case CHARSXP:
+                isString = type == SEXPTYPE.CHARSXP;
+                xa = array;
+                break;
+
+            case LGLSXP: {
+                byte[] xal = (byte[]) array;
+                // RFFI wants int*
+                int[] xai = new int[xal.length];
+                for (int i = 0; i < xai.length; i++) {
+                    byte lval = xal[i];
+                    xai[i] = RRuntime.isNA(lval) ? RRuntime.INT_NA : lval;
+                }
+                xa = xai;
+                logicalByteArray = xal;
+                break;
+            }
+
+            default:
+                throw RInternalError.shouldNotReachHere();
+
+        }
+        if (tableHwm == table.length) {
+            table = Arrays.copyOf(table, table.length * 2);
+            initTableElements(tableHwm);
+        }
+        Info t = table[tableHwm];
+        t.x = x;
+        t.array = xa;
+        t.logicalByteArray = logicalByteArray;
+        t.arrayAddress = TruffleNFI_Call.returnArrayCreate(xa, isString);
+        tableHwm++;
+        return t.arrayAddress;
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
new file mode 100644
index 0000000000..a0c1b6d886
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import java.nio.charset.StandardCharsets;
+
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+
+public class TruffleNFI_PCRE implements PCRERFFI {
+    private enum Function {
+        maketables("(): sint64", true),
+        compile("((uint64, string, sint32): void, string, sint32, uint64): void", false),
+        getcapturecount("(uint64, uint64): sint32", false),
+        getcapturenames("((sint32, string): void, uint64, uint64)", false),
+        study("(uint64, sint32): void", false),
+        exec("(uint64, uint64, [uint8], sint32, sint32, sint32, [sint32], sint32): sint32", true);
+
+        private final int argCount;
+        private final String signature;
+        private final String callName;
+        private Node executeNode;
+        private TruffleObject function;
+
+        Function(String signature, boolean direct) {
+            this.argCount = TruffleNFI_Utils.getArgCount(signature);
+            this.signature = signature;
+            this.callName = (direct ? "pcre_" : "call_") + name();
+        }
+
+        private void initialize() {
+            if (executeNode == null) {
+                executeNode = Message.createExecute(argCount).createNode();
+            }
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind(callName, false, signature);
+            }
+        }
+    }
+
+    private static class TruffleNFI_MaketablesNode extends MaketablesNode {
+
+        @Override
+        public long execute() {
+            Function.maketables.initialize();
+            try {
+                long result = (long) ForeignAccess.sendExecute(Function.maketables.executeNode, Function.maketables.function);
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    private static class TruffleNFI_GetCaptureCountNode extends GetCaptureCountNode {
+
+        @Override
+        public int execute(long code, long extra) {
+            Function.getcapturecount.initialize();
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.getcapturecount.executeNode, Function.getcapturecount.function, code, extra);
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode {
+        interface CaptureNames {
+            void addName(int i, String name);
+        }
+
+        final class CaptureNamesImpl implements CaptureNames {
+            private final String[] captureNames;
+
+            private CaptureNamesImpl(int captureCount) {
+                captureNames = new String[captureCount];
+            }
+
+            @Override
+            public void addName(int i, String name) {
+                captureNames[i] = name;
+            }
+
+        }
+
+        @Override
+        public String[] execute(long code, long extra, int captureCount) {
+            Function.getcapturenames.initialize();
+            try {
+                CaptureNamesImpl captureNamesImpl = new CaptureNamesImpl(captureCount);
+                int result = (int) ForeignAccess.sendExecute(Function.getcapturenames.executeNode, Function.getcapturenames.function,
+                                JavaInterop.asTruffleFunction(CaptureNames.class, captureNamesImpl), code, extra);
+                if (result < 0) {
+                    CompilerDirectives.transferToInterpreter();
+                    throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result);
+                } else {
+                    return captureNamesImpl.captureNames;
+                }
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    private static class TruffleNFI_CompileNode extends CompileNode {
+        interface MakeResult {
+            void makeresult(long pcreResult, String errorMessage, int errOffset);
+        }
+
+        private static class MakeResultImpl implements MakeResult {
+            private PCRERFFI.Result result;
+
+            @Override
+            public void makeresult(long pcreResult, String errorMessage, int errOffset) {
+                result = new PCRERFFI.Result(pcreResult, errorMessage, errOffset);
+            }
+        }
+
+        @Override
+        public Result execute(String pattern, int options, long tables) {
+            Function.compile.initialize();
+            try {
+                MakeResultImpl makeResultImpl = new MakeResultImpl();
+                ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, JavaInterop.asTruffleFunction(MakeResult.class, makeResultImpl),
+                                pattern, options, tables);
+                return makeResultImpl.result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    private static class TruffleNFI_ExecNode extends ExecNode {
+
+        @Override
+        public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) {
+            Function.exec.initialize();
+            try {
+
+                byte[] subjectBytes = subject.getBytes(StandardCharsets.UTF_8);
+                return (int) ForeignAccess.sendExecute(Function.exec.executeNode, Function.exec.function, code, extra,
+                                JavaInterop.asTruffleObject(subjectBytes), subjectBytes.length,
+                                offset, options, JavaInterop.asTruffleObject(ovector), ovector.length);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    @Override
+    public MaketablesNode createMaketablesNode() {
+        return new TruffleNFI_MaketablesNode();
+    }
+
+    @Override
+    public CompileNode createCompileNode() {
+        return new TruffleNFI_CompileNode();
+    }
+
+    @Override
+    public GetCaptureCountNode createGetCaptureCountNode() {
+        return new TruffleNFI_GetCaptureCountNode();
+    }
+
+    @Override
+    public GetCaptureNamesNode createGetCaptureNamesNode() {
+        return new TruffleNFI_GetCaptureNamesNode();
+    }
+
+    @Override
+    public StudyNode createStudyNode() {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public ExecNode createExecNode() {
+        return new TruffleNFI_ExecNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
new file mode 100644
index 0000000000..0ec6f4d2ef
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+
+public final class TruffleNFI_PkgInit {
+
+    private enum UpCall {
+        registerRoutines("(object, sint32, sint32, uint64): void"),
+        useDynamicSymbols("(object, sint32): sint32"),
+        setDotSymbolValues("(object, string, pointer, sint32): object"),
+        forceSymbols("(object, sint32): sint32");
+        private final String signature;
+
+        UpCall(String signature) {
+            this.signature = signature;
+        }
+    }
+
+    /**
+     * The upcalls from native code that support symbol registration.
+     */
+    interface UpCalls {
+
+        /**
+         * This is the start, called from {@code R_RegisterRoutines}.
+         *
+         * @param dllInfo library the symbols are defined in
+         * @param nstOrd the ordinal value corresponding to
+         *            {@link com.oracle.truffle.r.runtime.ffi.DLL.NativeSymbolType}.
+         * @param num the number of functions being registered
+         * @param routines the C address of the function table (not interpreted).
+         */
+        void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines);
+
+        /**
+         * Internal upcall used by {@code Rdynload_setSymbol}. The {@code fun} value must be
+         * converted to a {@link TruffleObject} representing the symbol}.
+         *
+         * @param dllInfo library the symbol is defined in
+         * @param name name of function
+         * @param fun the C address of the function (in the table)
+         * @param numArgs the number of arguments the function takes.
+         */
+        DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, TruffleObject fun, int numArgs);
+
+        /**
+         * Directly implements {@code R_useDynamicSymbols}.
+         */
+        int useDynamicSymbols(DLLInfo dllInfo, int value);
+
+        /**
+         * Directly implements {@code R_forceSymbols}.
+         */
+        int forceSymbols(DLLInfo dllInfo, int value);
+
+    }
+
+    private static class UpCallsImpl implements UpCalls {
+        /**
+         * First create the array, then downcall to native to get the specific info for each symbol
+         * which is delivered by {@link #setDotSymbolValues}.
+         */
+        @Override
+        public void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines) {
+            DotSymbol[] array = new DotSymbol[num];
+            for (int i = 0; i < num; i++) {
+                array[i] = setSymbol(dllInfo, nstOrd, routines, i);
+            }
+            dllInfo.setNativeSymbols(nstOrd, array);
+        }
+
+        @Override
+        public int useDynamicSymbols(DLLInfo dllInfo, int value) {
+            return DLL.useDynamicSymbols(dllInfo, value);
+        }
+
+        @Override
+        public DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, TruffleObject fun, int numArgs) {
+            /*
+             * We don't know the NFI signature at this point, so we cannot bind the function here.
+             */
+            DotSymbol result = new DotSymbol(name, new SymbolHandle(fun), numArgs);
+            return result;
+        }
+
+        @Override
+        public int forceSymbols(DLLInfo dllInfo, int value) {
+            return DLL.forceSymbols(dllInfo, value);
+        }
+    }
+
+    private static final String SETSYMBOL_SIGNATURE = "(object, sint32, uint64, sint32): object";
+    private static TruffleObject setSymbolFunction;
+
+    static void initialize() {
+        Node bind = Message.createInvoke(1).createNode();
+        SymbolHandle symbolHandle = DLL.findSymbol("Rdynload_init", null);
+        Node executeNode = Message.createExecute(2).createNode();
+        UpCallsImpl upCalls = new UpCallsImpl();
+        TruffleObject upCallsObject = JavaInterop.asTruffleObject(upCalls);
+        Node readNode = Message.READ.createNode();
+        try {
+            for (UpCall upCall : UpCall.values()) {
+                Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCall.name());
+                String addCallbackSignature = String.format("(sint32, %s): void", upCall.signature);
+                TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
+                ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCall.ordinal(), upCallMethodObject);
+            }
+            symbolHandle = DLL.findSymbol("Rdynload_setSymbol", null);
+            setSymbolFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", SETSYMBOL_SIGNATURE);
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    private static DotSymbol setSymbol(DLLInfo dllInfo, int nstOrd, long routines, int index) {
+        Node executeNode = Message.createExecute(4).createNode();
+        try {
+            DotSymbol result = (DotSymbol) ForeignAccess.sendExecute(executeNode, setSymbolFunction, dllInfo, nstOrd, routines, index);
+            return result;
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java
new file mode 100644
index 0000000000..e0289cdacb
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+
+public class TruffleNFI_RAppl implements RApplRFFI {
+    enum Function {
+        dqrdc2("([double], sint32, sint32, sint32, double, [sint32], [double], [sint32], [double]): void"),
+        dqrcf("([double], sint32, sint32, [double], [double], sint32, [double], [sint32]): void"),
+        dqrls("([double], sint32, sint32, [double], sint32, double, [double], [double], [double], [sint32], [sint32], [double], [double]): void");
+
+        private final int argCount;
+        private final String signature;
+        @CompilationFinal private Node executeNode;
+        @CompilationFinal private TruffleObject function;
+
+        Function(String signature) {
+            this.argCount = TruffleNFI_Utils.getArgCount(signature);
+            this.signature = signature;
+        }
+
+        private void initialize() {
+            if (executeNode == null) {
+                executeNode = Message.createExecute(argCount).createNode();
+            }
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind("call_" + name(), false, signature);
+            }
+        }
+    }
+
+    private static class TruffleNFI_Dqrdc2Node extends Dqrdc2Node {
+
+        @Override
+        public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
+            Function.dqrdc2.initialize();
+            try {
+                ForeignAccess.sendExecute(Function.dqrdc2.executeNode, Function.dqrdc2.function,
+                                JavaInterop.asTruffleObject(x),
+                                ldx, n, p, tol,
+                                JavaInterop.asTruffleObject(rank),
+                                JavaInterop.asTruffleObject(qraux),
+                                JavaInterop.asTruffleObject(pivot),
+                                JavaInterop.asTruffleObject(work));
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+
+        }
+
+    }
+
+    private static class TruffleNFI_DqrcfNode extends DqrcfNode {
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
+            Function.dqrcf.initialize();
+            try {
+                ForeignAccess.sendExecute(Function.dqrcf.executeNode, Function.dqrcf.function,
+                                JavaInterop.asTruffleObject(x),
+                                n, k,
+                                JavaInterop.asTruffleObject(qraux),
+                                JavaInterop.asTruffleObject(y),
+                                ny,
+                                JavaInterop.asTruffleObject(b),
+                                JavaInterop.asTruffleObject(info));
+
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    private static class TruffleNFI_DqrlsNode extends DqrlsNode {
+
+        @Override
+        public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
+            Function.dqrls.initialize();
+            try {
+                ForeignAccess.sendExecute(Function.dqrls.executeNode, Function.dqrls.function,
+                                JavaInterop.asTruffleObject(x),
+                                n, p,
+                                JavaInterop.asTruffleObject(y),
+                                ny, tol,
+                                JavaInterop.asTruffleObject(b),
+                                JavaInterop.asTruffleObject(rsd),
+                                JavaInterop.asTruffleObject(qty),
+                                JavaInterop.asTruffleObject(k),
+                                JavaInterop.asTruffleObject(jpvt),
+                                JavaInterop.asTruffleObject(qraux),
+                                JavaInterop.asTruffleObject(work));
+
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+
+        }
+
+    }
+
+    @Override
+    public Dqrdc2Node createDqrdc2Node() {
+        return new TruffleNFI_Dqrdc2Node();
+    }
+
+    @Override
+    public DqrcfNode createDqrcfNode() {
+        return new TruffleNFI_DqrcfNode();
+    }
+
+    @Override
+    public DqrlsNode createDqrlsNode() {
+        return new TruffleNFI_DqrlsNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
new file mode 100644
index 0000000000..d884490e87
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+import com.oracle.truffle.r.runtime.ffi.LibPaths;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+import com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory;
+
+public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
+    private static class ContextStateImpl implements RContext.ContextState {
+        @Override
+        public ContextState initialize(RContext context) {
+            if (context.isInitial()) {
+                String librffiPath = LibPaths.getBuiltinLibPath("R");
+                DLL.loadLibR(librffiPath);
+            }
+            return this;
+        }
+    }
+
+    @Override
+    public ContextState newContextState() {
+        return new ContextStateImpl();
+    }
+
+    @CompilationFinal private CallRFFI callRFFI;
+
+    @CompilationFinal private BaseRFFI baseRFFI;
+
+    @Override
+    public BaseRFFI getBaseRFFI() {
+        if (baseRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            baseRFFI = new TruffleNFI_Base();
+        }
+        return baseRFFI;
+    }
+
+    @Override
+    public CallRFFI getCallRFFI() {
+        if (callRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            callRFFI = new TruffleNFI_Call();
+        }
+        return callRFFI;
+    }
+
+    @CompilationFinal private DLLRFFI dllRFFI;
+
+    @Override
+    public DLLRFFI getDLLRFFI() {
+        if (dllRFFI == null) {
+            dllRFFI = new TruffleNFI_DLL();
+        }
+        return dllRFFI;
+    }
+
+    @CompilationFinal private UserRngRFFI userRngRFFI;
+
+    @Override
+    public UserRngRFFI getUserRngRFFI() {
+        if (userRngRFFI == null) {
+            userRngRFFI = new TruffleNFI_UserRng();
+        }
+        return userRngRFFI;
+    }
+
+    @CompilationFinal private ZipRFFI zipRFFI;
+
+    @Override
+    public ZipRFFI getZipRFFI() {
+        if (zipRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            zipRFFI = new TruffleNFI_Zip();
+        }
+        return zipRFFI;
+    }
+
+    @CompilationFinal private PCRERFFI pcreRFFI;
+
+    @Override
+    public PCRERFFI getPCRERFFI() {
+        if (pcreRFFI == null) {
+            pcreRFFI = new TruffleNFI_PCRE();
+        }
+        return pcreRFFI;
+    }
+
+    @CompilationFinal private LapackRFFI lapackRFFI;
+
+    @Override
+    public LapackRFFI getLapackRFFI() {
+        if (lapackRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            lapackRFFI = new TruffleNFI_Lapack();
+        }
+        return lapackRFFI;
+    }
+
+    @CompilationFinal private RApplRFFI rApplRFFI;
+
+    @Override
+    public RApplRFFI getRApplRFFI() {
+        if (rApplRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            rApplRFFI = new TruffleNFI_RAppl();
+        }
+        return rApplRFFI;
+    }
+
+    @CompilationFinal private StatsRFFI statsRFFI;
+
+    @Override
+    public StatsRFFI getStatsRFFI() {
+        if (statsRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            statsRFFI = new TruffleNFI_Stats();
+        }
+        return statsRFFI;
+    }
+
+    @CompilationFinal private ToolsRFFI toolsRFFI;
+
+    @Override
+    public ToolsRFFI getToolsRFFI() {
+        if (toolsRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            toolsRFFI = new TruffleNFI_Tools();
+        }
+        return toolsRFFI;
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java
new file mode 100644
index 0000000000..f6c8d87e16
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+
+public class TruffleNFI_Stats implements StatsRFFI {
+
+    private static class TruffleNFI_FactorNode extends FactorNode {
+        private static final String FFT_FACTOR = "fft_factor";
+        private static final String FFT_FACTOR_SIGNATURE = "(sint32, [sint32], [sint32]): void";
+
+        @Child Node factorMessage = Message.createExecute(3).createNode();
+        @Child DLLRFFI.DLSymNode dlsymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+
+        @CompilationFinal private TruffleObject fftFactorFunction;
+
+        @Override
+        public void execute(int n, int[] pmaxf, int[] pmaxp) {
+            try {
+                if (fftFactorFunction == null) {
+                    Node bind = Message.createInvoke(1).createNode();
+                    fftFactorFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, findSymbol(FFT_FACTOR, dlsymNode).asTruffleObject(), "bind", FFT_FACTOR_SIGNATURE);
+                }
+                ForeignAccess.sendExecute(factorMessage, fftFactorFunction, n, JavaInterop.asTruffleObject(pmaxf), JavaInterop.asTruffleObject(pmaxp));
+            } catch (InteropException t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static class TruffleNFI_WorkNode extends WorkNode {
+        private static final String FFT_WORK = "fft_work";
+        private static final String FFT_WORK_SIGNATURE = "([double], sint32, sint32, sint32, sint32, [double], [sint32]): sint32";
+
+        @Child DLLRFFI.DLSymNode dlsymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+        @Child Node workMessage = Message.createExecute(7).createNode();
+        @CompilationFinal private TruffleObject fftWorkFunction;
+
+        @Override
+        public int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) {
+            try {
+                if (fftWorkFunction == null) {
+                    Node bind = Message.createInvoke(1).createNode();
+                    fftWorkFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, findSymbol(FFT_WORK, dlsymNode).asTruffleObject(), "bind", FFT_WORK_SIGNATURE);
+                }
+                return (int) ForeignAccess.sendExecute(workMessage, fftWorkFunction, JavaInterop.asTruffleObject(a), nseg, n, nspn, isn,
+                                JavaInterop.asTruffleObject(work), JavaInterop.asTruffleObject(iwork));
+            } catch (InteropException t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+    }
+
+    private static SymbolHandle findSymbol(String symbol, DLLRFFI.DLSymNode dlsymNode) {
+        SymbolHandle fftAddress;
+        DLLInfo dllInfo = DLL.findLibrary("stats");
+        assert dllInfo != null;
+        fftAddress = dlsymNode.execute(dllInfo.handle, symbol);
+        assert fftAddress != DLL.SYMBOL_NOT_FOUND;
+        return fftAddress;
+    }
+
+    @Override
+    public FactorNode createFactorNode() {
+        return new TruffleNFI_FactorNode();
+    }
+
+    @Override
+    public WorkNode createWorkNode() {
+        return new TruffleNFI_WorkNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
new file mode 100644
index 0000000000..305c038b49
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import java.io.IOException;
+
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.RConnection;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools;
+
+public class TruffleNFI_Tools implements ToolsRFFI {
+
+    private static class TruffleNFI_ToolsRFFINode extends Generic_Tools.Generic_ToolsRFFINode {
+        private interface RConnGetC {
+            int getc(RConnection conn);
+        }
+
+        private static class RConnGetCImpl implements RConnGetC {
+            @Override
+            public int getc(RConnection conn) {
+                try {
+                    return conn.getc();
+                } catch (IOException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        private static boolean initialized;
+
+        @Child private DLLRFFI.DLSymNode dysymNode = DLLRFFI.DLSymNode.create();
+
+        @Override
+        public synchronized Object execute(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros,
+                        RLogicalVector warndups) {
+            if (!initialized) {
+                initCallback();
+                initialized = true;
+            }
+            return super.execute(con, srcfile, verbose, fragment, basename, warningCalls, JavaInterop.asTruffleObject(macros), warndups);
+        }
+
+        private void initCallback() {
+            DLLInfo toolsDLLInfo = DLL.findLibrary(TOOLS);
+            assert toolsDLLInfo != null;
+            SymbolHandle symbolHandle = dysymNode.execute(toolsDLLInfo.handle, "gramRd_nfi_init");
+            assert symbolHandle != DLL.SYMBOL_NOT_FOUND;
+            Node bind = Message.createInvoke(1).createNode();
+            Node executeNode = Message.createExecute(1).createNode();
+            try {
+                TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "((object): sint32): void");
+                ForeignAccess.sendExecute(executeNode, function, JavaInterop.asTruffleFunction(RConnGetC.class, new RConnGetCImpl()));
+            } catch (InteropException t) {
+                throw RInternalError.shouldNotReachHere(t);
+            }
+
+        }
+    }
+
+    @Override
+    public ParseRdNode createParseRdNode() {
+        return new TruffleNFI_ToolsRFFINode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java
new file mode 100644
index 0000000000..e302c637ca
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl;
+import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+
+public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
+    @Override
+    public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) {
+        // "bytes" is actually a TruffleObject denoting a native pointer
+        // TODO: handle encoding properly
+        return CharSXPWrapper.create(TruffleNFI_Utils.convertCstring(bytes, len));
+    }
+
+    @Override
+    public Object INTEGER(Object x) {
+        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
+        if (arrayAddress == 0) {
+            Object array = super.INTEGER(x);
+            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.INTSXP);
+        } else {
+            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.INTSXP, arrayAddress);
+        }
+        return x;
+    }
+
+    @Override
+    public Object LOGICAL(Object x) {
+        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
+        if (arrayAddress == 0) {
+            Object array = super.LOGICAL(x);
+            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.LGLSXP);
+        } else {
+            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.LGLSXP, arrayAddress);
+        }
+        return x;
+
+    }
+
+    @Override
+    public Object REAL(Object x) {
+        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
+        if (arrayAddress == 0) {
+            Object array = super.LOGICAL(x);
+            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.REALSXP);
+        } else {
+            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.REALSXP, arrayAddress);
+        }
+        return x;
+
+    }
+
+    @Override
+    public Object RAW(Object x) {
+        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
+        if (arrayAddress == 0) {
+            Object array = super.LOGICAL(x);
+            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.RAWSXP);
+        } else {
+            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.RAWSXP, arrayAddress);
+        }
+        return x;
+    }
+
+    @Override
+    public Object R_CHAR(Object x) {
+        long arrayAddress = TruffleNFI_NativeArray.findArray(x);
+        if (arrayAddress == 0) {
+            CharSXPWrapper charSXP = (CharSXPWrapper) x;
+            Object array = charSXP.getContents().getBytes();
+            arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.CHARSXP);
+        } else {
+            TruffleNFI_Call.returnArrayExisting(SEXPTYPE.CHARSXP, arrayAddress);
+        }
+        return x;
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java
new file mode 100644
index 0000000000..e94994edaf
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
+
+public class TruffleNFI_UserRng implements UserRngRFFI {
+
+    private static class NFIUserRngRFFINode extends UserRngRFFINode {
+        Node initMessage;
+        Node randMessage;
+        Node nSeedMessage;
+        Node seedsMessage;
+        Node readPointerNode = Message.createExecute(1).createNode();
+
+        TruffleObject initFunction;
+        TruffleObject nSeedFunction;
+        TruffleObject randFunction;
+        TruffleObject seedsFunction;
+
+        @Override
+        public void init(int seed) {
+            if (initMessage == null) {
+                initMessage = Message.createExecute(1).createNode();
+            }
+            try {
+                if (initFunction == null) {
+                    Node bind = Message.createInvoke(1).createNode();
+                    initFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Init.getSymbolHandle().asTruffleObject(), "bind", "(sint32): void");
+                }
+                ForeignAccess.sendExecute(initMessage, initFunction, seed);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+        @Override
+        public double rand() {
+            if (randMessage == null) {
+                randMessage = Message.createExecute(0).createNode();
+            }
+            try {
+                if (randFunction == null) {
+                    Node bind = Message.createInvoke(1).createNode();
+                    randFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Rand.getSymbolHandle().asTruffleObject(), "bind", "(): pointer");
+                }
+                Object address = ForeignAccess.sendExecute(randMessage, randFunction);
+                Object value = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_DOUBLE.getSymbolFunction(), address);
+                return (double) value;
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+        @Override
+        public int nSeed() {
+            if (nSeedMessage == null) {
+                nSeedMessage = Message.createExecute(0).createNode();
+            }
+            try {
+                if (nSeedFunction == null) {
+                    Node bind = Message.createInvoke(1).createNode();
+                    nSeedFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.NSeed.getSymbolHandle().asTruffleObject(), "bind", "(): pointer");
+                }
+                Object address = ForeignAccess.sendExecute(nSeedMessage, nSeedFunction);
+                Object n = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_INT.getSymbolFunction(), address);
+                return (int) n;
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+
+        @Override
+        public void seeds(int[] n) {
+            if (seedsMessage == null) {
+                seedsMessage = Message.createExecute(0).createNode();
+            }
+            try {
+                if (seedsFunction == null) {
+                    Node bind = Message.createInvoke(1).createNode();
+                    seedsFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Seedloc.getSymbolHandle().asTruffleObject(), "bind", "(): pointer");
+                }
+                Object address = ForeignAccess.sendExecute(seedsMessage, seedsFunction);
+                for (int i = 0; i < n.length; i++) {
+                    Object seed = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_ARRAY_INT.getSymbolFunction(), address, i);
+                    n[i] = (int) seed;
+                }
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Override
+    public UserRngRFFINode createUserRngRFFINode() {
+        return new NFIUserRngRFFINode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
new file mode 100644
index 0000000000..df1edddf96
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import java.nio.charset.StandardCharsets;
+
+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.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.engine.interop.UnsafeAdapter;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+
+public class TruffleNFI_Utils {
+
+    private static String getString(long address, int len) {
+        byte[] byteArray = new byte[len];
+        for (int i = 0; i < len; i++) {
+            byteArray[i] = UnsafeAdapter.UNSAFE.getByte(address + i);
+        }
+        return new String(byteArray, StandardCharsets.UTF_8);
+    }
+
+    static String convertCstring(Object cstring, int len) {
+        try {
+            long address = (long) ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) cstring);
+            return getString(address, len);
+        } catch (UnsupportedMessageException ex) {
+            throw RInternalError.shouldNotReachHere(ex);
+        }
+    }
+
+    private static TruffleObject defaultLibrary;
+
+    private static void initDefaultLibrary() {
+        if (defaultLibrary == null) {
+            PolyglotEngine engine = RContext.getInstance().getVM();
+            defaultLibrary = engine.eval(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).as(TruffleObject.class);
+        }
+
+    }
+
+    /**
+     * Looks up the symbol {@code name} in either the "default" library (e.g. C library symbols) or
+     * in one of the libraries loaded through {@link DLL}, and binds the given NFI signature to the
+     * result, returning the resulting Truffle function object. Failure is fatal.
+     */
+    static TruffleObject lookupAndBind(String name, boolean inDefaultLibrary, String signature) {
+        initDefaultLibrary();
+        try {
+            TruffleObject symbol;
+            if (inDefaultLibrary) {
+                symbol = ((TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), defaultLibrary, name));
+            } else {
+                symbol = DLL.findSymbol(name, null).asTruffleObject();
+            }
+            return (TruffleObject) ForeignAccess.sendInvoke(Message.createInvoke(1).createNode(), symbol, "bind", signature);
+        } catch (InteropException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        }
+    }
+
+    /**
+     * Returns the number of arguments in an NFI signature.
+     */
+    static int getArgCount(String signature) {
+        int argCount = 0;
+        int nestCount = -1;
+        boolean type = false;
+        for (int i = 0; i < signature.length(); i++) {
+            char ch = signature.charAt(i);
+            if (ch == '(') {
+                nestCount++;
+            } else if (ch == ')') {
+                if (nestCount > 0) {
+                    nestCount--;
+                } else {
+                    return type ? argCount + 1 : 0;
+                }
+            } else if (ch == ',') {
+                if (nestCount == 0) {
+                    argCount++;
+                }
+            } else {
+                type = true;
+            }
+        }
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    public static void main(String[] args) {
+        System.out.printf("argCount: %s%n", getArgCount(args[0]));
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java
new file mode 100644
index 0000000000..957b88ea24
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+public class TruffleNFI_Zip implements ZipRFFI {
+
+    private enum Function {
+        compress("([uint8], [uint64], [uint8], uint64): sint32"),
+        uncompress("([uint8], [uint64], [uint8], uint64): sint32");
+
+        private final int argCount;
+        private final String signature;
+        private Node executeNode;
+        private TruffleObject function;
+
+        Function(String signature) {
+            this.argCount = TruffleNFI_Utils.getArgCount(signature);
+            this.signature = signature;
+        }
+
+        private void initialize() {
+            if (executeNode == null) {
+                executeNode = Message.createExecute(argCount).createNode();
+            }
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind(name(), true, signature);
+            }
+        }
+    }
+
+    private static class TruffleNFI_CompressNode extends ZipRFFI.CompressNode {
+
+        @Override
+        public int execute(byte[] dest, byte[] source) {
+            Function.compress.initialize();
+            long[] destlen = new long[]{dest.length};
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.compress.executeNode, Function.compress.function,
+                                JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen),
+                                JavaInterop.asTruffleObject(source), JavaInterop.asTruffleObject(source.length));
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    private static class TruffleNFI_UncompressNode extends ZipRFFI.UncompressNode {
+        @Override
+        public int execute(byte[] dest, byte[] source) {
+            Function.uncompress.initialize();
+            long[] destlen = new long[]{dest.length};
+            try {
+                int result = (int) ForeignAccess.sendExecute(Function.uncompress.executeNode, Function.uncompress.function,
+                                JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen),
+                                JavaInterop.asTruffleObject(source), JavaInterop.asTruffleObject(source.length));
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    @Override
+    public CompressNode createCompressNode() {
+        return new TruffleNFI_CompressNode();
+    }
+
+    @Override
+    public UncompressNode createUncompressNode() {
+        return new TruffleNFI_UncompressNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index 37ea9afada..fae4e67969 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -30,6 +30,10 @@ export FASTR_NATIVE_DIR = $(TOPDIR)
 export R_VERSION = $(subst R-,,$(notdir $(basename $(basename $(wildcard $(FASTR_R_HOME)/libdownloads/R-*.gz)))))
 export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION)
 
+ifndef FASTR_RFFI
+export FASTR_RFFI = jni
+endif
+
 # Completely accurate dependency analysis is very difficult for this project, so use a version number
 # to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the 
 # dependencies accurately.
diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile
index 78b1f4b0c3..47d879c4c0 100644
--- a/com.oracle.truffle.r.native/fficall/Makefile
+++ b/com.oracle.truffle.r.native/fficall/Makefile
@@ -39,9 +39,8 @@ R_LIBNAME := libR$(DYLIB_EXT)
 R_LIB := $(FASTR_LIB_DIR)/$(R_LIBNAME)
 JNIBOOT_LIBNAME := libjniboot$(DYLIB_EXT)
 JNIBOOT_LIB := $(FASTR_LIB_DIR)/$(JNIBOOT_LIBNAME)
-
-FASTR_COMPILERS_DIR := $(FASTR_R_HOME)/mx.fastr/compilers
-HAVE_SULONG := $(shell $(FASTR_COMPILERS_DIR)/have_sulong)
+CACCESS_LIBNAME := libcaccess$(DYLIB_EXT)
+CACCESS_LIB := $(FASTR_LIB_DIR)/$(CACCESS_LIBNAME)
 
 ifeq ($(OS_NAME), Darwin)
 VERSION_FLAGS := -current_version $(R_VERSION) -compatibility_version $(R_VERSION)
@@ -50,13 +49,13 @@ endif
 BLAS_TARGET := $(FASTR_LIB_DIR)/libRblas$(DYLIB_EXT)
 LAPACK_TARGET := $(FASTR_LIB_DIR)/libRlapack$(DYLIB_EXT)
 
-all: $(R_LIB) $(JNIBOOT_LIB)
+all: $(R_LIB)
 
 # use sentinels to avoid (usually unnecessary) rebuilds.
 # N.B. if things change in the subdirs, a clean must be invoked
 # to remove the sentinels
 
-$(R_LIB): jni.done 
+$(R_LIB): fficall.done 
 ifeq ($(OS_NAME),Darwin)
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack  -lpcre -lz $(VERSION_FLAGS)
 	install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB)
@@ -68,31 +67,58 @@ else
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) $(shell echo $(PKG_LDFLAGS_OVERRIDE)) -Wl,-rpath,'$$ORIGIN' -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack  -lpcre -lz
 endif
 
-jni.done:
-	$(MAKE) -C src/common all
-	$(MAKE) -C src/jni all
-ifeq ($(HAVE_SULONG),yes)
+ifeq ($(FASTR_RFFI),nfi)
+fficall.done: common.done
+	$(MAKE) -C src/truffle_nfi all
+	touch fficall.done
+else
+ifeq ($(FASTR_RFFI),llvm)
+fficall.done: common.done
 	$(MAKE) -C src/truffle_llvm all
-endif
-	touch jni.done
+	touch fficall.done
+else
+ifeq ($(FASTR_RFFI),jni)
+fficall.done: common.done $(JNIBOOT_LIB)
+	$(MAKE) -C src/jni all
+
+jniboot.done:
+	$(MAKE) -C src/jniboot all
+	touch jniboot.done
 
 $(JNIBOOT_LIB): jniboot.done
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(JNIBOOT_LIB) src/jniboot/jniboot.o $(VERSION_FLAGS)
 ifeq ($(OS_NAME),Darwin)
 	install_name_tool -id @rpath/libjniboot.dylib $(JNIBOOT_LIB)
 endif
+else
+	$(error unknown value for FASTR_RFFI)
+endif
+	touch fficall.done
+endif
+endif
 
-jniboot.done:
-	$(MAKE) -C src/jniboot all
-	touch jniboot.done
+common.done:
+	$(MAKE) -C src/common all	
+
+$(CACCESS_LIB): src/caccess/caccess.o
+	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(CACCESS_LIB) src/caccess/caccess.o $(VERSION_FLAGS)
+ifeq ($(OS_NAME),Darwin)
+	install_name_tool -id @rpath/libcaccess.dylib $(CACCESS_LIB)
+endif
 
 clean:
 	$(MAKE) -C src/common clean
-	$(MAKE) -C src/jni clean
-ifeq ($(HAVE_SULONG),yes)
+ifeq ($(FASTR_RFFI),nfi)
+	$(MAKE) -C src/truffle_nfi clean
+else
+ifeq ($(FASTR_RFFI),llvm)
 	$(MAKE) -C src/truffle_llvm clean
+else
+	$(MAKE) -C src/jni clean
+endif
 endif
 	rm -rf $(R_LIB)
 	rm -rf $(JNIBOOT_LIB)
-	rm -rf jni.done jniboot.done
+	rm -rf $(CACCESS_LIB)
+	rm -rf fficall.done
 
diff --git a/com.oracle.truffle.r.native/fficall/src/caccess/Makefile b/com.oracle.truffle.r.native/fficall/src/caccess/Makefile
new file mode 100644
index 0000000000..de9823908e
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/caccess/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(TOPDIR)/platform.mk
+endif
+
+
+.PHONY: all
+
+all: caccess.o
+
+caccess.o: caccess.c
+	$(CC) $(CFLAGS) -c caccess.c -o $@
diff --git a/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c b/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c
new file mode 100644
index 0000000000..6743e91b48
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+int caccess_read_pointer_int(int *address) {
+	return *address;
+}
+
+double caccess_read_pointer_double(double *address) {
+	return *address;
+}
+
+int caccess_read_array_int(int *address, int index) {
+	return address[index];
+}
+
+double caccess_read_array_double(double *address, int index) {
+	return address[index];
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
new file mode 100644
index 0000000000..ce8e60537b
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(TOPDIR)/platform.mk
+endif
+
+.PHONY: all clean
+
+# location of compiled code (.o files)
+OBJ = ../../lib
+
+C_HDRS := $(wildcard *.h)
+
+C_SOURCES = $(wildcard *.c)
+C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(C_SOURCES))
+#$(info C_OBJECTS=$(C_OBJECTS))
+
+FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext
+#NFI_INCLUDES is set in environment (by mx)
+LOCAL_INCLUDES = -I . -I $(abspath ../include)
+
+INCLUDES := $(LOCAL_INCLUDES) $(FFI_INCLUDES) $(NFI_INCLUDES)
+
+# uncomment to see exactly where headers are being read from
+#CFLAGS := $(CFLAGS) -H
+
+all: Makefile $(C_OBJECTS) 
+
+$(C_OBJECTS): | $(OBJ)
+
+$(OBJ):
+	mkdir -p $(OBJ)
+
+$(OBJ)/%.o: %.c $(TOPDIR)/include/Rinternals.h $(C_HDRS)
+	$(CC) $(CFLAGS) $(INCLUDES) -I../variable_defs -c $< -o $@
+
+# for debugging, to see what's really being compiled
+$(OBJ)/%.E: %.c $(TOPDIR)/include/Rinternals.h
+	$(CC) -E $(CFLAGS) $(INCLUDES) -c $< > $@
+
+clean:
+	rm -rf $(OBJ)
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c
new file mode 100644
index 0000000000..a12d66c3cf
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c
@@ -0,0 +1,123 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995-2015, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+#include <rffiutils.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define T_MEM_TABLE_INITIAL_SIZE 0
+// The table of transient objects that have been allocated dur the current FFI call
+static void **tMemTable;
+// hwm of tMemTable
+static int tMemTableIndex;
+static int tMemTableLength;
+
+void init_memory() {
+    tMemTable = malloc(sizeof(void*) * T_MEM_TABLE_INITIAL_SIZE);
+    tMemTableLength = T_MEM_TABLE_INITIAL_SIZE;
+    tMemTableIndex = 0;
+}
+
+void *R_chk_calloc(size_t nelem, size_t elsize);
+
+// Memory that is auto-reclaimed across FFI calls
+char *R_alloc(size_t n, int size) {
+    void *p = R_chk_calloc(n, size);
+    if (tMemTableIndex >= tMemTableLength) {
+	int newLength = 2 * tMemTableLength;
+	void *newtMemTable = malloc(sizeof(void*) * newLength);
+	if (newtMemTable == NULL) {
+	    fatalError("malloc failure");
+	}
+	memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*));
+	free(tMemTable);
+	tMemTable = newtMemTable;
+	tMemTableLength = newLength;
+    }
+    tMemTable[tMemTableIndex] = p;
+    return (char*) p;
+}
+
+char* S_alloc(long n, int size) {
+	char *p = R_alloc(n, size);
+	memset(p, 0, n);
+	return p;
+}
+
+char* S_realloc(char *p, long a, long b, int size) {
+	return unimplemented("S_realloc");
+}
+
+void allocExit() {
+    int i;
+    for (i = 0; i < tMemTableIndex; i++) {
+	free(tMemTable[i]);
+    }
+}
+
+void *R_chk_calloc(size_t nelem, size_t elsize) {
+    void *p;
+#ifndef HAVE_WORKING_CALLOC
+    if (nelem == 0)
+	return (NULL);
+#endif
+    p = calloc(nelem, elsize);
+    if (!p) /* problem here is that we don't have a format for size_t. */
+	error(_("'Calloc' could not allocate memory (%.0f of %u bytes)"),
+		(double) nelem, elsize);
+    return (p);
+}
+
+void *R_chk_realloc(void *ptr, size_t size) {
+    void *p;
+    /* Protect against broken realloc */
+    if(ptr) p = realloc(ptr, size); else p = malloc(size);
+    if(!p)
+	error(_("'Realloc' could not re-allocate memory (%.0f bytes)"),
+	      (double) size);
+    return(p);
+}
+
+void R_chk_free(void *ptr) {
+    if(ptr) {
+	    free(ptr);
+    }
+}
+
+int VMAX_MAGIC = 1234;
+
+void* vmaxget(void) {
+//    unimplemented("vmaxget");
+    // ignored
+    return &VMAX_MAGIC;
+}
+
+void vmaxset(const void * x) {
+//    unimplemented("vmaxget");
+    if (x != &VMAX_MAGIC) {
+	unimplemented("vmaxset with different value");
+    }
+}
+
+void R_gc(void) {
+    unimplemented("R_gc");
+}
+
+int R_gc_running() {
+    unimplemented("R_gc_running");
+    return 0;
+}
+
+SEXP Rf_allocS4Object() {
+	unimplemented("Rf_allocS4Object unimplemented");
+	return NULL;
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
new file mode 100644
index 0000000000..e9adb555cf
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
@@ -0,0 +1,134 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995-2012, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+#include <rffiutils.h>
+#include <Rdynload.h>
+#include <stdio.h>
+
+static void (*call_registerRoutines)(DllInfo *dllInfo, int nstOrd, int num, long routines);
+static int (*call_useDynamicSymbols)(DllInfo *dllInfo, Rboolean value);
+static TruffleObject (*call_setDotSymbolValues)(DllInfo *dllInfo, char *name, long fun, int numArgs);
+static int (*call_forceSymbols)(DllInfo *dllInfo, Rboolean value);
+
+#define registerRoutines_x 0
+#define useDynamicSymbols_x 1
+#define setDotSymbolValues_x 2
+#define forceSymbols_x 3
+
+void Rdynload_init(int index, void* closure) {
+	newClosureRef(closure);
+	switch (index) {
+	case registerRoutines_x: call_registerRoutines = closure; break;
+	case useDynamicSymbols_x: call_useDynamicSymbols = closure; break;
+	case setDotSymbolValues_x: call_setDotSymbolValues = closure; break;
+	case forceSymbols_x: call_forceSymbols = closure; break;
+	}
+}
+
+// Must match ordinal value for DLL.NativeSymbolType
+#define C_NATIVE_TYPE 0
+#define CALL_NATIVE_TYPE 1
+#define FORTRAN_NATIVE_TYPE 2
+#define EXTERNAL_NATIVE_TYPE 3
+
+int
+R_registerRoutines(DllInfo *info, const R_CMethodDef * const croutines,
+		   const R_CallMethodDef * const callRoutines,
+		   const R_FortranMethodDef * const fortranRoutines,
+		   const R_ExternalMethodDef * const externalRoutines) {
+	int num;
+	if (croutines) {
+		for(num = 0; croutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%d,%d,%p\n", info, C_NATIVE_TYPE, num, croutines);
+		call_registerRoutines(info, C_NATIVE_TYPE, num, (long) croutines);
+	}
+	if (callRoutines) {
+		for(num = 0; callRoutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%d,%d,%p\n", info, CALL_NATIVE_TYPE, num, callRoutines);
+		call_registerRoutines(info, CALL_NATIVE_TYPE, num, (long) callRoutines);
+	}
+	if (fortranRoutines) {
+		for(num = 0; fortranRoutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%p,%d,%d,%p\n", call_registerRoutines, info, FORTRAN_NATIVE_TYPE, num, fortranRoutines);
+		call_registerRoutines(info, FORTRAN_NATIVE_TYPE, num, (long) fortranRoutines);
+	}
+	if (externalRoutines) {
+		for(num = 0; externalRoutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%d,%d,%p\n", info, EXTERNAL_NATIVE_TYPE, num, externalRoutines);
+		call_registerRoutines(info, EXTERNAL_NATIVE_TYPE, num, (long) externalRoutines);
+	}
+    return 1;
+}
+
+Rboolean R_useDynamicSymbols(DllInfo *dllInfo, Rboolean value) {
+	return call_useDynamicSymbols(dllInfo, value);
+}
+
+Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) {
+	return call_forceSymbols(dllInfo, value);
+}
+
+
+
+TruffleObject Rdynload_setSymbol(DllInfo *info, int nstOrd, long routinesAddr, int index) {
+	char *name;
+	long fun;
+	int numArgs;
+	switch (nstOrd) {
+	case C_NATIVE_TYPE: {
+		R_CMethodDef *croutines = (R_CMethodDef *) routinesAddr;
+		name = croutines[index].name;
+		fun = (long) croutines[index].fun;
+		numArgs = croutines[index].numArgs;
+		break;
+	}
+	case CALL_NATIVE_TYPE: {
+		R_CallMethodDef *callRoutines = (R_CallMethodDef *) routinesAddr;
+		name = callRoutines[index].name;
+		fun = (long) callRoutines[index].fun;
+		numArgs = callRoutines[index].numArgs;
+		break;
+	}
+	case FORTRAN_NATIVE_TYPE: {
+		R_FortranMethodDef * fortranRoutines = (R_FortranMethodDef *) routinesAddr;
+		name = fortranRoutines[index].name;
+		fun = (long) fortranRoutines[index].fun;
+		numArgs = fortranRoutines[index].numArgs;
+		break;
+	}
+	case EXTERNAL_NATIVE_TYPE: {
+		R_ExternalMethodDef * externalRoutines = (R_ExternalMethodDef *) routinesAddr;
+		name = externalRoutines[index].name;
+		fun = (long) externalRoutines[index].fun;
+		numArgs = externalRoutines[index].numArgs;
+		break;
+	}
+	}
+	//printf("call_setDotSymbolValues %p, %s, %p, %d\n", info, name, fun, numArgs);
+	TruffleObject result = call_setDotSymbolValues(info, name, fun, numArgs);
+
+	return result;
+}
+
+extern SEXP unimplemented(char *fun);
+
+void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) {
+	// we ignore this for now
+}
+
+DL_FUNC R_GetCCallable(const char *package, const char *name) {
+	return unimplemented("R_GetCCallable");
+}
+
+DL_FUNC R_FindSymbol(char const *name, char const *pkg,
+		     R_RegisteredNativeSymbol *symbol) {
+    return unimplemented("R_FindSymbol");
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
new file mode 100644
index 0000000000..c60dc95c6a
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <Rinterface.h>
+#include <rffiutils.h>
+
+char *R_HomeDir(void) {
+	return ((call_R_HomeDir) callbacks[R_HomeDir_x])();
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c
new file mode 100644
index 0000000000..455826794f
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Riconv.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <rffiutils.h>
+#include <Riconv.h>
+
+void * Riconv_open (const char* tocode, const char* fromcode) {
+	return unimplemented("Riconv_open");
+}
+
+size_t Riconv (void * cd, const char **inbuf, size_t *inbytesleft,
+	       char  **outbuf, size_t *outbytesleft) {
+    unimplemented("Riconv");
+    return 0;
+}
+
+int Riconv_close (void * cd) {
+	unimplemented("Riconv_close");
+	return 0;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
new file mode 100644
index 0000000000..026f9f5ba7
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -0,0 +1,1281 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <Rinterface.h>
+#include <rffiutils.h>
+#include <rffi_callbacks.h>
+
+void *callbacks[CALLBACK_TABLE_SIZE];
+
+void Rinternals_addCallback(int index, void *closure) {
+	newClosureRef(closure);
+	callbacks[index] = closure;
+}
+
+static SEXP unimplemented(char *f) {
+	printf("unimplemented %s\n", f);
+	exit(1);
+	return NULL;
+}
+
+static int* return_int;
+static double* return_double;
+static char* return_byte;
+
+long return_INTEGER_CREATE(int *value, int len) {
+	int* idata = malloc(len * sizeof(int));
+	memcpy(idata, value, len * sizeof(int));
+	return_int = idata;
+	return (long) idata;
+}
+
+long return_DOUBLE_CREATE(double *value, int len) {
+	double* ddata = malloc(len * sizeof(double));
+	memcpy(ddata, value, len * sizeof(double));
+	return_double = ddata;
+	return (long) ddata;
+}
+
+long return_BYTE_CREATE(char *value, int len, int isString) {
+	if (isString) {
+		len += 1;
+	}
+	char* bdata = malloc(len * sizeof(char));
+	memcpy(bdata, value, len * sizeof(char));
+	if (isString) {
+		bdata[len] = 0;
+	}
+	return_byte = bdata;
+	return (long) bdata;
+}
+
+void return_INTEGER_EXISTING(long address) {
+	return_int = (int*) address;
+}
+
+void return_DOUBLE_EXISTING(long address) {
+	return_double = (double*) address;
+}
+
+void return_BYTE_EXISTING(long address) {
+	return_byte = (char*) address;
+}
+
+void return_FREE(void *address) {
+//	free(address);
+}
+
+// R_GlobalEnv et al are not a variables in FASTR as they are RContext specific
+SEXP FASTR_R_GlobalEnv() {
+	return unimplemented("FASTR_R_GlobalEnv");
+}
+
+SEXP FASTR_R_BaseEnv() {
+	return ((call_R_BaseEnv) callbacks[R_BaseEnv_x])();
+}
+
+SEXP FASTR_R_BaseNamespace() {
+	return unimplemented("FASTR_R_BaseNamespace");
+}
+
+SEXP FASTR_R_NamespaceRegistry() {
+	return unimplemented("FASTR_R_NamespaceRegistry");
+}
+
+CTXT FASTR_GlobalContext() {
+	return unimplemented("FASTR_GlobalContext");
+}
+
+Rboolean FASTR_R_Interactive() {
+	return (int) unimplemented("FASTR_R_Interactive");
+}
+
+SEXP CAR(SEXP e) {
+	return ((call_CAR) callbacks[CAR_x])(e);
+}
+
+SEXP CDR(SEXP e) {
+	return ((call_CDR) callbacks[CDR_x])(e);
+}
+
+int *INTEGER(SEXP x) {
+	((call_INTEGER) callbacks[INTEGER_x])(x);
+	return return_int;
+}
+
+int *LOGICAL(SEXP x){
+	((call_LOGICAL) callbacks[LOGICAL_x])(x);
+	return return_int;
+}
+
+double *REAL(SEXP x){
+	((call_REAL) callbacks[REAL_x])(x);
+	return return_double;
+}
+
+Rbyte *RAW(SEXP x) {
+	((call_RAW) callbacks[RAW_x])(x);
+		return return_byte;
+}
+
+int LENGTH(SEXP x) {
+	return ((call_LENGTH) callbacks[LENGTH_x])(x);
+}
+
+const char * R_CHAR(SEXP x) {
+	((call_R_CHAR) callbacks[R_CHAR_x])(x);
+	return return_byte;
+}
+
+SEXP Rf_ScalarString(SEXP value) {
+	return ((call_Rf_ScalarString) callbacks[Rf_ScalarString_x])(value);
+}
+
+SEXP Rf_mkChar(const char *x) {
+	return Rf_mkCharLenCE(x, strlen(x), CE_NATIVE);
+}
+
+SEXP Rf_mkCharCE(const char *x, cetype_t y) {
+	return Rf_mkCharLenCE(x, strlen(x), y);
+}
+
+SEXP Rf_mkCharLen(const char *x, int y) {
+	return Rf_mkCharLenCE(x, y, CE_NATIVE);
+}
+
+SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) {
+	return ((call_Rf_mkCharLenCE) callbacks[Rf_mkCharLenCE_x])(x,len, enc);
+}
+
+SEXP Rf_mkString(const char *s) {
+	return ScalarString(Rf_mkChar(s));
+}
+
+void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) {
+	((call_Rf_gsetVar) callbacks[Rf_gsetVar_x])(symbol, value, rho);
+}
+
+SEXP Rf_coerceVector(SEXP x, SEXPTYPE mode) {
+	return ((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode);
+}
+
+SEXP Rf_protect(SEXP x) {
+	return x;
+}
+
+void Rf_unprotect(int x) {
+	// nothing to do
+}
+
+SEXP Rf_cons(SEXP car, SEXP cdr) {
+	return ((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr);
+}
+
+SEXP R_FindNamespace(SEXP info) {
+	return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info);
+}
+
+SEXP Rf_GetOption1(SEXP tag) {
+	return ((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag);
+}
+
+#define BUFSIZE 8192
+
+static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
+{
+    int val;
+    val = vsnprintf(buf, size, format, ap);
+    buf[size-1] = '\0';
+    return val;
+}
+
+
+void Rf_error(const char *format, ...) {
+	// TODO fix this
+	// This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but
+	// RError.error does quite a lot of stuff including potentially searching for R condition handlers
+	// and, if it finds any, does not return, but throws a different exception than RError.
+	// We definitely need to exit the FFI call and we certainly cannot return to our caller.
+	// So we call RFFIUpCallsObject.Rf_error to throw the RError exception. When the pending
+	// exception (whatever it is) is observed by JNI, the call to Rf_error will return where we do a
+	// non-local transfer of control back to the entry point (which will cleanup).
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	// This will set a pending exception (in JNI)
+	((call_Rf_error) callbacks[Rf_error_x])(buf);
+	// just transfer back which will cleanup and exit the entire JNI call
+//	longjmp(*getErrorJmpBuf(), 1);
+
+}
+
+void Rf_errorcall(SEXP x, const char *format, ...) {
+	unimplemented("Rf_errorcall");
+}
+
+void Rf_warningcall(SEXP x, const char *format, ...) {
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rf_warningcall) callbacks[Rf_warningcall_x])(x, buf);
+}
+
+void Rf_warning(const char *format, ...) {
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rf_warning) callbacks[Rf_warning_x])(buf);
+}
+
+void Rprintf(const char *format, ...) {
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rprintf) callbacks[Rprintf_x])(buf);
+}
+
+/*
+  REprintf is used by the error handler do not add
+  anything unless you're sure it won't
+  cause problems
+*/
+void REprintf(const char *format, ...)
+{
+	// TODO: determine correct target for this message
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	// TODO
+}
+
+void Rvprintf(const char *format, va_list args) {
+	unimplemented("Rvprintf");
+}
+void REvprintf(const char *format, va_list args) {
+	unimplemented("REvprintf");
+}
+
+
+SEXP Rf_ScalarInteger(int value) {
+	return ((call_Rf_ScalarInteger) callbacks[Rf_ScalarInteger_x])(value);
+}
+
+SEXP Rf_ScalarReal(double value) {
+	return ((call_Rf_ScalarReal) callbacks[Rf_ScalarDouble_x])(value);
+}
+
+SEXP Rf_ScalarLogical(int value) {
+	return ((call_Rf_ScalarLogical) callbacks[Rf_ScalarLogical_x])(value);
+}
+
+SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
+    if (allocator != NULL) {
+  	    unimplemented("RF_allocVector with custom allocator");
+	    return NULL;
+    }
+    return ((call_Rf_allocateVector) callbacks[Rf_allocateVector_x])(t, len);
+}
+
+SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
+	unimplemented("Rf_allocArray");
+}
+
+SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
+	return unimplemented("Rf_alloc3DArray");
+}
+
+SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
+	unimplemented("Rf_allocMatrix");
+}
+
+SEXP Rf_allocList(int x) {
+	unimplemented("Rf_allocList)");
+	return NULL;
+}
+
+SEXP Rf_allocSExp(SEXPTYPE t) {
+	return unimplemented("Rf_allocSExp");
+}
+
+void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) {
+	((call_Rf_defineVar) callbacks[Rf_defineVar_x])(symbol, value, rho);
+}
+
+void Rf_setVar(SEXP x, SEXP y, SEXP z) {
+    unimplemented("Rf_setVar");
+}
+
+SEXP Rf_dimgets(SEXP x, SEXP y) {
+	return unimplemented("Rf_dimgets");
+}
+
+SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
+	return unimplemented("Rf_dimnamesgets");
+}
+
+SEXP Rf_eval(SEXP expr, SEXP env) {
+	return unimplemented("Rf_eval");
+}
+
+SEXP Rf_findFun(SEXP symbol, SEXP rho) {
+	return unimplemented("Rf_findFun");
+}
+
+SEXP Rf_findVar(SEXP sym, SEXP rho) {
+	return ((call_Rf_findVar) callbacks[Rf_findVar_x])(sym, rho);
+}
+
+SEXP Rf_findVarInFrame(SEXP rho, SEXP sym) {
+	return unimplemented("Rf_findVarInFrame");
+}
+
+SEXP Rf_findVarInFrame3(SEXP rho, SEXP sym, Rboolean b) {
+	return unimplemented("Rf_findVarInFrame");
+}
+
+SEXP Rf_getAttrib(SEXP vec, SEXP name) {
+	SEXP result = ((call_Rf_getAttrib) callbacks[Rf_getAttrib_x])(vec, name);
+//	printf("Rf_getAttrib: %p\n", result);
+	return result;
+}
+
+SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
+	return ((call_Rf_setAttrib) callbacks[Rf_setAttrib_x])(vec, name, val);
+}
+
+SEXP Rf_duplicate(SEXP x) {
+	return unimplemented("Rf_duplicate");
+}
+
+SEXP Rf_shallow_duplicate(SEXP x) {
+	return unimplemented("Rf_shallow_duplicate");
+}
+
+R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
+	return (R_xlen_t) unimplemented("Rf_any_duplicated");
+}
+
+SEXP Rf_duplicated(SEXP x, Rboolean y) {
+	unimplemented("Rf_duplicated");
+	return NULL;
+}
+
+SEXP Rf_applyClosure(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b) {
+	return unimplemented("Rf_applyClosure");
+}
+
+void Rf_copyMostAttrib(SEXP x, SEXP y) {
+	unimplemented("Rf_copyMostAttrib");
+}
+
+void Rf_copyVector(SEXP x, SEXP y) {
+	unimplemented("Rf_copyVector");
+}
+
+int Rf_countContexts(int x, int y) {
+	return (int) unimplemented("Rf_countContexts");
+}
+
+Rboolean Rf_inherits(SEXP x, const char * klass) {
+	return (Rboolean) unimplemented("Rf_inherits");
+}
+
+Rboolean Rf_isReal(SEXP x) {
+    return TYPEOF(x) == REALSXP;
+}
+
+Rboolean Rf_isSymbol(SEXP x) {
+    return TYPEOF(x) == SYMSXP;
+}
+
+Rboolean Rf_isComplex(SEXP x) {
+    return TYPEOF(x) == CPLXSXP;
+}
+
+Rboolean Rf_isEnvironment(SEXP x) {
+    return TYPEOF(x) == ENVSXP;
+}
+
+Rboolean Rf_isExpression(SEXP x) {
+    return TYPEOF(x) == EXPRSXP;
+}
+
+Rboolean Rf_isLogical(SEXP x) {
+    return TYPEOF(x) == LGLSXP;
+}
+
+Rboolean Rf_isObject(SEXP s) {
+	unimplemented("Rf_isObject");
+	return FALSE;
+}
+
+void Rf_PrintValue(SEXP x) {
+	unimplemented("Rf_PrintValue");
+}
+
+SEXP Rf_install(const char *name) {
+	((call_Rf_install) callbacks[Rf_install_x])(name);
+}
+
+SEXP Rf_installChar(SEXP charsxp) {
+	return ((call_Rf_installChar) callbacks[Rf_installChar_x])(charsxp);
+}
+
+Rboolean Rf_isNull(SEXP s) {
+	return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
+}
+
+Rboolean Rf_isString(SEXP s) {
+	return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s);
+}
+
+Rboolean R_cycle_detected(SEXP s, SEXP child) {
+	unimplemented("R_cycle_detected");
+	return 0;
+}
+
+cetype_t Rf_getCharCE(SEXP x) {
+    // unimplemented("Rf_getCharCE");
+    // TODO: real implementation
+    return CE_NATIVE;
+}
+
+const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst) {
+	// TODO proper implementation
+	return x;
+}
+
+int Rf_ncols(SEXP x) {
+	return (int) unimplemented("Rf_ncols");
+}
+
+int Rf_nrows(SEXP x) {
+	return (int) unimplemented("Rf_nrows");
+}
+
+
+void R_ProtectWithIndex(SEXP x, PROTECT_INDEX *y) {
+	//
+}
+
+void R_Reprotect(SEXP x, PROTECT_INDEX y) {
+	//
+}
+
+
+void Rf_unprotect_ptr(SEXP x) {
+	//
+}
+
+
+void R_FlushConsole(void) {
+	// ignored
+}
+
+void R_ProcessEvents(void) {
+	unimplemented("R_ProcessEvents");
+}
+
+// Tools package support, not in public API
+SEXP R_NewHashedEnv(SEXP parent, SEXP size) {
+	return ((call_R_NewHashedEnv) callbacks[R_NewHashedEnv_x])(parent, size);
+}
+
+SEXP Rf_classgets(SEXP vec, SEXP klass) {
+	return unimplemented("Rf_classgets");
+}
+
+const char *Rf_translateChar(SEXP x) {
+	// TODO: proper implementation
+	const char *result = CHAR(x);
+	return result;
+}
+
+const char *Rf_translateChar0(SEXP x) {
+	// TODO: proper implementation
+	const char *result = CHAR(x);
+	return result;
+}
+
+const char *Rf_translateCharUTF8(SEXP x) {
+	// TODO: proper implementation
+	const char *result = CHAR(x);
+	return result;
+}
+
+SEXP Rf_lengthgets(SEXP x, R_len_t y) {
+	return unimplemented("Rf_lengthgets");
+}
+
+SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) {
+	return unimplemented("Rf_xlengthgets");
+}
+
+SEXP R_lsInternal(SEXP env, Rboolean all) {
+	return R_lsInternal3(env, all, TRUE);
+}
+
+SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) {
+	return unimplemented("R_lsInternal3");
+}
+
+SEXP Rf_namesgets(SEXP x, SEXP y) {
+	return unimplemented("Rf_namesgets");
+}
+
+SEXP GetOption(SEXP tag, SEXP rho) {
+    return GetOption1(tag);
+}
+
+int GetOptionCutoff(void) {
+    int w;
+    w = asInteger(GetOption1(install("deparse.cutoff")));
+    if (w == NA_INTEGER || w <= 0) {
+	warning(_("invalid 'deparse.cutoff', used 60"));
+	w = 60;
+    }
+    return w;
+}
+
+#define R_MIN_WIDTH_OPT		10
+#define R_MAX_WIDTH_OPT		10000
+#define R_MIN_DIGITS_OPT	0
+#define R_MAX_DIGITS_OPT	22
+
+int GetOptionWidth(void) {
+    int w;
+    w = asInteger(GetOption1(install("width")));
+    if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) {
+	warning(_("invalid printing width, used 80"));
+	return 80;
+    }
+    return w;
+}
+
+int GetOptionDigits(void) {
+    int d;
+    d = asInteger(GetOption1(install("digits")));
+    if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) {
+	warning(_("invalid printing digits, used 7"));
+	return 7;
+    }
+    return d;
+}
+
+Rboolean Rf_GetOptionDeviceAsk(void) {
+    int ask;
+    ask = asLogical(GetOption1(install("device.ask.default")));
+    if(ask == NA_LOGICAL) {
+	warning(_("invalid value for \"device.ask.default\", using FALSE"));
+	return FALSE;
+    }
+    return ask != 0;
+}
+
+SEXP TAG(SEXP e) {
+	return ((call_TAG) callbacks[TAG_x])(e);
+}
+
+SEXP PRINTNAME(SEXP e) {
+	return unimplemented("PRINTNAME");
+}
+
+
+SEXP CAAR(SEXP e) {
+    unimplemented("CAAR");
+    return NULL;
+}
+
+SEXP CDAR(SEXP e) {
+    unimplemented("CDAR");
+    return NULL;
+}
+
+SEXP CADR(SEXP e) {
+	return ((call_CADR) callbacks[CADR_x])(e);
+}
+
+SEXP CDDR(SEXP e) {
+	return ((call_CDDR) callbacks[CDDR_x])(e);
+}
+
+SEXP CDDDR(SEXP e) {
+    unimplemented("CDDDR");
+    return NULL;
+}
+
+SEXP CADDR(SEXP e) {
+	return unimplemented("CADDR");
+}
+
+SEXP CADDDR(SEXP e) {
+    unimplemented("CADDDR");
+    return NULL;
+}
+
+SEXP CAD4R(SEXP e) {
+    unimplemented("CAD4R");
+    return NULL;
+}
+
+int MISSING(SEXP x){
+    unimplemented("MISSING");
+    return 0;
+}
+
+void SET_MISSING(SEXP x, int v) {
+    unimplemented("SET_MISSING");
+}
+
+void SET_TAG(SEXP x, SEXP y) {
+	((call_SET_TAG) callbacks[SET_TAG_x])(x, y);
+}
+
+SEXP SETCAR(SEXP x, SEXP y) {
+	return ((call_SETCAR) callbacks[SETCAR_x])(x, y);
+}
+
+SEXP SETCDR(SEXP x, SEXP y) {
+	return ((call_SETCDR) callbacks[SETCDR_x])(x, y);
+}
+
+SEXP SETCADR(SEXP x, SEXP y) {
+	return unimplemented("SETCADR");
+}
+
+SEXP SETCADDR(SEXP x, SEXP y) {
+    unimplemented("SETCADDR");
+    return NULL;
+}
+
+SEXP SETCADDDR(SEXP x, SEXP y) {
+    unimplemented("SETCADDDR");
+    return NULL;
+}
+
+SEXP SETCAD4R(SEXP e, SEXP y) {
+    unimplemented("SETCAD4R");
+    return NULL;
+}
+
+SEXP FORMALS(SEXP x) {
+    return unimplemented("FORMALS");
+}
+
+SEXP BODY(SEXP x) {
+	return unimplemented("BODY");
+}
+
+SEXP CLOENV(SEXP x) {
+	return unimplemented("CLOENV");
+}
+
+int RDEBUG(SEXP x) {
+    unimplemented("RDEBUG");
+}
+
+int RSTEP(SEXP x) {
+	unimplemented("RSTEP");
+}
+
+int RTRACE(SEXP x) {
+	unimplemented("RTRACE");
+    return 0;
+}
+
+void SET_RDEBUG(SEXP x, int v) {
+	unimplemented("SET_RDEBUG");
+}
+
+void SET_RSTEP(SEXP x, int v) {
+	unimplemented("SET_RSTEP");
+}
+
+void SET_RTRACE(SEXP x, int v) {
+    unimplemented("SET_RTRACE");
+}
+
+void SET_FORMALS(SEXP x, SEXP v) {
+    unimplemented("SET_FORMALS");
+}
+
+void SET_BODY(SEXP x, SEXP v) {
+    unimplemented("SET_BODY");
+}
+
+void SET_CLOENV(SEXP x, SEXP v) {
+    unimplemented("SET_CLOENV");
+}
+
+SEXP SYMVALUE(SEXP x) {
+	return unimplemented("SYMVALUE");
+}
+
+SEXP INTERNAL(SEXP x) {
+	return unimplemented("INTERNAL");
+}
+
+int DDVAL(SEXP x) {
+	unimplemented("DDVAL");
+    return 0;
+}
+
+void SET_DDVAL(SEXP x, int v) {
+    unimplemented("SET_DDVAL");
+}
+
+void SET_SYMVALUE(SEXP x, SEXP v) {
+	unimplemented("SET_SYMVALUE");
+}
+
+void SET_INTERNAL(SEXP x, SEXP v) {
+    unimplemented("SET_INTERNAL");
+}
+
+SEXP FRAME(SEXP x) {
+	return unimplemented("FRAME");
+}
+
+SEXP ENCLOS(SEXP x) {
+	return unimplemented("ENCLOS");
+}
+
+SEXP HASHTAB(SEXP x) {
+	return unimplemented("HASHTAB");
+}
+
+int ENVFLAGS(SEXP x) {
+	unimplemented("ENVFLAGS");
+    return 0;
+}
+
+void SET_ENVFLAGS(SEXP x, int v) {
+	unimplemented("SET_ENVFLAGS");
+}
+
+void SET_FRAME(SEXP x, SEXP v) {
+    unimplemented("SET_FRAME");
+}
+
+void SET_ENCLOS(SEXP x, SEXP v) {
+	unimplemented("SET_ENCLOS");
+}
+
+void SET_HASHTAB(SEXP x, SEXP v) {
+	unimplemented("SET_HASHTAB");
+}
+
+SEXP PRCODE(SEXP x) {
+	return unimplemented("PRCODE");
+}
+
+SEXP PRENV(SEXP x) {
+	return unimplemented("PRENV");
+}
+
+SEXP PRVALUE(SEXP x) {
+	return unimplemented("PRVALUE");
+}
+
+int PRSEEN(SEXP x) {
+	return (int) unimplemented("PRSEEN");
+}
+
+void SET_PRSEEN(SEXP x, int v) {
+    unimplemented("SET_PRSEEN");
+}
+
+void SET_PRENV(SEXP x, SEXP v) {
+    unimplemented("SET_PRENV");
+}
+
+void SET_PRVALUE(SEXP x, SEXP v) {
+    unimplemented("SET_PRVALUE");
+}
+
+void SET_PRCODE(SEXP x, SEXP v) {
+    unimplemented("SET_PRCODE");
+}
+
+int TRUELENGTH(SEXP x){
+    unimplemented("unimplemented");
+    return 0;
+}
+
+
+void SETLENGTH(SEXP x, int v){
+    unimplemented("SETLENGTH");
+}
+
+
+void SET_TRUELENGTH(SEXP x, int v){
+    unimplemented("SET_TRUELENGTH");
+}
+
+
+R_xlen_t XLENGTH(SEXP x){
+    // xlength seems to be used for long vectors (no such thing in FastR at the moment)
+    return LENGTH(x);
+}
+
+
+R_xlen_t XTRUELENGTH(SEXP x){
+	unimplemented("XTRUELENGTH");
+	return 0;
+}
+
+
+int IS_LONG_VEC(SEXP x){
+	unimplemented("IS_LONG_VEC");
+	return 0;
+}
+
+
+int LEVELS(SEXP x){
+	unimplemented("LEVELS");
+	return 0;
+}
+
+
+int SETLEVELS(SEXP x, int v){
+	unimplemented("SETLEVELS");
+	return 0;
+}
+
+Rcomplex *COMPLEX(SEXP x){
+	unimplemented("COMPLEX");
+	return NULL;
+}
+
+SEXP STRING_ELT(SEXP x, R_xlen_t i) {
+	return ((call_STRING_ELT) callbacks[STRING_ELT_x])(x, i);
+}
+
+
+SEXP VECTOR_ELT(SEXP x, R_xlen_t i){
+	return ((call_VECTOR_ELT) callbacks[VECTOR_ELT_x])(x, i);
+}
+
+void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v){
+    ((call_SET_STRING_ELT) callbacks[SET_STRING_ELT_x])(x, i, v);
+}
+
+
+SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v){
+	return ((call_SET_VECTOR_ELT) callbacks[SET_VECTOR_ELT_x])(x, i, v);
+}
+
+SEXP *STRING_PTR(SEXP x){
+	unimplemented("STRING_PTR");
+	return NULL;
+}
+
+
+SEXP *VECTOR_PTR(SEXP x){
+	unimplemented("VECTOR_PTR");
+	return NULL;
+}
+
+SEXP Rf_asChar(SEXP x){
+	return unimplemented("Rf_asChar");
+}
+
+SEXP Rf_PairToVectorList(SEXP x){
+	return ((call_Rf_PairToVectorList) callbacks[Rf_PairToVectorList_x])(x);
+}
+
+SEXP Rf_VectorToPairList(SEXP x){
+	return unimplemented("Rf_VectorToPairList");
+}
+
+SEXP Rf_asCharacterFactor(SEXP x){
+	unimplemented("Rf_VectorToPairList");
+	return NULL;
+}
+
+int Rf_asLogical(SEXP x){
+	return ((call_Rf_asLogical) callbacks[Rf_asLogical_x])(x);
+}
+
+int Rf_asInteger(SEXP x) {
+	return ((call_Rf_asInteger) callbacks[Rf_asInteger_x])(x);
+}
+
+double Rf_asReal(SEXP x) {
+	unimplemented("Rf_asReal");
+	return 0.0;
+}
+
+Rcomplex Rf_asComplex(SEXP x){
+	unimplemented("Rf_asLogical");
+	Rcomplex c; return c;
+}
+
+int TYPEOF(SEXP x) {
+	return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x);
+}
+
+SEXP ATTRIB(SEXP x){
+    unimplemented("ATTRIB");
+    return NULL;
+}
+
+int OBJECT(SEXP x){
+	return (int) unimplemented("OBJECT");
+}
+
+int MARK(SEXP x){
+    unimplemented("MARK");
+    return 0;
+}
+
+int NAMED(SEXP x){
+	return (int) unimplemented("NAMED");
+}
+
+int REFCNT(SEXP x){
+    unimplemented("REFCNT");
+    return 0;
+}
+
+void SET_OBJECT(SEXP x, int v){
+    unimplemented("SET_OBJECT");
+}
+
+void SET_TYPEOF(SEXP x, int v){
+    unimplemented("SET_TYPEOF");
+}
+
+SEXP SET_TYPEOF_FASTR(SEXP x, int v){
+}
+
+void SET_NAMED(SEXP x, int v){
+    unimplemented("SET_NAMED");
+}
+
+void SET_ATTRIB(SEXP x, SEXP v){
+    unimplemented("SET_ATTRIB");
+}
+
+void DUPLICATE_ATTRIB(SEXP to, SEXP from){
+	unimplemented("DUPLICATE_ATTRIB");
+}
+
+char *dgettext(const char *domainname, const char *msgid) {
+	printf("dgettext: '%s'\n", msgid);
+	return (char*) msgid;
+}
+
+char *libintl_dgettext(const char *domainname, const char *msgid) {
+	return dgettext(domainname, msgid);
+}
+
+char *dngettext(const char *domainname, const char *msgid, const char * msgid_plural, unsigned long int n) {
+    printf("dngettext: singular - '%s' ; plural - '%s'\n", msgid, msgid_plural);
+    return (char*) (n == 1 ? msgid : msgid_plural);
+}
+
+void *DATAPTR(SEXP x) {
+	int type = TYPEOF(x);
+	if (type == INTSXP) {
+		return INTEGER(x);
+	} else if (type == REALSXP) {
+		return REAL(x);
+	} else if (type == LGLSXP) {
+		return LOGICAL(x);
+	} else {
+		printf("DATAPTR %d\n", type);
+		unimplemented("R_DATAPTR");
+		return NULL;
+	}
+}
+
+void R_qsort_I  (double *v, int *II, int i, int j) {
+	unimplemented("R_qsort_I");
+}
+
+void R_qsort_int_I(int *iv, int *II, int i, int j) {
+	unimplemented("R_qsort_int_I");
+}
+
+R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
+	return (R_len_t) unimplemented("R_BadLongVector");
+}
+
+int IS_S4_OBJECT(SEXP x) {
+	return (int) unimplemented("IS_S4_OBJECT");
+}
+
+void SET_S4_OBJECT(SEXP x) {
+	unimplemented("SET_S4_OBJECT");
+}
+void UNSET_S4_OBJECT(SEXP x) {
+	unimplemented("UNSET_S4_OBJECT");
+}
+
+Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
+	return (Rboolean) unimplemented("R_ToplevelExec");
+}
+
+SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
+		       void (*cleanfun)(void *), void *cleandata) {
+	return unimplemented("R_ExecWithCleanup");
+}
+
+/* Environment and Binding Features */
+void R_RestoreHashCount(SEXP rho) {
+	unimplemented("R_RestoreHashCount");
+}
+
+Rboolean R_IsPackageEnv(SEXP rho) {
+	unimplemented("R_IsPackageEnv");
+}
+
+SEXP R_PackageEnvName(SEXP rho) {
+	return unimplemented("R_PackageEnvName");
+}
+
+SEXP R_FindPackageEnv(SEXP info) {
+	return unimplemented("R_FindPackageEnv");
+}
+
+Rboolean R_IsNamespaceEnv(SEXP rho) {
+	return (Rboolean) unimplemented("R_IsNamespaceEnv");
+}
+
+SEXP R_NamespaceEnvSpec(SEXP rho) {
+	return unimplemented("R_NamespaceEnvSpec");
+}
+
+void R_LockEnvironment(SEXP env, Rboolean bindings) {
+	unimplemented("R_LockEnvironment");
+}
+
+Rboolean R_EnvironmentIsLocked(SEXP env) {
+	unimplemented("");
+}
+
+void R_LockBinding(SEXP sym, SEXP env) {
+	unimplemented("R_LockBinding");
+}
+
+void R_unLockBinding(SEXP sym, SEXP env) {
+	unimplemented("R_unLockBinding");
+}
+
+void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) {
+	unimplemented("R_MakeActiveBinding");
+}
+
+Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
+	return (Rboolean) unimplemented("R_BindingIsLocked");
+}
+
+Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
+    // TODO: for now, I belive all bindings are false
+    return (Rboolean)0;
+}
+
+Rboolean R_HasFancyBindings(SEXP rho) {
+	return (Rboolean) unimplemented("R_HasFancyBindings");
+}
+
+Rboolean Rf_isS4(SEXP x) {
+    return IS_S4_OBJECT(x);
+}
+
+SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
+	unimplemented("Rf_asS4");
+}
+
+static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
+}
+
+SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) {
+	return R_tryEvalInternal(x, y, ErrorOccurred, 0);
+}
+
+SEXP R_tryEvalSilent(SEXP x, SEXP y, int *ErrorOccurred) {
+	return R_tryEvalInternal(x, y, ErrorOccurred, 1);
+}
+
+double R_atof(const char *str) {
+	unimplemented("R_atof");
+	return 0;
+}
+
+double R_strtod(const char *c, char **end) {
+	unimplemented("R_strtod");
+	return 0;
+}
+
+SEXP R_PromiseExpr(SEXP x) {
+	return unimplemented("R_PromiseExpr");
+}
+
+SEXP R_ClosureExpr(SEXP x) {
+	return unimplemented("R_ClosureExpr");
+}
+
+SEXP R_forceAndCall(SEXP e, int n, SEXP rho) {
+	return unimplemented("R_forceAndCall");
+}
+
+SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) {
+	return unimplemented("R_MakeExternalPtr");
+}
+
+void *R_ExternalPtrAddr(SEXP s) {
+	return unimplemented("R_ExternalPtrAddr");
+}
+
+SEXP R_ExternalPtrTag(SEXP s) {
+	return unimplemented("R_ExternalPtrTag");
+}
+
+SEXP R_ExternalPtrProt(SEXP s) {
+	return unimplemented("R_ExternalPtrProt");
+}
+
+void R_SetExternalPtrAddr(SEXP s, void *p) {
+	unimplemented("R_SetExternalPtrAddr");
+}
+
+void R_SetExternalPtrTag(SEXP s, SEXP tag) {
+	unimplemented("R_SetExternalPtrTag");
+}
+
+void R_SetExternalPtrProtected(SEXP s, SEXP p) {
+	unimplemented("R_SetExternalPtrProtected");
+}
+
+void R_ClearExternalPtr(SEXP s) {
+	R_SetExternalPtrAddr(s, NULL);
+}
+
+void R_RegisterFinalizer(SEXP s, SEXP fun) {
+	// TODO implement, but not fail for now
+}
+void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) {
+	// TODO implement, but not fail for now
+}
+
+void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) {
+	// TODO implement, but not fail for now
+
+}
+
+void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) {
+	// TODO implement, but not fail for now
+}
+
+void R_RunPendingFinalizers(void) {
+	// TODO implement, but not fail for now
+}
+
+SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit) {
+	unimplemented("R_MakeWeakRef");
+}
+
+SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit) {
+	unimplemented("R_MakeWeakRefC");
+}
+
+SEXP R_WeakRefKey(SEXP w) {
+	unimplemented("R_WeakRefKey");
+}
+
+SEXP R_WeakRefValue(SEXP w) {
+	unimplemented("R_WeakRefValue");
+}
+
+void R_RunWeakRefFinalizer(SEXP w) {
+	// TODO implement, but not fail for now
+}
+
+SEXP R_do_slot(SEXP obj, SEXP name) {
+	return unimplemented("R_do_slot");
+}
+
+SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
+	return unimplemented("R_do_slot_assign");
+}
+
+int R_has_slot(SEXP obj, SEXP name) {
+	return (int) unimplemented("R_has_slot");
+}
+
+SEXP R_do_MAKE_CLASS(const char *what) {
+	return unimplemented("R_do_MAKE_CLASS");
+}
+
+SEXP R_getClassDef (const char *what) {
+	return unimplemented("R_getClassDef");
+}
+
+SEXP R_do_new_object(SEXP class_def) {
+	return unimplemented("R_do_new_object");
+}
+
+int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) {
+	return (int) unimplemented("R_check_class_and_super");
+}
+
+int R_check_class_etc (SEXP x, const char **valid) {
+	return (int) unimplemented("R_check_class_etc");
+}
+
+SEXP R_PreserveObject(SEXP x) {
+	return newObjectRef(x);
+}
+
+void R_ReleaseObject(SEXP x) {
+	releaseObjectRef(x);
+}
+
+void R_dot_Last(void) {
+	unimplemented("R_dot_Last");
+}
+
+
+Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
+	return (Rboolean) unimplemented("R_compute_identical");
+}
+
+void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
+	unimplemented("Rf_copyListMatrix");
+}
+
+void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
+	unimplemented("Rf_copyMatrix");
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c
new file mode 100644
index 0000000000..f9ea65f0db
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <rffiutils.h>
+
+double Rf_dnorm(double a, double b, double c, int d) {
+    unimplemented("Rf_dnorm");
+    return 0;
+}
+
+double Rf_dnorm4(double a, double b, double c, int d) {
+    return Rf_dnorm(a, b, c, d);
+}
+
+double Rf_pnorm(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pnorm");
+    return 0;
+}
+
+double Rf_pnorm5(double a, double b, double c, int d, int e) {
+    return Rf_pnorm(a, b, c, d, e);
+}
+
+double Rf_qnorm(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qnorm");
+    return 0;
+}
+
+double Rf_qnorm5(double a, double b, double c, int d, int e) {
+    return Rf_qnorm(a, b, c, d, e);
+}
+
+double Rf_rnorm(double a, double b) {
+    unimplemented("Rf_rnorm");
+    return 0;
+}
+
+void Rf_pnorm_both(double a, double * b, double * c, int d, int e) {
+    unimplemented("Rf_pnorm_both");
+}
+
+double Rf_dunif(double a, double b, double c, int d) {
+    unimplemented("Rf_dunif");
+    return 0;
+}
+
+double Rf_punif(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_punif");
+    return 0;
+}
+
+double Rf_qunif(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qunif");
+    return 0;
+}
+
+double Rf_runif(double a, double b) {
+    unimplemented("Rf_runif");
+    return 0;
+}
+
+double Rf_dgamma(double a, double b, double c, int d) {
+    unimplemented("Rf_dgamma");
+    return 0;
+}
+
+double Rf_pgamma(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pgamma");
+    return 0;
+}
+
+double Rf_qgamma(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qgamma");
+    return 0;
+}
+
+double Rf_rgamma(double a, double b) {
+    unimplemented("Rf_rgamma");
+    return 0;
+}
+
+double Rf_log1pmx(double a) {
+    unimplemented("Rf_log1pmx");
+    return 0;
+}
+
+double Rf_log1pexp(double a) {
+    unimplemented("Rf_log1pexp");
+    return 0;
+}
+
+double Rf_lgamma1p(double a) {
+    unimplemented("Rf_lgamma1p");
+    return 0;
+}
+
+double Rf_logspace_add(double a, double b) {
+    unimplemented("Rf_logspace_add");
+    return 0;
+}
+
+double Rf_logspace_sub(double a, double b) {
+    unimplemented("Rf_logspace_sub");
+    return 0;
+}
+
+double Rf_dbeta(double a, double b, double c, int d) {
+    unimplemented("Rf_dbeta");
+    return 0;
+}
+
+double Rf_pbeta(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pbeta");
+    return 0;
+}
+
+double Rf_qbeta(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qbeta");
+    return 0;
+}
+
+double Rf_rbeta(double a, double b) {
+    unimplemented("Rf_rbeta");
+    return 0;
+}
+
+double Rf_dlnorm(double a, double b, double c, int d) {
+    unimplemented("Rf_dlnorm");
+    return 0;
+}
+
+double Rf_plnorm(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_plnorm");
+    return 0;
+}
+
+double Rf_qlnorm(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qlnorm");
+    return 0;
+}
+
+double Rf_rlnorm(double a, double b) {
+    unimplemented("Rf_rlnorm");
+    return 0;
+}
+
+double Rf_dchisq(double a, double b, int c) {
+    unimplemented("Rf_dchisq");
+    return 0;
+}
+
+double Rf_pchisq(double a, double b, int c, int d) {
+    unimplemented("Rf_pchisq");
+    return 0;
+}
+
+double Rf_qchisq(double a, double b, int c, int d) {
+    unimplemented("Rf_qchisq");
+    return 0;
+}
+
+double Rf_rchisq(double a) {
+    unimplemented("Rf_rchisq");
+    return 0;
+}
+
+double Rf_dnchisq(double a, double b, double c, int d) {
+    unimplemented("Rf_dnchisq");
+    return 0;
+}
+
+double Rf_pnchisq(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pnchisq");
+    return 0;
+}
+
+double Rf_qnchisq(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qnchisq");
+    return 0;
+}
+
+double Rf_rnchisq(double a, double b) {
+    unimplemented("Rf_rnchisq");
+    return 0;
+}
+
+double Rf_df(double a, double b, double c, int d) {
+    unimplemented("Rf_df");
+    return 0;
+}
+
+double Rf_pf(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pf");
+    return 0;
+}
+
+double Rf_qf(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qf");
+    return 0;
+}
+
+double Rf_rf(double a, double b) {
+    unimplemented("Rf_rf");
+    return 0;
+}
+
+double Rf_dt(double a, double b, int c) {
+    unimplemented("Rf_dt");
+    return 0;
+}
+
+double Rf_pt(double a, double b, int c, int d) {
+    unimplemented("Rf_pt");
+    return 0;
+}
+
+double Rf_qt(double a, double b, int c, int d) {
+    unimplemented("Rf_qt");
+    return 0;
+}
+
+double Rf_rt(double a) {
+    unimplemented("Rf_rt");
+    return 0;
+}
+
+double Rf_dbinom(double a, double b, double c, int d) {
+    unimplemented("Rf_dbinom");
+    return 0;
+}
+
+double Rf_pbinom(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pbinom");
+    return 0;
+}
+
+double Rf_qbinom(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qbinom");
+    return 0;
+}
+
+double Rf_rbinom(double a, double b) {
+    unimplemented("Rf_rbinom");
+    return 0;
+}
+
+void Rf_rmultinom(int a, double* b, int c, int* d) {
+    unimplemented("Rf_rmultinom");
+}
+
+double Rf_dcauchy(double a, double b, double c, int d) {
+    unimplemented("Rf_dcauchy");
+    return 0;
+}
+
+double Rf_pcauchy(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pcauchy");
+    return 0;
+}
+
+double Rf_qcauchy(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qcauchy");
+    return 0;
+}
+
+double Rf_rcauchy(double a, double b) {
+    unimplemented("Rf_rcauchy");
+    return 0;
+}
+
+double Rf_dexp(double a, double b, int c) {
+    unimplemented("Rf_dexp");
+    return 0;
+}
+
+double Rf_pexp(double a, double b, int c, int d) {
+    unimplemented("Rf_pexp");
+    return 0;
+}
+
+double Rf_qexp(double a, double b, int c, int d) {
+    unimplemented("Rf_qexp");
+    return 0;
+}
+
+double Rf_rexp(double a) {
+    unimplemented("Rf_rexp");
+    return 0;
+}
+
+double Rf_dgeom(double a, double b, int c) {
+    unimplemented("Rf_dgeom");
+    return 0;
+}
+
+double Rf_pgeom(double a, double b, int c, int d) {
+    unimplemented("Rf_pgeom");
+    return 0;
+}
+
+double Rf_qgeom(double a, double b, int c, int d) {
+    unimplemented("Rf_qgeom");
+    return 0;
+}
+
+double Rf_rgeom(double a) {
+    unimplemented("Rf_rgeom");
+    return 0;
+}
+
+double Rf_dhyper(double a, double b, double c, double d, int e) {
+    unimplemented("Rf_dhyper");
+    return 0;
+}
+
+double Rf_phyper(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_phyper");
+    return 0;
+}
+
+double Rf_qhyper(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_qhyper");
+    return 0;
+}
+
+double Rf_rhyper(double a, double b, double c) {
+    unimplemented("Rf_rhyper");
+    return 0;
+}
+
+double Rf_dnbinom(double a, double b, double c, int d) {
+    unimplemented("Rf_dnbinom");
+    return 0;
+}
+
+double Rf_pnbinom(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pnbinom");
+    return 0;
+}
+
+double Rf_qnbinom(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qnbinom");
+    return 0;
+}
+
+double Rf_rnbinom(double a, double b) {
+    unimplemented("Rf_rnbinom");
+    return 0;
+}
+
+double Rf_dnbinom_mu(double a, double b, double c, int d) {
+    unimplemented("Rf_dnbinom_mu");
+    return 0;
+}
+
+double Rf_pnbinom_mu(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pnbinom_mu");
+    return 0;
+}
+
+double Rf_qnbinom_mu(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qnbinom_mu");
+    return 0;
+}
+
+double Rf_rnbinom_mu(double a, double b) {
+    unimplemented("Rf_rnbinom_mu");
+    return 0;
+}
+
+double Rf_dpois(double a, double b, int c) {
+    unimplemented("Rf_dpois");
+    return 0;
+}
+
+double Rf_ppois(double a, double b, int c, int d) {
+    unimplemented("Rf_ppois");
+    return 0;
+}
+
+double Rf_qpois(double a, double b, int c, int d) {
+    unimplemented("Rf_qpois");
+    return 0;
+}
+
+double Rf_rpois(double a) {
+    unimplemented("Rf_rpois");
+    return 0;
+}
+
+double Rf_dweibull(double a, double b, double c, int d) {
+    unimplemented("Rf_dweibull");
+    return 0;
+}
+
+double Rf_pweibull(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pweibull");
+    return 0;
+}
+
+double Rf_qweibull(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qweibull");
+    return 0;
+}
+
+double Rf_rweibull(double a, double b) {
+    unimplemented("Rf_rweibull");
+    return 0;
+}
+
+double Rf_dlogis(double a, double b, double c, int d) {
+    unimplemented("Rf_dlogis");
+    return 0;
+}
+
+double Rf_plogis(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_plogis");
+    return 0;
+}
+
+double Rf_qlogis(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qlogis");
+    return 0;
+}
+
+double Rf_rlogis(double a, double b) {
+    unimplemented("Rf_rlogis");
+    return 0;
+}
+
+double Rf_dnbeta(double a, double b, double c, double d, int e) {
+    unimplemented("Rf_dnbeta");
+    return 0;
+}
+
+double Rf_pnbeta(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_pnbeta");
+    return 0;
+}
+
+double Rf_qnbeta(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_qnbeta");
+    return 0;
+}
+
+double Rf_rnbeta(double a, double b, double c) {
+    unimplemented("Rf_rnbeta");
+    return 0;
+}
+
+double Rf_dnf(double a, double b, double c, double d, int e) {
+    unimplemented("Rf_dnf");
+    return 0;
+}
+
+double Rf_pnf(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_pnf");
+    return 0;
+}
+
+double Rf_qnf(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_qnf");
+    return 0;
+}
+
+double Rf_dnt(double a, double b, double c, int d) {
+    unimplemented("Rf_dnt");
+    return 0;
+}
+
+double Rf_pnt(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pnt");
+    return 0;
+}
+
+double Rf_qnt(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qnt");
+    return 0;
+}
+
+double Rf_ptukey(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_ptukey");
+    return 0;
+}
+
+double Rf_qtukey(double a, double b, double c, double d, int e, int f) {
+    unimplemented("Rf_qtukey");
+    return 0;
+}
+
+double Rf_dwilcox(double a, double b, double c, int d) {
+    unimplemented("Rf_dwilcox");
+    return 0;
+}
+
+double Rf_pwilcox(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_pwilcox");
+    return 0;
+}
+
+double Rf_qwilcox(double a, double b, double c, int d, int e) {
+    unimplemented("Rf_qwilcox");
+    return 0;
+}
+
+double Rf_rwilcox(double a, double b) {
+    unimplemented("Rf_rwilcox");
+    return 0;
+}
+
+double Rf_dsignrank(double a, double b, int c) {
+    unimplemented("Rf_dsignrank");
+    return 0;
+}
+
+double Rf_psignrank(double a, double b, int c, int d) {
+    unimplemented("Rf_psignrank");
+    return 0;
+}
+
+double Rf_qsignrank(double a, double b, int c, int d) {
+    unimplemented("Rf_qsignrank");
+    return 0;
+}
+
+double Rf_rsignrank(double a) {
+    unimplemented("Rf_rsignrank");
+    return 0;
+}
+
+double Rf_gammafn(double a) {
+    unimplemented("Rf_gammafn");
+    return 0;
+}
+
+double Rf_lgammafn(double a) {
+    unimplemented("Rf_lgammafn");
+    return 0;
+}
+
+double Rf_lgammafn_sign(double a, int* b) {
+    unimplemented("Rf_lgammafn_sign");
+    return 0;
+}
+
+void Rf_dpsifn(double a, int b, int c, int d, double* e, int* f, int* g) {
+    unimplemented("Rf_dpsifn");
+}
+
+double Rf_psigamma(double a, double b) {
+    unimplemented("Rf_psigamma");
+    return 0;
+}
+
+double Rf_digamma(double a) {
+    unimplemented("Rf_digamma");
+    return 0;
+}
+
+double Rf_trigamma(double a) {
+    unimplemented("Rf_trigamma");
+    return 0;
+}
+
+double Rf_tetragamma(double a) {
+    unimplemented("Rf_tetragamma");
+    return 0;
+}
+
+double Rf_pentagamma(double a) {
+    unimplemented("Rf_pentagamma");
+    return 0;
+}
+
+double Rf_beta(double a, double b) {
+    unimplemented("Rf_beta");
+    return 0;
+}
+
+double Rf_lbeta(double a, double b) {
+    unimplemented("Rf_lbeta");
+    return 0;
+}
+
+double Rf_choose(double a, double b) {
+    unimplemented("Rf_choose");
+    return 0;
+}
+
+double Rf_lchoose(double a, double b) {
+    unimplemented("Rf_lchoose");
+    return 0;
+}
+
+double Rf_bessel_i(double a, double b, double c) {
+    unimplemented("Rf_bessel_i");
+    return 0;
+}
+
+double Rf_bessel_j(double a, double b) {
+    unimplemented("Rf_bessel_j");
+    return 0;
+}
+
+double Rf_bessel_k(double a, double b, double c) {
+    unimplemented("Rf_bessel_k");
+    return 0;
+}
+
+double Rf_bessel_y(double a, double b) {
+    unimplemented("Rf_bessel_y");
+    return 0;
+}
+
+double Rf_bessel_i_ex(double a, double b, double c, double * d) {
+    unimplemented("Rf_bessel_i_ex");
+    return 0;
+}
+
+double Rf_bessel_j_ex(double a, double b, double * c) {
+    unimplemented("Rf_bessel_j_ex");
+    return 0;
+}
+
+double Rf_bessel_k_ex(double a, double b, double c, double * d) {
+    unimplemented("Rf_bessel_k_ex");
+    return 0;
+}
+
+double Rf_bessel_y_ex(double a, double b, double * c) {
+    unimplemented("Rf_bessel_y_ex");
+    return 0;
+}
+
+int Rf_imax2(int x, int y) {
+    return x > y ? x : y;
+}
+
+int Rf_imin2(int x, int y) {
+    return x > y ? y : x;
+}
+
+double Rf_fmax2(double x, double y) {
+    return x > y ? x : y;
+}
+
+double Rf_fmin2(double x, double y) {
+    return x > y ? y : x;
+}
+
+double Rf_sign(double a) {
+    unimplemented("Rf_sign");
+    return 0;
+}
+
+double Rf_fprec(double a, double b) {
+    unimplemented("Rf_fprec");
+    return 0;
+}
+
+double Rf_fsign(double a, double b) {
+    unimplemented("Rf_fsign");
+    return 0;
+}
+
+double Rf_ftrunc(double a) {
+    unimplemented("Rf_ftrunc");
+    return 0;
+}
+
+double Rf_cospi(double a) {
+    unimplemented("Rf_cospi");
+    return 0;
+}
+
+double Rf_sinpi(double a) {
+    unimplemented("Rf_sinpi");
+    return 0;
+}
+
+double Rf_tanpi(double a) {
+    unimplemented("Rf_tanpi");
+    return 0;
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c
new file mode 100644
index 0000000000..0c49103831
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Utils.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <rffiutils.h>
+
+void R_CheckStack(void) {
+    // TODO: check for stack overflow
+    // ignored
+}
+
+void R_CheckStack2(size_t extra) {
+    // TODO: check for stack overflow
+    // ignored
+}
+
+void R_CheckUserInterrupt(void) {
+    // ignored
+}
+
+void Rf_onintr()
+{
+    // TODO: implement interrupt handling, signal errors
+    // ignored
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c
new file mode 100644
index 0000000000..5ebdbc607d
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <rffiutils.h>
+
+extern void dqrdc2_(double *x, int *ldx, int *n, int *p, double *tol, int *rank, double *qraux, int* pivot, double *work);
+extern void dqrcf_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *b, int* info);
+extern void dqrls_(double *x, int *n, int *p, double *y, int *ny, double *tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work);
+
+void call_dqrdc2(double *x, int ldx, int n, int p, double tol, int *rank, double *qraux, int* pivot, double *work) {
+	dqrdc2_(x, &ldx, &n, &p, &tol, rank, qraux, pivot, work);
+}
+
+void call_dqrcf(double *x, int n, int k, double *qraux, double *y, int ny, double *b, int* info) {
+	dqrcf_(x, &n, &k, qraux, y, &ny, b, info);
+}
+
+void call_dqrls(double *x, int n, int p, double *y, int ny, double tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work) {
+	dqrls_(x, &n, &p, y, &ny, &tol, b, rsd, qty, k, jpvt, qraux, work);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
new file mode 100644
index 0000000000..2073ad00fe
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <rffiutils.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glob.h>
+#include <sys/utsname.h>
+#include <errno.h>
+
+
+void call_uname(void (*call_uname_setfields)(char *sysname, char *release, char *version, char *machine, char *nodename)) {
+	struct utsname name;
+
+	uname(&name);
+	call_uname_setfields(name.sysname, name.release, name.version, name.machine, name.nodename);
+}
+
+void call_glob(char *pattern, void *closure) {
+	void (*call_addpath)(char *path) = closure;
+
+	glob_t globstruct;
+	int rc = glob(pattern, 0, NULL, &globstruct);
+	if (rc == 0) {
+		int i;
+		for (i = 0; i < globstruct.gl_pathc; i++) {
+			char *path = globstruct.gl_pathv[i];
+			call_addpath(path);
+		}
+	}
+}
+
+void call_readlink(void (*call_setresult)(char *link, int errno), char *path) {
+	char *link = NULL;
+	int cerrno = 0;
+    char buf[4096];
+    int len = readlink(path, buf, 4096);
+    if (len == -1) {
+    	cerrno = errno;
+    } else {
+    	buf[len] = 0;
+    	link = buf;
+    }
+	call_setresult(link, cerrno);
+}
+
+void call_strtol(void (*call_setresult)(long result, int errno), char *s, int base) {
+    long rc = strtol(s, NULL, base);
+	call_setresult(rc, errno);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
new file mode 100644
index 0000000000..c52ed611c6
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
@@ -0,0 +1,26 @@
+#include <rffiutils.h>
+
+typedef void (*callVoid0func)();
+
+Call_callVoid0(long address) {
+//	jmp_buf error_jmpbuf;
+//	callEnter(env, &error_jmpbuf);
+//	if (!setjmp(error_jmpbuf)) {
+		callVoid0func call1 = (callVoid0func) address;
+		(*call1)();
+//	}
+//	callExit(env);
+}
+
+typedef void (*callVoid1func)(SEXP arg1);
+
+
+Call_callVoid1(long address, TruffleObject *arg1) {
+//	jmp_buf error_jmpbuf;
+//	callEnter(env, &error_jmpbuf);
+//	if (!setjmp(error_jmpbuf)) {
+		callVoid0func call1 = (callVoid0func) address;
+		(*call1)(arg1);
+//	}
+//	callExit(env);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
new file mode 100644
index 0000000000..cc68ca6f0a
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <rffiutils.h>
+
+extern void ilaver_(int *major, int *minor, int *patch);
+
+void call_ilaver(int* version) {
+	int major;
+	int minor;
+	int patch;
+	ilaver_(&major, &minor, &patch);
+	version[0] = major;
+	version[1] = minor;
+	version[2] = patch;
+}
+
+extern int dgeev_(char *jobVL, char *jobVR, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info);
+
+int call_dgeev(char jobVL, char jobVR, int n, double *a, int lda, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, double *work, int lwork) {
+    int info;
+    dgeev_(&jobVL, &jobVR, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info);
+    return info;
+}
+
+extern int dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info);
+
+
+int call_dgeqp3(int m, int n, double *a, int lda, int *jpvt, double *tau, double *work, int lwork) {
+    int info;
+    dgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info);
+    return info;
+}
+
+extern int dormqr_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info);
+
+int call_dormqr(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, double *work, int lwork) {
+    int info;
+    dormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
+    return info;
+}
+
+extern int dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info);
+
+
+int call_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double *a, int lda, double *b, int ldb) {
+    int info;
+    dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, a, &lda, b, &ldb, &info);
+    return info;
+}
+
+extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
+
+int call_dgetrf(int m, int n, double *a, int lda, int *ipiv) {
+    int info;
+    dgetrf_(&m, &n, a, &lda, ipiv, &info);
+    return info;
+}
+
+extern int dpotrf_(char *uplo, int *n, double *a, int *lda, int *info);
+
+int call_dpotrf(char uplo, int n, double *a, int lda) {
+    int info;
+    dpotrf_(&uplo, &n, a, &lda, &info);
+    return info;
+}
+
+extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info);
+
+int call_dpstrf(char uplo, int n, double *a, int lda, int *piv, int *rank, double tol, double *work) {
+    int info;
+    dpstrf_(&uplo, &n, a, &lda, piv, rank, &tol, work, &info);
+    return info;
+}
+
+extern int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
+
+int call_dgesv(int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb) {
+    int info;
+    dgesv_(&n, &nrhs, a, &lda, ipiv, b, &ldb, &info);
+    return info;
+}
+
+extern double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work);
+
+double call_dlange(char norm, int m, int n, double *a, int lda, double *work) {
+    double info = dlange_(&norm, &m, &n, a, &lda, work);
+    return info;
+}
+
+extern int dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info);
+
+int call_dgecon(char norm, int n, double *a, int lda, double anorm, double *rcond, double *work, int *iwork) {
+    int info;
+    dgecon_(&norm, &n, a, &lda, &anorm, rcond, work, iwork, &info);
+    return info;
+}
+
+extern int dsyevr_(char *jobz, char *range, char *uplo, int *n, double* a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int* m, double* w,
+                double* z, int *ldz, int* isuppz, double* work, int *lwork, int* iwork, int *liwork, int* info);
+
+int call_dsyevr(char jobz, char range, char uplo, int n, double *a, int lda, double vl, double vu, int il, int iu, double abstol, int *m, double *w,
+		                    double *z, int ldz, int *isuppz, double *work, int lwork, int *iwork, int liwork) {
+    int info;
+    dsyevr_(&jobz, &range, &uplo, &n, a, &lda, &vl, &vu, &il, &iu, &abstol, m, w,
+            z, &ldz, isuppz, work, &lwork, iwork, &liwork, &info);
+    return info;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c
new file mode 100644
index 0000000000..28be2cb058
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c
@@ -0,0 +1,65 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2015,  The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+#include <rffiutils.h>
+
+#define PCRE_INFO_CAPTURECOUNT       2
+#define PCRE_INFO_NAMEENTRYSIZE      7
+#define PCRE_INFO_NAMECOUNT          8
+#define PCRE_INFO_NAMETABLE          9
+
+//char *pcre_maketables();
+void *pcre_compile(char *pattern, int options, char **errorMessage, int *errOffset, char *tables);
+//int  pcre_exec(void *code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize);
+int pcre_fullinfo(void *code, void *extra, int what, void *where);
+//void pcre_free(void *code);
+
+void call_compile(void *closure, char *pattern, int options, long tables) {
+	void (*call_makeresult)(long result, char *errMsg, int errOffset) = closure;
+	char *errorMessage;
+	int errOffset;
+	void *pcre_result = pcre_compile(pattern, options, &errorMessage, &errOffset, (char*) tables);
+	call_makeresult((long) pcre_result, errorMessage, errOffset);
+}
+
+int call_getcapturecount(long code, long extra) {
+    int captureCount;
+	int rc = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_CAPTURECOUNT, &captureCount);
+    return rc < 0 ? rc : captureCount;
+}
+
+int call_getcapturenames(void *closure, long code, long extra) {
+	void (*call_setcapturename)(int i, char *name) = closure;
+    int nameCount;
+    int nameEntrySize;
+    char* nameTable;
+    int res;
+	res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMECOUNT, &nameCount);
+    if (res < 0) {
+        return res;
+    }
+    res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize);
+    if (res < 0) {
+        return res;
+    }
+	res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMETABLE, &nameTable);
+    if (res < 0) {
+        return res;
+    }
+    // from GNU R's grep.c
+	for(int i = 0; i < nameCount; i++) {
+	    char* entry = nameTable + nameEntrySize * i;
+	    int captureNum = (entry[0] << 8) + entry[1] - 1;
+	    call_setcapturename(captureNum, entry + 2);
+    }
+    return res;
+
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
new file mode 100644
index 0000000000..d4e0e017db
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifndef CALLBACKS_H
+#define CALLBACKS_H
+
+#define CADDR_x 0
+#define CADR_x 1
+#define CAR_x 2
+#define CDDR_x 3
+#define CDR_x 4
+#define DUPLICATE_ATTRIB_x 5
+#define ENCLOS_x 6
+#define GetRNGstate_x 7
+#define INTEGER_x 8
+#define IS_S4_OBJECT_x 9
+#define LENGTH_x 10
+#define LOGICAL_x 11
+#define NAMED_x 12
+#define OBJECT_x 13
+#define PRCODE_x 14
+#define PRENV_x 15
+#define PRINTNAME_x 16
+#define PRSEEN_x 17
+#define PRVALUE_x 18
+#define PutRNGstate_x 19
+#define RAW_x 20
+#define RDEBUG_x 21
+#define REAL_x 22
+#define RSTEP_x 23
+#define R_BaseEnv_x 24
+#define R_BaseNamespace_x 25
+#define R_BindingIsLocked_x 26
+#define R_CHAR_x 27
+#define R_CleanUp_x 28
+#define R_ExternalPtrAddr_x 29
+#define R_ExternalPtrProt_x 30
+#define R_ExternalPtrTag_x 31
+#define R_FindNamespace_x 32
+#define R_GetConnection_x 33
+#define R_GlobalContext_x 34
+#define R_GlobalEnv_x 35
+#define R_HomeDir_x 36
+#define R_Interactive_x 37
+#define R_MakeExternalPtr_x 38
+#define R_NamespaceRegistry_x 39
+#define R_NewHashedEnv_x 40
+#define R_ParseVector_x 41
+#define R_PromiseExpr_x 42
+#define R_ReadConnection_x 43
+#define R_SetExternalPtrAddr_x 44
+#define R_SetExternalPtrProt_x 45
+#define R_SetExternalPtrTag_x 46
+#define R_ToplevelExec_x 47
+#define R_WriteConnection_x 48
+#define R_computeIdentical_x 49
+#define R_do_MAKE_CLASS_x 50
+#define R_getContextCall_x 51
+#define R_getContextEnv_x 52
+#define R_getContextFun_x 53
+#define R_getContextSrcRef_x 54
+#define R_getGlobalFunctionContext_x 55
+#define R_getParentFunctionContext_x 56
+#define R_insideBrowser_x 57
+#define R_isEqual_x 58
+#define R_isGlobal_x 59
+#define R_lsInternal3_x 60
+#define R_new_custom_connection_x 61
+#define R_tryEval_x 62
+#define Rf_GetOption1_x 63
+#define Rf_PairToVectorList_x 64
+#define Rf_ScalarDouble_x 65
+#define Rf_ScalarInteger_x 66
+#define Rf_ScalarLogical_x 67
+#define Rf_ScalarString_x 68
+#define Rf_allocateArray_x 69
+#define Rf_allocateMatrix_x 70
+#define Rf_allocateVector_x 71
+#define Rf_anyDuplicated_x 72
+#define Rf_asChar_x 73
+#define Rf_asInteger_x 74
+#define Rf_asLogical_x 75
+#define Rf_asReal_x 76
+#define Rf_classgets_x 77
+#define Rf_coerceVector_x 78
+#define Rf_cons_x 79
+#define Rf_copyListMatrix_x 80
+#define Rf_copyMatrix_x 81
+#define Rf_defineVar_x 82
+#define Rf_duplicate_x 83
+#define Rf_error_x 84
+#define Rf_eval_x 85
+#define Rf_findVar_x 86
+#define Rf_findVarInFrame_x 87
+#define Rf_findVarInFrame3_x 88
+#define Rf_findfun_x 89
+#define Rf_getAttrib_x 90
+#define Rf_gsetVar_x 91
+#define Rf_inherits_x 92
+#define Rf_install_x 93
+#define Rf_installChar_x 94
+#define Rf_isNull_x 95
+#define Rf_isString_x 96
+#define Rf_lengthgets_x 97
+#define Rf_mkCharLenCE_x 98
+#define Rf_ncols_x 99
+#define Rf_nrows_x 100
+#define Rf_setAttrib_x 101
+#define Rf_warning_x 102
+#define Rf_warningcall_x 103
+#define Rprintf_x 104
+#define SETCADR_x 105
+#define SETCAR_x 106
+#define SETCDR_x 107
+#define SET_RDEBUG_x 108
+#define SET_RSTEP_x 109
+#define SET_STRING_ELT_x 110
+#define SET_SYMVALUE_x 111
+#define SET_TAG_x 112
+#define SET_TYPEOF_FASTR_x 113
+#define SET_VECTOR_ELT_x 114
+#define STRING_ELT_x 115
+#define SYMVALUE_x 116
+#define TAG_x 117
+#define TYPEOF_x 118
+#define VECTOR_ELT_x 119
+#define getConnectionClassString_x 120
+#define getOpenModeString_x 121
+#define getSummaryDescription_x 122
+#define isSeekable_x 123
+#define unif_rand_x 124
+
+#define CALLBACK_TABLE_SIZE 125
+
+extern void* callbacks[];
+
+// TODO Use an array indexed by above
+
+// This is the complete set , including those not yet implemented
+
+typedef SEXP (*call_Rf_ScalarInteger)(int value);
+typedef SEXP (*call_Rf_ScalarReal)(double value);
+typedef SEXP (*call_Rf_ScalarString)(SEXP value);
+typedef SEXP (*call_Rf_ScalarLogical)(int value);
+typedef SEXP (*call_Rf_allocateVector)(SEXPTYPE t, R_xlen_t len);
+typedef SEXP (*call_Rf_allocArray)(SEXPTYPE t, SEXP dims);
+typedef SEXP (*call_Rf_alloc3DArray)(SEXPTYPE t, int x, int y, int z);
+typedef SEXP (*call_Rf_allocMatrix)(SEXPTYPE mode, int nrow, int ncol);
+typedef SEXP (*call_Rf_allocList)(int x);
+typedef SEXP (*call_Rf_allocSExp)(SEXPTYPE t);
+typedef SEXP (*call_Rf_cons)(SEXP car, SEXP cdr);
+typedef void (*call_Rf_defineVar)(SEXP symbol, SEXP value, SEXP rho);
+typedef void (*call_Rf_setVar)(SEXP x, SEXP y, SEXP z);
+typedef SEXP (*call_Rf_dimgets)(SEXP x, SEXP y);
+typedef SEXP (*call_Rf_dimnamesgets)(SEXP x, SEXP y);
+typedef SEXP (*call_Rf_eval)(SEXP expr, SEXP env);
+typedef SEXP (*call_Rf_findFun)(SEXP symbol, SEXP rho);
+typedef SEXP (*call_Rf_findVar)(SEXP sym, SEXP rho);
+typedef SEXP (*call_Rf_findVarInFrame)(SEXP rho, SEXP sym);
+typedef SEXP (*call_Rf_findVarInFrame3)(SEXP rho, SEXP sym, Rboolean b);
+typedef SEXP (*call_Rf_getAttrib)(SEXP vec, SEXP name);
+typedef SEXP (*call_Rf_GetOption1)(SEXP tag);
+typedef SEXP (*call_Rf_setAttrib)(SEXP vec, SEXP name, SEXP val);
+typedef SEXP (*call_Rf_duplicate)(SEXP x);
+typedef SEXP (*call_Rf_shallow_duplicate)(SEXP x);
+typedef SEXP (*call_Rf_coerceVector)(SEXP x, SEXPTYPE mode);
+typedef R_xlen_t (*call_Rf_any_duplicated)(SEXP x, Rboolean from_last);
+typedef SEXP (*call_Rf_duplicated)(SEXP x, Rboolean y);
+typedef SEXP (*call_Rf_applyClosure)(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b);
+typedef void (*call_Rf_copyMostAttrib)(SEXP x, SEXP y);
+typedef void (*call_Rf_copyVector)(SEXP x, SEXP y);
+typedef int (*call_Rf_countContexts)(int x, int y);
+typedef Rboolean (*call_Rf_inherits)(SEXP x, const char * klass);
+typedef Rboolean (*call_Rf_isReal)(SEXP x);
+typedef Rboolean (*call_Rf_isSymbol)(SEXP x);
+typedef Rboolean (*call_Rf_isComplex)(SEXP x);
+typedef Rboolean (*call_Rf_isEnvironment)(SEXP x);
+typedef Rboolean (*call_Rf_isExpression)(SEXP x);
+typedef Rboolean (*call_Rf_isLogical)(SEXP x);
+typedef Rboolean (*call_Rf_isObject)(SEXP s);
+typedef void (*call_Rf_PrintValue)(SEXP x);
+typedef SEXP (*call_Rf_install)(const char *name);
+typedef SEXP (*call_Rf_installChar)(SEXP charsxp);
+typedef Rboolean (*call_Rf_isNull)(SEXP s);
+typedef Rboolean (*call_Rf_isString)(SEXP s);
+typedef Rboolean (*call_R_cycle_detected)(SEXP s, SEXP child);
+typedef cetype_t (*call_Rf_getCharCE)(SEXP x);
+typedef SEXP (*call_Rf_mkChar)(const char *x);
+typedef SEXP (*call_Rf_mkCharCE)(const char *x, cetype_t y);
+typedef SEXP (*call_Rf_mkCharLen)(const char *x, int y);
+typedef SEXP (*call_Rf_mkCharLenCE)(const char *x, int len, cetype_t enc);
+typedef const char * (*call_Rf_reEnc)(const char *x, cetype_t ce_in, cetype_t ce_out, int subst);
+typedef SEXP (*call_Rf_mkString)(const char *s);
+typedef int (*call_Rf_ncols)(SEXP x);
+typedef int (*call_Rf_nrows)(SEXP x);
+typedef SEXP (*call_Rf_protect)(SEXP x);
+typedef void (*call_Rf_unprotect)(int x);
+typedef void (*call_R_ProtectWithIndex)(SEXP x, PROTECT_INDEX *y);
+typedef void (*call_R_Reprotect)(SEXP x, PROTECT_INDEX y);
+typedef void (*call_Rf_unprotect_ptr)(SEXP x);
+typedef void (*call_Rf_error)(const char *format, ...);
+typedef void (*call_Rf_errorcall)(SEXP x, const char *format, ...);
+typedef void (*call_Rf_warningcall)(SEXP x, const char *format, ...);
+typedef void (*call_Rf_warning)(const char *format, ...);
+typedef void (*call_Rprintf)(const char *format, ...);
+typedef void (*call_Rvprintf)(const char *format, va_list args);
+typedef void (*call_REvprintf)(const char *format, va_list args);
+typedef void (*call_R_FlushConsole)(void);
+typedef void (*call_R_ProcessEvents)(void);
+typedef SEXP (*call_R_NewHashedEnv)(SEXP parent, SEXP size);
+typedef SEXP (*call_Rf_classgets)(SEXP vec, SEXP klass);
+typedef const char *(*call_Rf_translateChar)(SEXP x);
+typedef const char *(*call_Rf_translateChar0)(SEXP x);
+typedef const char *(*call_Rf_translateCharUTF8)(SEXP x);
+typedef SEXP (*call_Rf_lengthgets)(SEXP x, R_len_t y);
+typedef SEXP (*call_Rf_xlengthgets)(SEXP x, R_xlen_t y);
+typedef SEXP (*call_R_lsInternal)(SEXP env, Rboolean all);
+typedef SEXP (*call_R_lsInternal3)(SEXP env, Rboolean all, Rboolean sorted);
+typedef SEXP (*call_Rf_namesgets)(SEXP x, SEXP y);
+typedef SEXP (*call_TAG)(SEXP e);
+typedef SEXP (*call_PRINTNAME)(SEXP e);
+typedef SEXP (*call_CAR)(SEXP e);
+typedef SEXP (*call_CDR)(SEXP e);
+typedef SEXP (*call_CAAR)(SEXP e);
+typedef SEXP (*call_CDAR)(SEXP e);
+typedef SEXP (*call_CADR)(SEXP e);
+typedef SEXP (*call_CDDR)(SEXP e);
+typedef SEXP (*call_CDDDR)(SEXP e);
+typedef SEXP (*call_CADDR)(SEXP e);
+typedef SEXP (*call_CADDDR)(SEXP e);
+typedef SEXP (*call_CAD4R)(SEXP e);
+typedef int (*call_MISSING)(SEXP x);
+typedef void (*call_SET_MISSING)(SEXP x, int v);
+typedef void (*call_SET_TAG)(SEXP x, SEXP y);
+typedef SEXP (*call_SETCAR)(SEXP x, SEXP y);
+typedef SEXP (*call_SETCDR)(SEXP x, SEXP y);
+typedef SEXP (*call_SETCADR)(SEXP x, SEXP y);
+typedef SEXP (*call_SETCADDR)(SEXP x, SEXP y);
+typedef SEXP (*call_SETCADDDR)(SEXP x, SEXP y);
+typedef SEXP (*call_SETCAD4R)(SEXP e, SEXP y);
+typedef SEXP (*call_FORMALS)(SEXP x);
+typedef SEXP (*call_BODY)(SEXP x);
+typedef SEXP (*call_CLOENV)(SEXP x);
+typedef int (*call_RDEBUG)(SEXP x);
+typedef int (*call_RSTEP)(SEXP x);
+typedef int (*call_RTRACE)(SEXP x);
+typedef void (*call_SET_RDEBUG)(SEXP x, int v);
+typedef void (*call_SET_RSTEP)(SEXP x, int v);
+typedef void (*call_SET_RTRACE)(SEXP x, int v);
+typedef void (*call_SET_FORMALS)(SEXP x, SEXP v);
+typedef void (*call_SET_BODY)(SEXP x, SEXP v);
+typedef void (*call_SET_CLOENV)(SEXP x, SEXP v);
+typedef SEXP (*call_SYMVALUE)(SEXP x);
+typedef SEXP (*call_INTERNAL)(SEXP x);
+typedef int (*call_DDVAL)(SEXP x);
+typedef void (*call_SET_DDVAL)(SEXP x, int v);
+typedef void (*call_SET_SYMVALUE)(SEXP x, SEXP v);
+typedef void (*call_SET_INTERNAL)(SEXP x, SEXP v);
+typedef SEXP (*call_FRAME)(SEXP x);
+typedef SEXP (*call_ENCLOS)(SEXP x);
+typedef SEXP (*call_HASHTAB)(SEXP x);
+typedef int (*call_ENVFLAGS)(SEXP x);
+typedef void (*call_SET_ENVFLAGS)(SEXP x, int v);
+typedef void (*call_SET_FRAME)(SEXP x, SEXP v);
+typedef void (*call_SET_ENCLOS)(SEXP x, SEXP v);
+typedef void (*call_SET_HASHTAB)(SEXP x, SEXP v);
+typedef SEXP (*call_PRCODE)(SEXP x);
+typedef SEXP (*call_PRENV)(SEXP x);
+typedef SEXP (*call_PRVALUE)(SEXP x);
+typedef int (*call_PRSEEN)(SEXP x);
+typedef void (*call_SET_PRSEEN)(SEXP x, int v);
+typedef void (*call_SET_PRENV)(SEXP x, SEXP v);
+typedef void (*call_SET_PRVALUE)(SEXP x, SEXP v);
+typedef void (*call_SET_PRCODE)(SEXP x, SEXP v);
+typedef int (*call_LENGTH)(SEXP x);
+typedef int (*call_TRUELENGTH)(SEXP x);
+typedef void (*call_SETLENGTH)(SEXP x, int v);
+typedef void (*call_SET_TRUELENGTH)(SEXP x, int v);
+typedef R_xlen_t (*call_XLENGTH)(SEXP x);
+typedef R_xlen_t (*call_XTRUELENGTH)(SEXP x);
+typedef int (*call_IS_LONG_VEC)(SEXP x);
+typedef int (*call_LEVELS)(SEXP x);
+typedef int (*call_SETLEVELS)(SEXP x, int v);
+typedef int *(*call_LOGICAL)(SEXP x);
+typedef int *(*call_INTEGER)(SEXP x);
+typedef Rbyte *(*call_RAW)(SEXP x);
+typedef double *(*call_REAL)(SEXP x);
+typedef Rcomplex *(*call_COMPLEX)(SEXP x);
+typedef SEXP (*call_STRING_ELT)(SEXP x, R_xlen_t i);
+typedef SEXP (*call_VECTOR_ELT)(SEXP x, R_xlen_t i);
+typedef void (*call_SET_STRING_ELT)(SEXP x, R_xlen_t i, SEXP v);
+typedef SEXP (*call_SET_VECTOR_ELT)(SEXP x, R_xlen_t i, SEXP v);
+typedef SEXP *(*call_STRING_PTR)(SEXP x);
+typedef SEXP *(*call_VECTOR_PTR)(SEXP x);
+typedef SEXP (*call_Rf_asChar)(SEXP x);
+typedef SEXP (*call_Rf_PairToVectorList)(SEXP x);
+typedef SEXP (*call_Rf_VectorToPairList)(SEXP x);
+typedef SEXP (*call_Rf_asCharacterFactor)(SEXP x);
+typedef int (*call_Rf_asLogical)(SEXP x);
+typedef int (*call_Rf_asInteger)(SEXP x);
+typedef double (*call_Rf_asReal)(SEXP x);
+typedef Rcomplex (*call_Rf_asComplex)(SEXP x);
+typedef int (*call_TYPEOF)(SEXP x);
+typedef SEXP (*call_ATTRIB)(SEXP x);
+typedef int (*call_OBJECT)(SEXP x);
+typedef int (*call_MARK)(SEXP x);
+typedef int (*call_NAMED)(SEXP x);
+typedef int (*call_REFCNT)(SEXP x);
+typedef void (*call_SET_OBJECT)(SEXP x, int v);
+typedef void (*call_SET_TYPEOF)(SEXP x, int v);
+typedef SEXP (*call_SET_TYPEOF_FASTR)(SEXP x, int v);
+typedef void (*call_SET_NAMED)(SEXP x, int v);
+typedef void (*call_SET_ATTRIB)(SEXP x, SEXP v);
+typedef void (*call_DUPLICATE_ATTRIB)(SEXP to, SEXP from);
+typedef int (*call_IS_S4_OBJECT)(SEXP x);
+typedef void (*call_SET_S4_OBJECT)(SEXP x);
+typedef void (*call_UNSET_S4_OBJECT)(SEXP x);
+typedef Rboolean (*call_R_ToplevelExec)(void (*fun)(void *), void *data);
+typedef void (*call_R_RestoreHashCount)(SEXP rho);
+typedef Rboolean (*call_R_IsPackageEnv)(SEXP rho);
+typedef SEXP (*call_R_PackageEnvName)(SEXP rho);
+typedef SEXP (*call_R_FindPackageEnv)(SEXP info);
+typedef Rboolean (*call_R_IsNamespaceEnv)(SEXP rho);
+typedef SEXP (*call_R_NamespaceEnvSpec)(SEXP rho);
+typedef SEXP (*call_R_FindNamespace)(SEXP info);
+typedef void (*call_R_LockEnvironment)(SEXP env, Rboolean bindings);
+typedef Rboolean (*call_R_EnvironmentIsLocked)(SEXP env);
+typedef void (*call_R_LockBinding)(SEXP sym, SEXP env);
+typedef void (*call_R_unLockBinding)(SEXP sym, SEXP env);
+typedef void (*call_R_MakeActiveBinding)(SEXP sym, SEXP fun, SEXP env);
+typedef Rboolean (*call_R_BindingIsLocked)(SEXP sym, SEXP env);
+typedef Rboolean (*call_R_BindingIsActive)(SEXP sym, SEXP env);
+typedef Rboolean (*call_R_HasFancyBindings)(SEXP rho);
+typedef Rboolean (*call_Rf_isS4)(SEXP x);
+typedef SEXP (*call_Rf_asS4)(SEXP x, Rboolean b, int i);
+typedef SEXP (*call_R_tryEval)(SEXP x, SEXP y, int *ErrorOccurred);
+typedef SEXP (*call_R_tryEvalSilent)(SEXP x, SEXP y, int *ErrorOccurred);
+typedef double (*call_R_atof)(const char *str);
+typedef double (*call_R_strtod)(const char *c, char **end);
+typedef SEXP (*call_R_PromiseExpr)(SEXP x);
+typedef SEXP (*call_R_ClosureExpr)(SEXP x);
+typedef SEXP (*call_R_forceAndCall)(SEXP e, int n, SEXP rho);
+typedef SEXP (*call_R_MakeExternalPtr)(void *p, SEXP tag, SEXP prot);
+typedef void *(*call_R_ExternalPtrAddr)(SEXP s);
+typedef SEXP (*call_R_ExternalPtrTag)(SEXP s);
+typedef SEXP (*call_R_ExternalPtrProt)(SEXP s);
+typedef void (*call_R_SetExternalPtrAddr)(SEXP s, void *p);
+typedef void (*call_R_SetExternalPtrTag)(SEXP s, SEXP tag);
+typedef void (*call_R_SetExternalPtrProtected)(SEXP s, SEXP p);
+typedef void (*call_R_ClearExternalPtr)(SEXP s);
+typedef void (*call_R_RegisterFinalizer)(SEXP s, SEXP fun);
+typedef void (*call_R_RegisterCFinalizer)(SEXP s, R_CFinalizer_t fun);
+typedef void (*call_R_RegisterFinalizerEx)(SEXP s, SEXP fun, Rboolean onexit);
+typedef void (*call_R_RegisterCFinalizerEx)(SEXP s, R_CFinalizer_t fun, Rboolean onexit);
+typedef void (*call_R_RunPendingFinalizers)(void);
+typedef SEXP (*call_R_MakeWeakRef)(SEXP key, SEXP val, SEXP fin, Rboolean onexit);
+typedef SEXP (*call_R_MakeWeakRefC)(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit);
+typedef SEXP (*call_R_WeakRefKey)(SEXP w);
+typedef SEXP (*call_R_WeakRefValue)(SEXP w);
+typedef void (*call_R_RunWeakRefFinalizer)(SEXP w);
+typedef SEXP (*call_R_do_slot)(SEXP obj, SEXP name);
+typedef SEXP (*call_R_do_slot_assign)(SEXP obj, SEXP name, SEXP value);
+typedef int (*call_R_has_slot)(SEXP obj, SEXP name);
+typedef SEXP (*call_R_do_MAKE_CLASS)(const char *what);
+typedef SEXP (*call_R_getClassDef )(const char *what);
+typedef SEXP (*call_R_do_new_object)(SEXP class_def);
+typedef int (*call_R_check_class_and_super)(SEXP x, const char **valid, SEXP rho);
+typedef int (*call_R_check_class_etc )(SEXP x, const char **valid);
+typedef SEXP (*call_R_PreserveObject)(SEXP x);
+typedef void (*call_R_ReleaseObject)(SEXP x);
+typedef void (*call_R_dot_Last)(void);
+typedef Rboolean (*call_R_compute_identical)(SEXP x, SEXP y, int flags);
+typedef void (*call_Rf_copyListMatrix)(SEXP s, SEXP t, Rboolean byrow);
+typedef void (*call_Rf_copyMatrix)(SEXP s, SEXP t, Rboolean byrow);
+typedef void (*call_GetRNGstate)();
+typedef void (*call_PutRNGstate)();
+typedef SEXP (*call_R_BaseEnv)();
+typedef SEXP (*call_R_BaseNamespace)();
+typedef SEXP (*call_R_GlobalEnv)();
+typedef SEXP (*call_R_NamespaceRegistry)();
+typedef SEXP (*call_R_Interactive)();
+typedef SEXP (*call_R_GlobalContext)();
+typedef SEXP (*call_R_CHAR)(SEXP x);
+typedef char *(*call_R_HomeDir)();
+typedef void (*call_R_CleanUp)(int sa, int status, int runlast);
+typedef void (*call_Rf_gsetVar)(SEXP symbol, SEXP value, SEXP rho);
+typedef double (*call_unif_rand)();
+
+#endif
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
new file mode 100644
index 0000000000..4068091952
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifndef RFFIUTILS_H
+#define RFFIUTILS_H
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <Rinternals.h>
+#include <rffi_callbacks.h>
+#include <trufflenfi.h>
+
+extern void init_memory();
+
+#endif
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
new file mode 100644
index 0000000000..acd535c135
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <Rinternals.h>
+#include <trufflenfi.h>
+
+#define R_Home_x 0
+#define R_TempDir_x 1
+#define R_NilValue_x 2
+#define R_UnboundValue_x 3
+#define R_MissingArg_x 4
+#define R_GlobalEnv_x 5
+#define R_EmptyEnv_x 6
+#define R_BaseEnv_x 7
+#define R_BaseNamespace_x 8
+#define R_NamespaceRegistry_x 9
+#define R_Srcref_x 10
+#define R_Bracket2Symbol_x 11
+#define R_BracketSymbol_x 12
+#define R_BraceSymbol_x 13
+#define R_ClassSymbol_x 14
+#define R_DeviceSymbol_x 15
+#define R_DevicesSymbol_x 16
+#define R_DimNamesSymbol_x 17
+#define R_DimSymbol_x 18
+#define R_DollarSymbol_x 19
+#define R_DotsSymbol_x 20
+#define R_DropSymbol_x 21
+#define R_LastvalueSymbol_x 22
+#define R_LevelsSymbol_x 23
+#define R_ModeSymbol_x 24
+#define R_NameSymbol_x 25
+#define R_NamesSymbol_x 26
+#define R_NaRmSymbol_x 27
+#define R_PackageSymbol_x 28
+#define R_QuoteSymbol_x 29
+#define R_RowNamesSymbol_x 30
+#define R_SeedsSymbol_x 31
+#define R_SourceSymbol_x 32
+#define R_TspSymbol_x 33
+#define R_dot_defined_x 34
+#define R_dot_Method_x 35
+#define R_dot_target_x 36
+#define R_SrcrefSymbol_x 37
+#define R_SrcfileSymbol_x 38
+#define R_NaString_x 39
+#define R_NaN_x 40
+#define R_PosInf_x 41
+#define R_NegInf_x 42
+#define R_NaReal_x 43
+#define R_NaInt_x 44
+#define R_BlankString_x 45
+#define R_BlankScalarString_x 46
+#define R_BaseSymbol_x 47
+#define R_NamespaceEnvSymbol_x 48
+#define R_RestartToken_x 49
+
+static const char *R_Home_static;
+static const char *R_TempDir_static;
+static SEXP R_EmptyEnv_static;
+static SEXP R_Srcref_static;
+static SEXP R_NilValue_static;
+static SEXP R_UnboundValue_static;
+static SEXP R_MissingArg_static;
+static SEXP R_BaseSymbol_static;
+static SEXP R_Bracket2Symbol_static;   /* "[[" */
+static SEXP R_BracketSymbol_static;    /* "[" */
+static SEXP R_BraceSymbol_static;      /* "{" */
+static SEXP R_ClassSymbol_static;     /* "class" */
+static SEXP R_DeviceSymbol_static;     /* ".Device" */
+static SEXP R_DevicesSymbol_static;     /* ".Devices" */
+static SEXP R_DimNamesSymbol_static;   /* "dimnames" */
+static SEXP R_DimSymbol_static;     /* "dim" */
+static SEXP R_DollarSymbol_static;     /* "$" */
+static SEXP R_DotsSymbol_static;     /* "..." */
+static SEXP R_DropSymbol_static;     /* "drop" */
+static SEXP R_LastvalueSymbol_static;  /* ".Last.value" */
+static SEXP R_LevelsSymbol_static;     /* "levels" */
+static SEXP R_ModeSymbol_static;     /* "mode" */
+static SEXP R_NameSymbol_static;     /* "name" */
+static SEXP R_NamesSymbol_static;     /* "names" */
+static SEXP R_NaRmSymbol_static;     /* "na.rm" */
+static SEXP R_PackageSymbol_static;    /* "package" */
+static SEXP R_QuoteSymbol_static;     /* "quote" */
+static SEXP R_RowNamesSymbol_static;   /* "row.names" */
+static SEXP R_SeedsSymbol_static;     /* ".Random.seed" */
+static SEXP R_SourceSymbol_static;     /* "source" */
+static SEXP R_TspSymbol_static;     /* "tsp" */
+static SEXP R_dot_defined_static;      /* ".defined" */
+static SEXP R_dot_Method_static;       /* ".Method" */
+static SEXP R_dot_target_static;       /* ".target" */
+static SEXP R_NaString_static;	    /* NA_STRING as a CHARSXP */
+static SEXP R_BlankString_static;	    /* "" as a CHARSXP */
+static SEXP R_BlankScalarString_static;	    /* "" as a STRSXP */
+static SEXP R_BaseSymbol_static;	    /* "base" as a SYMSXP */
+static SEXP	R_NamespaceEnvSymbol_static;   // ".__NAMESPACE__."
+
+// Symbols not part of public API but used in FastR tools implementation
+static SEXP R_SrcrefSymbol_static;
+static SEXP R_SrcfileSymbol_static;
+static SEXP R_RestartToken_static;
+
+// Arith.h
+double R_NaN;		/* IEEE NaN */
+double R_PosInf;	/* IEEE Inf */
+double R_NegInf;	/* IEEE -Inf */
+double R_NaReal;	/* NA_REAL: IEEE */
+int R_NaInt;	/* NA_INTEGER:= INT_MIN currently */
+
+// various ignored flags and variables nevertheless needed to resolve symbols
+Rboolean R_Visible;
+Rboolean R_interrupts_suspended;
+int R_interrupts_pending;
+Rboolean mbcslocale;
+Rboolean useaqua;
+char* OutDec = ".";
+Rboolean utf8locale = FALSE;
+Rboolean mbcslocale = FALSE;
+Rboolean latin1locale = FALSE;
+int R_dec_min_exponent = -308;
+int max_contour_segments = 25000;
+
+// from sys-std.c
+#include <R_ext/eventloop.h>
+
+static InputHandler BasicInputHandler = {2, -1, NULL};
+InputHandler *R_InputHandlers = &BasicInputHandler;
+
+char *FASTR_R_Home() {
+	return (char *) R_Home_static;
+}
+
+char *FASTR_R_TempDir() {
+	return (char *) R_TempDir_static;
+}
+
+SEXP FASTR_R_EmptyEnv() {
+    return R_EmptyEnv_static;
+}
+
+SEXP FASTR_R_Srcref() {
+    return R_Srcref_static;
+}
+
+SEXP FASTR_R_NilValue() {
+    return R_NilValue_static;
+}
+
+SEXP FASTR_R_UnboundValue() {
+    return R_UnboundValue_static;
+}
+
+SEXP FASTR_R_MissingArg() {
+    return R_MissingArg_static;
+}
+
+SEXP FASTR_R_BaseSymbol() {
+    return R_BaseSymbol_static;
+}
+
+
+SEXP FASTR_R_BraceSymbol() {
+    return R_BraceSymbol_static;
+}
+
+SEXP FASTR_R_Bracket2Symbol() {
+    return R_Bracket2Symbol_static;
+}
+
+SEXP FASTR_R_BracketSymbol() {
+    return R_BracketSymbol_static;
+}
+
+SEXP FASTR_R_ClassSymbol() {
+    return R_ClassSymbol_static;
+}
+
+SEXP FASTR_R_DimNamesSymbol() {
+    return R_DimNamesSymbol_static;
+}
+
+SEXP FASTR_R_DimSymbol() {
+    return R_DimSymbol_static;
+}
+
+
+SEXP FASTR_R_DollarSymbol() {
+    return R_DollarSymbol_static;
+}
+
+SEXP FASTR_R_DotsSymbol() {
+    return R_DotsSymbol_static;
+}
+
+
+SEXP FASTR_R_DropSymbol() {
+    return R_DropSymbol_static;
+}
+
+SEXP FASTR_R_LastvalueSymbol() {
+    return R_LastvalueSymbol_static;
+}
+
+
+SEXP FASTR_R_LevelsSymbol() {
+    return R_LevelsSymbol_static;
+}
+
+SEXP FASTR_R_ModeSymbol() {
+    return R_ModeSymbol_static;
+}
+
+SEXP FASTR_R_NaRmSymbol() {
+    return R_NaRmSymbol_static;
+}
+
+
+SEXP FASTR_R_NameSymbol() {
+    return R_NameSymbol_static;
+}
+
+SEXP FASTR_R_NamesSymbol() {
+    return R_NamesSymbol_static;
+}
+
+
+SEXP FASTR_R_NamespaceEnvSymbol() {
+    return R_NamespaceEnvSymbol_static;
+}
+
+SEXP FASTR_R_PackageSymbol() {
+    return R_PackageSymbol_static;
+}
+
+SEXP FASTR_R_QuoteSymbol() {
+    return R_QuoteSymbol_static;
+}
+
+SEXP FASTR_R_RowNamesSymbol() {
+    return R_RowNamesSymbol_static;
+}
+
+SEXP FASTR_R_SeedsSymbol() {
+    return R_SeedsSymbol_static;
+}
+
+SEXP FASTR_R_SourceSymbol() {
+    return R_SourceSymbol_static;
+}
+
+SEXP FASTR_R_TspSymbol() {
+    return R_TspSymbol_static;
+}
+
+SEXP FASTR_R_dot_defined() {
+    return R_dot_defined_static;
+}
+
+SEXP FASTR_R_dot_Method() {
+    return R_dot_Method_static;
+}
+
+SEXP FASTR_R_dot_target() {
+    return R_dot_target_static;
+}
+
+SEXP FASTR_R_NaString() {
+    return R_NaString_static;
+}
+
+
+SEXP FASTR_R_BlankString() {
+    return R_BlankString_static;
+}
+
+SEXP FASTR_R_BlankScalarString() {
+    return R_BlankScalarString_static;
+}
+
+SEXP FASTR_R_DevicesSymbol() {
+    return R_DevicesSymbol_static;
+}
+
+SEXP FASTR_R_DeviceSymbol() {
+    return R_DeviceSymbol_static;
+}
+
+SEXP FASTR_R_SrcrefSymbol() {
+    return R_SrcrefSymbol_static;
+}
+
+SEXP FASTR_R_SrcfileSymbol() {
+    return R_SrcfileSymbol_static;
+}
+
+void Call_initvar_double(int index, double value) {
+	switch (index) {
+    case R_NaN_x: R_NaN = value; break;
+	}
+}
+
+void Call_initvar_int(int index, int value) {
+	switch (index) {
+    case R_NaInt_x: R_NaInt = value; break;
+    case R_PosInf_x: R_PosInf = value; break;
+    case R_NegInf_x: R_NegInf = value; break;
+    case R_NaReal_x: R_NaReal = value; break;
+	}
+}
+
+char *copystring(char *value) {
+	char *result = malloc(strlen(value) + 1);
+	strcpy(result, value);
+	return result;
+}
+
+// value must be copied
+void Call_initvar_string(int index, char *value) {
+	switch (index) {
+    case R_Home_x: R_Home_static = copystring(value); break;
+    case R_TempDir_x: R_TempDir_static = copystring(value); break;
+	}
+}
+
+void Call_initvar_obj(int index, void* value) {
+	switch (index) {
+    case R_NilValue_x: R_NilValue_static = newObjectRef(value); break;
+    case R_UnboundValue_x: R_UnboundValue_static = newObjectRef(value); break;
+    case R_MissingArg_x: R_MissingArg_static = newObjectRef(value); break;
+//    case R_Srcref_x: R_Srcref_static = newObjectRef(value); break;
+    case R_EmptyEnv_x: R_EmptyEnv_static = newObjectRef(value); break;
+    case R_Bracket2Symbol_x: R_Bracket2Symbol_static = newObjectRef(value); break;
+    case R_BracketSymbol_x: R_BracketSymbol_static = newObjectRef(value); break;
+    case R_BraceSymbol_x: R_BraceSymbol_static = newObjectRef(value); break;
+    case R_ClassSymbol_x: R_ClassSymbol_static = newObjectRef(value); break;
+    case R_DeviceSymbol_x: R_DeviceSymbol_static = newObjectRef(value); break;
+    case R_DevicesSymbol_x: R_DevicesSymbol_static = newObjectRef(value); break;
+    case R_DimNamesSymbol_x: R_DimNamesSymbol_static = newObjectRef(value); break;
+    case R_DimSymbol_x: R_DimSymbol_static = newObjectRef(value); break;
+    case R_DollarSymbol_x: R_DollarSymbol_static = newObjectRef(value); break;
+    case R_DotsSymbol_x: R_DotsSymbol_static = newObjectRef(value); break;
+    case R_DropSymbol_x: R_DropSymbol_static = newObjectRef(value); break;
+    case R_LastvalueSymbol_x: R_LastvalueSymbol_static = newObjectRef(value); break;
+    case R_LevelsSymbol_x: R_LevelsSymbol_static = newObjectRef(value); break;
+    case R_ModeSymbol_x: R_ModeSymbol_static = newObjectRef(value); break;
+    case R_NameSymbol_x: R_NameSymbol_static = newObjectRef(value); break;
+    case R_NamesSymbol_x: R_NamesSymbol_static = newObjectRef(value); break;
+    case R_NaRmSymbol_x: R_NaRmSymbol_static = newObjectRef(value); break;
+    case R_PackageSymbol_x: R_PackageSymbol_static = newObjectRef(value); break;
+    case R_QuoteSymbol_x: R_QuoteSymbol_static = newObjectRef(value); break;
+    case R_RowNamesSymbol_x: R_RowNamesSymbol_static = newObjectRef(value); break;
+    case R_SeedsSymbol_x: R_SeedsSymbol_static = newObjectRef(value); break;
+    case R_SourceSymbol_x: R_SourceSymbol_static = newObjectRef(value); break;
+    case R_TspSymbol_x: R_TspSymbol_static = newObjectRef(value); break;
+    case R_dot_defined_x: R_dot_defined_static = newObjectRef(value); break;
+    case R_dot_Method_x: R_dot_Method_static = newObjectRef(value); break;
+    case R_dot_target_x: R_dot_target_static = newObjectRef(value); break;
+    case R_SrcrefSymbol_x: R_SrcrefSymbol_static = newObjectRef(value); break;
+    case R_SrcfileSymbol_x: R_SrcfileSymbol_static = newObjectRef(value); break;
+    case R_NaString_x: R_NaString_static = newObjectRef(value); break;
+    case R_BlankString_x: R_BlankString_static = newObjectRef(value); break;
+    case R_BlankScalarString_x: R_BlankString_static = newObjectRef(value); break;
+    case R_BaseSymbol_x: R_BaseSymbol_static = newObjectRef(value); break;
+    case R_NamespaceEnvSymbol_x: R_NamespaceEnvSymbol_static = newObjectRef(value); break;
+    // case R_RestartToken_x: R_RestartToken_static = newObjectRef(value); break;
+    default:
+    	printf("Call_initvar_obj: unimplemented index %d\n", index);
+    	exit(1);
+	}
+}
+
diff --git a/com.oracle.truffle.r.native/gnur/Makefile.gnur b/com.oracle.truffle.r.native/gnur/Makefile.gnur
index abc5c59b12..a6819b2a23 100644
--- a/com.oracle.truffle.r.native/gnur/Makefile.gnur
+++ b/com.oracle.truffle.r.native/gnur/Makefile.gnur
@@ -40,12 +40,12 @@
 
 OSNAME := $(shell uname)
 
-ifdef FASTR_TRUFFLE_RFFI
+ifeq ($(FASTR_RFFI),llvm)
 FC_DIR := $(abspath $(TOPDIR)/../mx.fastr/compilers)
 FASTR_COMPILERS := CC=$(FC_DIR)/fastr-cc FC=$(FC_DIR)/fastr-fc F77=$(FC_DIR)/fastr-fc CXX=$(FC_DIR)/fastr-c++ CXXCPP=$(FC_DIR)/fastr-cpp OBJC=$(FC_DIR)/fastr-cc
 endif
 
-ifndef FASTR_TRUFFLE_RFFI
+ifneq ($(FASTR_RFFI),llvm)
 # LLVM text parser and -g don't get on
 OPT_FLAGS := -g -O2
 OPT_FLAGS := -O2
diff --git a/com.oracle.truffle.r.native/library/lib.mk b/com.oracle.truffle.r.native/library/lib.mk
index 727f096cb6..4f6a44fcb9 100644
--- a/com.oracle.truffle.r.native/library/lib.mk
+++ b/com.oracle.truffle.r.native/library/lib.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -103,9 +103,9 @@ $(GNUR_F_OBJECTS): | $(OBJ)
 $(OBJ):
 	mkdir -p $(OBJ)
 
-$(LIB_PKG): $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKGDIR)
+$(LIB_PKG): $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKGDIR) $(XTRA_C_OBJECTS)
 	mkdir -p $(LIBDIR)
-	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(LIB_PKG) $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKG_LIBS)
+	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(LIB_PKG) $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(XTRA_C_OBJECTS) $(PKG_LIBS)
 	mkdir -p $(FASTR_LIBRARY_DIR)/$(PKG)/libs
 	cp $(LIB_PKG) $(FASTR_LIBRARY_DIR)/$(PKG)/libs
 ifeq ($(OS_NAME),Darwin)
diff --git a/com.oracle.truffle.r.native/library/tools/Makefile b/com.oracle.truffle.r.native/library/tools/Makefile
index 3bf843f957..f044af7d7e 100644
--- a/com.oracle.truffle.r.native/library/tools/Makefile
+++ b/com.oracle.truffle.r.native/library/tools/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,21 @@ LIB_PKG_PRE = $(GRAMRD_OBJ)
 
 CLEAN_PKG = rm_gramRd
 
+ifeq ($(FASTR_RFFI),nfi)
+XTRA_C_SOURCES += $(SRC)/truffle_nfi/gramRd_nfi.c
+XTRA_C_OBJECTS += $(OBJ)/gramRd_nfi.o
+else
+ifeq ($(FASTR_RFFI),llvm)
+XTRA_C_SOURCES += $(SRC)/truffle_llvm/gramRd_llvm.c
+XTRA_C_OBJECTS += $(OBJ)/gramRd_llvm.o
+else
+ifeq ($(FASTR_RFFI),jni)
+XTRA_C_SOURCES += $(SRC)/jni/gramRd_jni.c
+XTRA_C_OBJECTS += $(OBJ)/gramRd_jni.o
+endif
+endif
+endif
+
 include ../lib.mk
 
 # in case already generated
@@ -46,5 +61,11 @@ $(SRC)/gramRd.c: $(GNUR_SRC)/gramRd.c
 $(OBJ)/%.o: $(GNUR_SRC)/%.c
 	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
 
+$(OBJ)/gramRd_nfi.o: $(SRC)/truffle_nfi/gramRd_nfi.c
+	$(CC) $(CFLAGS) $(FFI_INCLUDES) -c $< -o $@
+
+$(OBJ)/gramRd_jni.o: $(SRC)/jni/gramRd_jni.c
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
 rm_gramRd:
 	rm -f $(SRC)/gramRd.c
diff --git a/com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c b/com.oracle.truffle.r.native/library/tools/src/jni/gramRd_jni.c
similarity index 94%
rename from com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c
rename to com.oracle.truffle.r.native/library/tools/src/jni/gramRd_jni.c
index c109bff1be..14eb60c2e9 100644
--- a/com.oracle.truffle.r.native/library/tools/src/gramRd_jni.c
+++ b/com.oracle.truffle.r.native/library/tools/src/jni/gramRd_jni.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#include "gramRd_fastr.h"
+#include "../gramRd_fastr.h"
 #include <jni.h>
 
 extern JNIEnv *getEnv();
diff --git a/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
new file mode 100644
index 0000000000..c5716bb4c3
--- /dev/null
+++ b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "../gramRd_fastr.h"
+
+static int (*call_RConnGetC)(void *conn);
+
+void gramRd_nfi_init(void *closure) {
+	call_RConnGetC = closure;
+}
+
+int callGetCMethod(void *conn) {
+	return call_RConnGetC(conn);
+}
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 98d9bcb75a..3c032078a4 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-17
+18
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index c379ee6da5..5be9dfbdad 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -379,6 +379,7 @@ public class LaFunctions {
         }
 
         @Specialization
+
         protected RList doDetGeReal(RAbstractDoubleVector aIn, boolean useLog,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") LapackRFFI.DgetrfNode dgetrfNode) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
index 170f820fd2..06d6fa23d7 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
@@ -37,12 +37,12 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 
 public class Generic_Tools implements ToolsRFFI {
-    private static class Generic_ToolsRFFINode extends ParseRdNode {
+    public static class Generic_ToolsRFFINode extends ParseRdNode {
         private static final String C_PARSE_RD = "C_parseRd";
-        private static final String TOOLS = "tools";
+        protected static final String TOOLS = "tools";
 
         @Child private CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
-        @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
+        @Child private DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
 
         @CompilationFinal private NativeCallInfo nativeCallInfo;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index 00825a42b4..c1d2879620 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -309,12 +309,16 @@ public class DLL {
      * Abstracts the way that DLL function symbols are represented, either as a machine address (
      * {@link Long}) or a {@link TruffleObject}. At the present time, both forms can exists within a
      * single VM, so the class is defined as a "union" for simplicity.
+     *
+     * N.B. It is explicitly allowed to register a {@code null} value as the base package registers
+     * some (Fortran) functions that are implemented in Java but have a bogus (zero) native symbol
+     * definition. Any use of {@code null} is failed
      */
     public static final class SymbolHandle {
         public final Object value;
 
         public SymbolHandle(Object value) {
-            assert value instanceof Long || value instanceof TruffleObject;
+            assert value == null || value instanceof Long || value instanceof TruffleObject;
             this.value = value;
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index 963d98cc59..b443cb0a7c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -47,7 +47,7 @@ public abstract class RFFIFactory {
 
     private static final String FACTORY_CLASS_PROPERTY = "fastr.rffi.factory.class";
     private static final String FACTORY_CLASS_NAME_PROPERTY = "fastr.rffi.factory";
-    private static final String FACTORY_CLASS_ENV = "FASTR_RFFI_FACTORY";
+    private static final String FACTORY_CLASS_ENV = "FASTR_RFFI";
     private static final Factory DEFAULT_FACTORY = Factory.JNI;
 
     /**
diff --git a/com.oracle.truffle.r.test.native/Makefile b/com.oracle.truffle.r.test.native/Makefile
index 9c3c1b9ffc..8045621a3c 100644
--- a/com.oracle.truffle.r.test.native/Makefile
+++ b/com.oracle.truffle.r.test.native/Makefile
@@ -35,13 +35,17 @@ all:
 	$(MAKE) -C urand
 	$(MAKE) -C packages
 ifneq ($(OSNAME), SunOS)
+ifeq ($(FASTR_RFFI),jni)
 	$(MAKE) -C embedded
 endif
+endif
 
 clean:
 	$(MAKE) -C urand clean
 	$(MAKE) -C packages clean
 ifneq ($(OSNAME), SunOS)
+ifeq ($(FASTR_RFFI),jni)
 	$(MAKE) -C embedded clean
+endif
 endif
 	rm -f $(REPO_DIR)/*
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
index b538c5c44d..03d88811d9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.test.tools;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.Arrays;
 import java.util.Comparator;
 
@@ -36,8 +37,23 @@ import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
  */
 public class RFFIUpCallMethodGenerate {
 
-    public static void main(String[] args) {
-        Method[] methods = UpCallsRFFI.class.getMethods();
+    public static void main(String[] args) throws Exception {
+        String klassName = "com.oracle.truffle.r.runtime.ffi.UpCallsRFFI";
+        boolean klassArg = false;
+
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i];
+            if (arg.equals("--class")) {
+                i++;
+                klassName = args[i];
+                klassArg = true;
+            }
+            i++;
+        }
+
+        Class<?> klass = Class.forName(klassName);
+        Method[] methods = klassArg ? klass.getDeclaredMethods() : klass.getMethods();
 
         Arrays.sort(methods, new Comparator<Method>() {
 
@@ -47,8 +63,11 @@ public class RFFIUpCallMethodGenerate {
             }
 
         });
-        for (int i = 0; i < methods.length; i++) {
+        for (i = 0; i < methods.length; i++) {
             Method m = methods[i];
+            if (klassArg && (Modifier.isStatic(m.getModifiers()))) {
+                continue;
+            }
             String sig = getNFISignature(m);
             System.out.printf("%s(\"%s\")%s%n", m.getName(), sig, i == methods.length - 1 ? ";" : ",");
         }
@@ -92,12 +111,20 @@ public class RFFIUpCallMethodGenerate {
                 } else {
                     return rffiCstring.convert() ? "string" : "pointer";
                 }
+            case "char":
+                return "uint8";
             case "int":
                 return "sint32";
             case "double":
                 return "double";
             case "void":
                 return "void";
+            case "int[]":
+                return "[sint32]";
+            case "double[]":
+                return "[double]";
+            case "byte[]":
+                return "[uint8]";
             default:
                 return "object";
         }
diff --git a/documentation/dev/ffi.md b/documentation/dev/ffi.md
index 1ebb04860b..69fb145d11 100644
--- a/documentation/dev/ffi.md
+++ b/documentation/dev/ffi.md
@@ -1,7 +1,8 @@
 # The R FFI Implementation
 
 # Introduction
-FastR interfaces to native C and Fortran code in a number of ways, for example, access to C library APIs not supported by the Java JDK, access to LaPack functions, and the `.Call`, `.Fortran`, `.C` builtins. Each of these are defined by a Java interface,e.g. `CallRFFI` for the `.Call` builtin. To facilitate experimentation and different implementations, the implementation of these interfaces is defined by a factory class, `RFFIFactory`, that is chosen at run time via the `fastr.ffi.factory.class` system property. The factory is responsible for creating an instance of the `RFFI` interface that in turn provides access to implementations of the underlying interfaces such as `CallRFFI`. This structure allows
+FastR interfaces to native C and Fortran code in a number of ways, for example, access to C library APIs not supported by the Java JDK, access to LaPack functions, and the `.Call`, `.Fortran`, `.C` builtins. Each of these are defined by a Java interface,e.g. `CallRFFI` for the `.Call` builtin. To facilitate experimentation and different implementations, the implementation of these interfaces is defined by a factory class, `RFFIFactory`, that is chosen at run time via the `fastr.ffi.factory.class` system property, or the `FASTR_RFFI` environment variable.
+The factory is responsible for creating an instance of the `RFFI` interface that in turn provides access to implementations of the underlying interfaces such as `CallRFFI`. This structure allows
 for each of the individual interfaces to be implemented by a different mechanism. Currently the default factory class is `JNI_RFFIFactory` which uses the Java JNI system to implement the transition to native code.
 
 # Native Implementation
@@ -10,10 +11,11 @@ the `com.oracle/truffle.r.native` project`. It's actually a bit more than that a
 simple that it is neither necessary nor desirable to implement in Java. As this has evolved a better name for `fficall` would probably be `main`
 for compatibility with GNU R.
 
- There are four sub-directories in `fficall/src`:
+ There are five sub-directories in `fficall/src`:
  * `include`
  * `common`
  * `jni`
+ * `truffle_nfi`
  * `truffle_llvm`
 
 ## The `fficall/include` directory
@@ -44,7 +46,11 @@ copied/included from GNU R. N.B. Some modified files have a `_fastr` suffix to a
 the Makefile rule for compiling directly from the GNU R file.
 
 ## The `jni` directory
-`jni` contains the implementation that is based on and has explicit dependencies on Java JNI. It is described in more detail [here](jni_ffi.md)
+`jni` contains the implementation that is based on and has explicit dependencies on Java JNI. It is described in more detail [here](jni_ffi.md). This is the default implementation.
+
+## The `truffle_nfi` directory.
+`truffle_nfi` contains the implementation that is based on the Truffle Native Function Interface. It is enabled by setting `FASTR_RFFIU=nfi` and doing a clean build.
+The implementation is currently incomplete.
 
 ## The `truffle_llvm` directory
 
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index a09bd8bac8..c78942645b 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -115,6 +115,9 @@ com.oracle.truffle.r.native/fficall/src/include/rlocale.h,gnu_r_gentleman_ihaka.
 com.oracle.truffle.r.native/fficall/src/jni/Memory.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c,gnu_r.copyright
 com.oracle.truffle.r.native/include/src/libintl.h,no.copyright
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 259351b416..0bc160dec4 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -29,7 +29,7 @@ import mx_fastr_pkgs
 import mx_fastr_compile
 import mx_fastr_dists
 import mx_fastr_junit
-from mx_fastr_dists import FastRNativeProject, FastRTestNativeProject, FastRReleaseProject, FastRNativeRecommendedProject #pylint: disable=unused-import
+from mx_fastr_dists import FastRTestNativeProject, FastRReleaseProject, FastRNativeRecommendedProject #pylint: disable=unused-import
 import mx_copylib
 import mx_fastr_mkgramrd
 import mx_fastr_edinclude
diff --git a/mx.fastr/mx_fastr_dists.py b/mx.fastr/mx_fastr_dists.py
index 68066b43ce..2f81965b06 100644
--- a/mx.fastr/mx_fastr_dists.py
+++ b/mx.fastr/mx_fastr_dists.py
@@ -43,74 +43,6 @@ class FastRProjectAdapter(mx.ArchivableProject):
                     results.append(join(root, f))
 
 
-class FastRNativeProject(FastRProjectAdapter):
-    '''
-    Custom class for building the com.oracle.truffle.r.native project.
-    The customization is to support the creation of an exact FASTR_NATIVE_DEV distribution.
-    '''
-    def __init__(self, suite, name, deps, workingSets, theLicense, **args):
-        FastRProjectAdapter.__init__(self, suite, name, deps, workingSets, theLicense)
-
-    def getBuildTask(self, args):
-        return mx.NativeBuildTask(args, self)
-
-    def _get_gnur_files(self, gnur_dir, files, results):
-        for f in files:
-            results.append(join(self.dir, gnur_dir, f))
-
-    def getResults(self):
-        '''
-        Capture all the files from the com.oracle.truffle.r.native project that are needed
-        in an alternative implementation of the R FFI. This includes some files from GNU R.
-        This code has to be kept in sync with the FFI implementation.
-        '''
-        # plain files
-        results = [join(self.dir, "platform.mk")]
-        gnur = join('gnur', mx_fastr.r_version())
-        gnur_appl = join(gnur, 'src', 'appl')
-        self._get_gnur_files(gnur_appl, ['pretty.c', 'interv.c'], results)
-        gnur_main = join(gnur, 'src', 'main')
-        self._get_gnur_files(gnur_main, ['colors.c', 'devices.c', 'engine.c', 'format.c', 'graphics.c',
-                                         'plot.c', 'plot3d.c', 'plotmath.c', 'rlocale.c', 'sort.c'], results)
-        # these files are not compiled, just "included"
-        self._get_gnur_files(gnur_main, ['xspline.c', 'rlocale_data.h'], results)
-        # directories
-        for d in ["fficall/src/common", "fficall/src/include", "fficall/src/variable_defs"]:
-            self._get_files(d, results)
-
-        def is_dot_h(f):
-            ext = os.path.splitext(f)[1]
-            return ext == '.h'
-
-        # just the .h files from 'include'
-        self._get_files('include', results, is_dot_h)
-
-        # tools for alternate impl of gramRd.c
-        gnur_tools = join(gnur, 'library', 'tools')
-        self._get_files(gnur_tools, results)
-        gnur_tools_src = join(gnur, 'src', 'library', 'tools', 'src')
-        for f in ['gramRd.c', 'init.c', 'tools.h']:
-            results.append(join(self.dir, gnur_tools_src, f))
-        for f in ['lib.mk', 'Makefile', 'tools/src/tools_dummy.c', 'tools/src/gramRd_fastr.h', 'tools/Makefile']:
-            results.append(join(self.dir, 'library', f))
-
-        # selected headers from GNU R source
-        with open(join(self.dir, 'fficall/src/include/gnurheaders.mk')) as f:
-            lines = f.readlines()
-            for line in lines:
-                if '$(GNUR_HOME)' in line:
-                    parts = line.split(' ')
-                    results.append(join(self.dir, parts[2].rstrip().replace('$(GNUR_HOME)', gnur)))
-
-        def is_ddot_o(f):
-            ext = os.path.splitext(f)[1]
-            return f[0] == 'd' and ext == '.o'
-
-        # binary files from GNU R
-        self._get_files(gnur_appl, results, is_ddot_o)
-
-        return results
-
 class FastRTestNativeProject(FastRProjectAdapter):
     '''
     Custom class for building the com.oracle.truffle.r.native project.
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index ea8973c6b8..39727463a8 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -197,6 +197,7 @@ suite = {
         "com.oracle.truffle.r.parser",
         "truffle:JLINE",
         "truffle:TRUFFLE_DEBUG",
+        "truffle:TRUFFLE_NFI",
       ],
      "generatedDependencies" : [
         "com.oracle.truffle.r.parser",
@@ -243,11 +244,13 @@ suite = {
       "dependencies" : [
         "GNUR",
         "GNU_ICONV",
+        "truffle:TRUFFLE_NFI_NATIVE",
       ],
       "native" : "true",
-      "class" : "FastRNativeProject",
-      "output" : "com.oracle.truffle.r.native",
       "workingSets" : "FastR",
+      "buildEnv" : {
+        "NFI_INCLUDES" : "-I<path:truffle:TRUFFLE_NFI_NATIVE>/include",
+      },
     },
 
     "com.oracle.truffle.r.library" : {
@@ -315,6 +318,8 @@ suite = {
       "distDependencies" : [
         "truffle:TRUFFLE_API",
         "truffle:TRUFFLE_DEBUG",
+        "truffle:TRUFFLE_NFI",
+        "truffle:TRUFFLE_NFI_NATIVE",
         "TRUFFLE_R_PARSER_PROCESSOR",
       ],
     },
@@ -336,8 +341,6 @@ suite = {
 
     "FASTR_UNIT_TESTS_NATIVE" : {
       "description" : "unit tests support (from test.native project)",
-      "dependencies" : ["com.oracle.truffle.r.test.native"],
-      "distDependencies" : ["FASTR_NATIVE_DEV"],
       "exclude" : ["GNUR", "GNU_ICONV"],
        "os_arch" : {
          "linux" : {
@@ -361,35 +364,6 @@ suite = {
       },
     },
 
-    "FASTR_NATIVE_DEV": {
-      "description" : "support for overriding the native project implementation in a separate suite",
-      "dependencies" : ["com.oracle.truffle.r.native"],
-      "exclude" : [
-        "GNUR",
-        "GNU_ICONV",
-      ],
-      "os_arch" : {
-        "linux" : {
-          "amd64" : {
-            "path" : "mxbuild/dists/linux/amd64/fastr-native-dev.jar",
-          },
-          "sparcv9" : {
-            "path" : "mxbuild/dists/linux/sparcv9/fastr-native-dev.jar",
-          },
-        },
-        "darwin" : {
-          "amd64" : {
-            "path" : "mxbuild/dists/darwin/amd64/fastr-native-dev.jar",
-          },
-        },
-        "solaris" : {
-          "sparcv9" : {
-            "path" : "mxbuild/dists/solaris/sparcv9/fastr-native-dev.jar",
-          },
-        },
-      },
-    },
-
     "FASTR_RELEASE": {
       "description" : "a binary release of FastR",
       "dependencies" : ["com.oracle.truffle.r.release"],
-- 
GitLab


From 1c482c4bdbc985dc529925bfd7636cceba4060d6 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Thu, 9 Mar 2017 18:16:09 +0100
Subject: [PATCH 221/402] Implemented Rf_copyMatrix() and related fixes.

---
 .../fficall/src/jni/Rinternals.c              | 112 +++++++++--
 com.oracle.truffle.r.native/version.source    |   2 +-
 .../truffle/r/nodes/builtin/base/Prod.java    |  59 +++++-
 .../r/nodes/ffi/FFIUpCallRootNode.java        |   6 +
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      | 186 +++++++++++++++++-
 .../oracle/truffle/r/nodes/ffi/MiscNodes.java |  66 +++++++
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java |   3 +
 .../r/nodes/ffi/TracingUpCallsRFFIImpl.java   |  36 ++++
 .../objects/CollectGenericArgumentsNode.java  |   7 +-
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |  13 ++
 .../truffle/r/test/ExpectedTestOutput.test    |  40 ++++
 .../r/test/builtins/TestBuiltin_prod.java     |  12 +-
 12 files changed, 520 insertions(+), 22 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 9efedd0f00..7a21ecaa62 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -91,6 +91,9 @@ jmethodID logNotCharSXPWrapperMethodID;
 static jmethodID STRING_ELT_MethodID;
 static jmethodID VECTOR_ELT_MethodID;
 static jmethodID LENGTH_MethodID;
+static jmethodID R_do_slot_MethodID;
+static jmethodID R_do_slot_assign_MethodID;
+static jmethodID R_MethodsNamespaceMethodID;
 static jmethodID Rf_asIntegerMethodID;
 static jmethodID Rf_asRealMethodID;
 static jmethodID Rf_asCharMethodID;
@@ -105,6 +108,8 @@ static jmethodID TYPEOF_MethodID;
 static jmethodID OBJECT_MethodID;
 static jmethodID DUPLICATE_ATTRIB_MethodID;
 static jmethodID IS_S4_OBJECTMethodID;
+static jmethodID SET_S4_OBJECTMethodID;
+static jmethodID UNSET_S4_OBJECTMethodID;
 static jmethodID R_tryEvalMethodID;
 static jmethodID RDEBUGMethodID;
 static jmethodID SET_RDEBUGMethodID;
@@ -114,6 +119,7 @@ static jmethodID ENCLOSMethodID;
 static jmethodID PRVALUEMethodID;
 static jmethodID R_lsInternal3MethodID;
 static jmethodID R_do_MAKE_CLASS_MethodID;
+static jmethodID R_do_new_object_MethodID;
 static jmethodID PRSEENMethodID;
 static jmethodID PRENVMethodID;
 static jmethodID R_PromiseExprMethodID;
@@ -171,6 +177,7 @@ void init_internals(JNIEnv *env) {
 	Rf_classgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_classgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)V", 0);
 	R_do_MAKE_CLASS_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_MAKE_CLASS", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
+	R_do_new_object_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_new_object", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_FindNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_FindNamespace", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_BindingIsLockedID = checkGetMethodID(env, UpCallsRFFIClass, "R_BindingIsLocked", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_GetOption1MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_GetOption1", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
@@ -201,6 +208,9 @@ void init_internals(JNIEnv *env) {
 	STRING_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "STRING_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 	VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 	LENGTH_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "LENGTH", "(Ljava/lang/Object;)I", 0);
+	R_do_slot_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_slot", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
+	R_do_slot_assign_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_slot_assign", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
+	R_MethodsNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_MethodsNamespace", "()Ljava/lang/Object;", 0);
 	Rf_asIntegerMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asInteger", "(Ljava/lang/Object;)I", 0);
 	Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0);
 	Rf_asCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
@@ -214,6 +224,8 @@ void init_internals(JNIEnv *env) {
 	OBJECT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "OBJECT", "(Ljava/lang/Object;)I", 0);
 	DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 	IS_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "IS_S4_OBJECT", "(Ljava/lang/Object;)I", 0);
+	SET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_S4_OBJECT", "(Ljava/lang/Object;)V", 0);
+	UNSET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "UNSET_S4_OBJECT", "(Ljava/lang/Object;)V", 0);
 	R_tryEvalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_tryEval", "(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;", 0);
 	RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "RDEBUG", "(Ljava/lang/Object;)I", 0);
 	SET_RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RDEBUG", "(Ljava/lang/Object;I)V", 0);
@@ -477,6 +489,7 @@ SEXP Rf_install(const char *name) {
 	JNIEnv *thisenv = getEnv();
 	jstring string = (*thisenv)->NewStringUTF(thisenv, name);
 	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_installMethodID, string);
+        addGlobalRef(thisenv, result, 1);
 	return checkRef(thisenv, result);
 }
 
@@ -1377,10 +1390,13 @@ int IS_S4_OBJECT(SEXP x) {
 }
 
 void SET_S4_OBJECT(SEXP x) {
-	unimplemented("SET_S4_OBJECT");
+	JNIEnv *env = getEnv();
+	(*env)->CallVoidMethod(env, UpCallsRFFIObject, SET_S4_OBJECTMethodID, x);
 }
+
 void UNSET_S4_OBJECT(SEXP x) {
-	unimplemented("UNSET_S4_OBJECT");
+	JNIEnv *env = getEnv();
+	(*env)->CallVoidMethod(env, UpCallsRFFIObject, UNSET_S4_OBJECTMethodID, x);
 }
 
 Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
@@ -1595,11 +1611,17 @@ void R_RunWeakRefFinalizer(SEXP w) {
 }
 
 SEXP R_do_slot(SEXP obj, SEXP name) {
-	return unimplemented("R_do_slot");
+    TRACE(TARGp, obj, name);
+    JNIEnv *thisenv = getEnv();
+    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_slot_MethodID, obj, name);
+    return checkRef(thisenv, result);
 }
 
-SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
-	return unimplemented("R_do_slot_assign");
+SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) { // Same like R_set_slot
+    TRACE(TARGp, obj, name, value);
+    JNIEnv *thisenv = getEnv();
+    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_slot_assign_MethodID, obj, name, value);
+    return checkRef(thisenv, result);
 }
 
 int R_has_slot(SEXP obj, SEXP name) {
@@ -1615,17 +1637,84 @@ SEXP R_do_MAKE_CLASS(const char *what) {
 SEXP R_getClassDef (const char *what) {
 	return unimplemented("R_getClassDef");
 }
-
+    
 SEXP R_do_new_object(SEXP class_def) {
-	return unimplemented("R_do_new_object");
+    JNIEnv *thisenv = getEnv();
+    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_new_object_MethodID, class_def);
+    return checkRef(thisenv, result);
 }
 
 int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) {
-	return (int) unimplemented("R_check_class_and_super");
+    int ans;
+    SEXP cl = PROTECT(asChar(getAttrib(x, R_ClassSymbol)));
+    const char *class = CHAR(cl);
+    for (ans = 0; ; ans++) {
+	if (!strlen(valid[ans])) // empty string
+	    break;
+	if (!strcmp(class, valid[ans])) {
+	    UNPROTECT(1); /* cl */
+	    return ans;
+	}
+    }
+    /* if not found directly, now search the non-virtual super classes :*/
+    if(IS_S4_OBJECT(x)) {
+	/* now try the superclasses, i.e.,  try   is(x, "....");  superCl :=
+	   .selectSuperClasses(getClass("....")@contains, dropVirtual=TRUE)  */
+	SEXP classExts, superCl, _call;
+        // install() results cached anyway so the following variables could be non-static if needed
+	static SEXP s_contains = NULL, s_selectSuperCl = NULL;
+	int i;
+	if(!s_contains) {
+	    s_contains      = install("contains");
+	    s_selectSuperCl = install(".selectSuperClasses");
+	}
+	SEXP classDef = PROTECT(R_getClassDef(class));
+	PROTECT(classExts = R_do_slot(classDef, s_contains));
+	PROTECT(_call = lang3(s_selectSuperCl, classExts,
+			      /* dropVirtual = */ ScalarLogical(1)));
+	superCl = eval(_call, rho);
+	UNPROTECT(3); /* _call, classExts, classDef */
+	PROTECT(superCl);
+	for(i=0; i < LENGTH(superCl); i++) {
+	    const char *s_class = CHAR(STRING_ELT(superCl, i));
+	    for (ans = 0; ; ans++) {
+		if (!strlen(valid[ans]))
+		    break;
+		if (!strcmp(s_class, valid[ans])) {
+		    UNPROTECT(2); /* superCl, cl */
+		    return ans;
+		}
+	    }
+	}
+	UNPROTECT(1); /* superCl */
+    }
+    UNPROTECT(1); /* cl */
+    return -1;
 }
 
 int R_check_class_etc (SEXP x, const char **valid) {
-	return (int) unimplemented("R_check_class_etc");
+    // install() results cached anyway so the following variables could be non-static if needed
+    static SEXP meth_classEnv = NULL;
+    SEXP cl = getAttrib(x, R_ClassSymbol), rho = R_GlobalEnv, pkg;
+    if (!meth_classEnv)
+        meth_classEnv = install(".classEnv");
+
+    pkg = getAttrib(cl, R_PackageSymbol); /* ==R== packageSlot(class(x)) */
+    if (!isNull(pkg)) { /* find  rho := correct class Environment */
+        SEXP clEnvCall;
+        // FIXME: fails if 'methods' is not loaded.
+        PROTECT(clEnvCall = lang2(meth_classEnv, cl));
+        JNIEnv *thisenv = getEnv();
+        SEXP methodsNamespace = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_MethodsNamespaceMethodID);
+        rho = eval(clEnvCall, methodsNamespace);
+        UNPROTECT(1);
+        if (!isEnvironment(rho))
+            error(_("could not find correct environment; please report!"));
+    }
+    PROTECT(rho);
+    int res = R_check_class_and_super(x, valid, rho);
+    UNPROTECT(1);
+    return res;
 }
 
 SEXP R_PreserveObject(SEXP x) {
@@ -1648,11 +1737,12 @@ Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
 }
 
 void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	JNIEnv *thisenv = getEnv();
+    JNIEnv *thisenv = getEnv();
     (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_copyListMatrixMethodID, s, t, byrow);
 }
 
 void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	JNIEnv *thisenv = getEnv();
+    JNIEnv *thisenv = getEnv();
     (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_copyMatrixMethodID, s, t, byrow);
 }
+
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 3c032078a4..d6b24041cf 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-18
+19
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
index 132a964889..34cd247dd9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
@@ -15,12 +15,16 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -49,12 +53,53 @@ public abstract class Prod extends RBuiltinNode {
 
     @Specialization
     protected Object prod(RArgsValuesAndNames args) {
+        int argsLen = args.getLength();
+        if (argsLen == 0) {
+            return 1d;
+        }
         if (prodRecursive == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             prodRecursive = insert(ProdNodeGen.create());
         }
-        // TODO: eventually handle multiple vectors properly
-        return prodRecursive.executeObject(args.getArgument(0));
+        Object ret = prodRecursive.executeObject(args.getArgument(0));
+        if (argsLen != 1) {
+            double prodReal;
+            double prodImg;
+            boolean complex;
+            if (ret instanceof RComplex) {
+                RComplex c = (RComplex) ret;
+                prodReal = c.getRealPart();
+                prodImg = c.getImaginaryPart();
+                complex = true;
+            } else {
+                prodReal = (Double) ret;
+                prodImg = 0d;
+                complex = false;
+            }
+            for (int i = 1; i < argsLen; i++) {
+                Object aProd = prodRecursive.executeObject(args.getArgument(i));
+                double aProdReal;
+                double aProdImg;
+                if (aProd instanceof RComplex) {
+                    RComplex c = (RComplex) aProd;
+                    aProdReal = c.getRealPart();
+                    aProdImg = c.getImaginaryPart();
+                    complex = true;
+                } else {
+                    aProdReal = (Double) aProd;
+                    aProdImg = 0d;
+                }
+                if (complex) {
+                    RComplex c = prod.op(prodReal, prodImg, aProdReal, aProdImg);
+                    prodReal = c.getRealPart();
+                    prodImg = c.getImaginaryPart();
+                } else {
+                    prodReal = prod.op(prodReal, aProdReal);
+                }
+            }
+            ret = complex ? RComplex.valueOf(prodReal, prodImg) : prodReal;
+        }
+        return ret;
     }
 
     @Specialization
@@ -93,4 +138,14 @@ public abstract class Prod extends RBuiltinNode {
         }
         return product;
     }
+
+    @Specialization
+    protected double prod(RNull n) {
+        return 1d;
+    }
+
+    @Fallback
+    protected Object prod(Object o) {
+        throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) RRuntime.asAbstractVector(o)).getRType().getName());
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
index e7d26f933b..475f51bdfd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
@@ -35,6 +35,9 @@ import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CARNodeGen;
 import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDDRNodeGen;
 import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDRNodeGen;
 import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.LENGTHNodeGen;
+import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoNewObjectNodeGen;
+import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoSlotNodeGen;
+import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoSlotAssignNodeGen;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 
@@ -91,6 +94,9 @@ public final class FFIUpCallRootNode extends RootNode {
         FFIUpCallRootNode.add(RFFIUpCallMethod.CADDR, CADDRNodeGen::create);
         FFIUpCallRootNode.add(RFFIUpCallMethod.CDDR, CDDRNodeGen::create);
         FFIUpCallRootNode.add(RFFIUpCallMethod.LENGTH, LENGTHNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_new_object, RDoNewObjectNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_slot, RDoSlotNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_slot_assign, RDoSlotAssignNodeGen::create);
     }
 
 }
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 2c78c9fbb6..2bb4cee421 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
@@ -80,13 +80,20 @@ import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
-import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListBaseVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -99,6 +106,8 @@ import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.rng.RRNG;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class provides a simple Java-based implementation of {@link UpCallsRFFI}, where all the
@@ -114,6 +123,8 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  */
 public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
+    private final Map<String, Object> nameSymbolCache = new ConcurrentHashMap<>();
+
     // Checkstyle: stop method name check
 
     @Override
@@ -197,6 +208,11 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), null, clazz);
     }
 
+    @Override
+    public Object R_do_new_object(Object classDef) {
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_new_object).call(classDef);
+    }
+
     @Override
     public Object Rf_findVar(Object symbolArg, Object envArg) {
         return findVarInFrameHelper(envArg, symbolArg, true);
@@ -319,7 +335,13 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public Object Rf_install(Object name) {
-        return RDataFactory.createSymbolInterned((String) name);
+        String nameStr = (String) name;
+        Object ret = nameSymbolCache.get(nameStr);
+        if (ret == null) {
+            ret = RDataFactory.createSymbolInterned(nameStr);
+            nameSymbolCache.put(nameStr, ret);
+        }
+        return ret;
     }
 
     @Override
@@ -798,13 +820,140 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_copyListMatrix(Object s, Object t, int byrow) {
+    public void Rf_copyListMatrix(Object t, Object s, int byrow) {
         throw unimplemented();
     }
 
     @Override
-    public void Rf_copyMatrix(Object s, Object t, int byrow) {
-        throw unimplemented();
+    public void Rf_copyMatrix(Object t, Object s, int byRow) {
+        int tRows = RRuntime.nrows(t);
+        int tCols = RRuntime.ncols(t);
+        final Object sav = RRuntime.asAbstractVector(s);
+        ContainerItemCopier c;
+        if (sav instanceof RAbstractContainer) {
+            int sLen = ((RAbstractContainer) sav).getLength();
+            if (sav instanceof RAbstractIntVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractIntVector sv = (RAbstractIntVector) sav;
+                    private final RAbstractIntVector tv = (RAbstractIntVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx));
+                    }
+                };
+            } else if (sav instanceof RAbstractDoubleVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractDoubleVector sv = (RAbstractDoubleVector) sav;
+                    private final RAbstractDoubleVector tv = (RAbstractDoubleVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx));
+                    }
+                };
+            } else if (sav instanceof RAbstractLogicalVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractLogicalVector sv = (RAbstractLogicalVector) sav;
+                    private final RAbstractLogicalVector tv = (RAbstractLogicalVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx));
+                    }
+                };
+            } else if (sav instanceof RAbstractComplexVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractComplexVector sv = (RAbstractComplexVector) sav;
+                    private final RAbstractComplexVector tv = (RAbstractComplexVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx));
+                    }
+                };
+            } else if (sav instanceof RAbstractStringVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractStringVector sv = (RAbstractStringVector) sav;
+                    private final RAbstractStringVector tv = (RAbstractStringVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx));
+                    }
+                };
+            } else if (sav instanceof RAbstractRawVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractRawVector sv = (RAbstractRawVector) sav;
+                    private final RAbstractRawVector tv = (RAbstractRawVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setRawDataAt(tvStore, tIdx, sv.getRawDataAt(sIdx));
+                    }
+                };
+            } else if (sav instanceof RAbstractListBaseVector) {
+                c = new ContainerItemCopier() {
+                    private final RAbstractListBaseVector sv = (RAbstractListBaseVector) sav;
+                    private final RAbstractListBaseVector tv = (RAbstractListBaseVector) t;
+                    private final Object tvStore = tv.getInternalStore();
+
+                    @Override
+                    public void copy(int sIdx, int tIdx) {
+                        tv.setDataAt(tvStore, tIdx, sv.getDataAt(sIdx));
+                    }
+                };
+            } else {
+                throw unimplemented();
+            }
+            if (byRow != 0) {
+                int sIdx = 0;
+                for (int i = 0; i < tRows; i++) {
+                    int tIdx = i;
+                    for (int j = 0; j < tCols; j++) {
+                        c.copy(sIdx, tIdx);
+                        sIdx++;
+                        if (sIdx >= sLen) {
+                            sIdx -= sLen;
+                        }
+                        tIdx += tRows;
+                    }
+                }
+            } else { // Copy by column
+                int tLen = ((RAbstractContainer) t).getLength();
+                if (sLen >= tLen) {
+                    for (int i = 0; i < tLen; i++) {
+                        c.copy(i, i);
+                    }
+                } else { // Recycle needed
+                    int sIdx = 0;
+                    for (int i = 0; i < tLen; i++) {
+                        c.copy(sIdx, i);
+                        if (sIdx >= sLen) {
+                            sIdx -= sLen;
+                        }
+                    }
+                }
+            }
+
+        } else { // source is non-RAbstractContainer
+            throw unimplemented();
+        }
+    }
+
+    /**
+     * Helper interface for {@link #Rf_copyMatrix(java.lang.Object, java.lang.Object, int)} that
+     * copies from source index in an (internally held) source container into target index in a
+     * target container.
+     */
+    interface ContainerItemCopier {
+        void copy(int sIdx, int tIdx);
     }
 
     @Override
@@ -966,7 +1115,17 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public int IS_S4_OBJECT(Object x) {
-        return x instanceof RS4Object ? 1 : 0;
+        return ((x instanceof RTypedValue) && ((RTypedValue) x).isS4()) ? 1 : 0;
+    }
+
+    @Override
+    public void SET_S4_OBJECT(Object x) {
+        guaranteeInstanceOf(x, RTypedValue.class).setS4();
+    }
+
+    @Override
+    public void UNSET_S4_OBJECT(Object x) {
+        guaranteeInstanceOf(x, RTypedValue.class).unsetS4();
     }
 
     @Override
@@ -1264,4 +1423,19 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return conn.isSeekable();
     }
 
+    @Override
+    public Object R_do_slot(Object o, Object name) {
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_slot).call(o, name);
+    }
+
+    @Override
+    public Object R_do_slot_assign(Object o, Object name, Object value) {
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_slot_assign).call(o, name, value);
+    }
+
+    @Override
+    public Object R_MethodsNamespace() {
+        return REnvironment.getRegisteredNamespace("methods");
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
index f3e2f0edc2..3a1ee7f7de 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
@@ -26,8 +26,15 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.nodes.access.AccessSlotNode;
+import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
+import com.oracle.truffle.r.nodes.access.UpdateSlotNode;
+import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen;
+import com.oracle.truffle.r.nodes.objects.NewObject;
+import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
@@ -80,4 +87,63 @@ public final class MiscNodes {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.LENGTH_MISAPPLIED, SEXPTYPE.gnuRTypeForObject(obj).name());
         }
     }
+
+    @TypeSystemReference(RTypes.class)
+    abstract static class RDoSlotNode extends FFIUpCallNode.Arg2 {
+
+        @Child private AccessSlotNode accessSlotNode;
+
+        RDoSlotNode() {
+            accessSlotNode = AccessSlotNodeGen.create(false);
+        }
+
+        @Specialization
+        Object doSlot(Object o, RSymbol nameSym) {
+            return accessSlotNode.executeAccess(o, nameSym.getName());
+        }
+
+        @Fallback
+        Object doSlot(@SuppressWarnings("unused") Object o, @SuppressWarnings("unused") Object name) {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name());
+        }
+
+    }
+
+    @TypeSystemReference(RTypes.class)
+    abstract static class RDoSlotAssignNode extends FFIUpCallNode.Arg3 {
+
+        @Child private UpdateSlotNode updateSlotNode;
+
+        RDoSlotAssignNode() {
+            updateSlotNode = UpdateSlotNodeGen.create();
+        }
+
+        @Specialization
+        Object doSlotAssign(Object o, String name, Object value) {
+            return updateSlotNode.executeUpdate(o, name, value);
+        }
+
+        @Fallback
+        Object doSlot(@SuppressWarnings("unused") Object o, Object name, @SuppressWarnings("unused") Object value) {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name());
+        }
+
+    }
+
+    @TypeSystemReference(RTypes.class)
+    abstract static class RDoNewObjectNode extends FFIUpCallNode.Arg1 {
+
+        @Child private NewObject newObjectNode;
+
+        RDoNewObjectNode() {
+            newObjectNode = NewObjectNodeGen.create();
+        }
+
+        @Specialization
+        Object doNewObject(Object classDef) {
+            return newObjectNode.execute(classDef);
+        }
+
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index 25d2f9f385..f3a19b0033 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -81,6 +81,9 @@ public enum RFFIUpCallMethod {
     R_WriteConnection("(sint32, object) : sint32"),
     R_computeIdentical("(object, object, sint32) : sint32"),
     R_do_MAKE_CLASS("(string) : object"),
+    R_do_new_object("(object) : object"),
+    R_do_slot("(object, object) : object"),
+    R_do_slot_assign("(object, object, object) : object"),
     R_getContextCall("(object) : object"),
     R_getContextEnv("(object) : object"),
     R_getContextFun("(object) : object"),
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 b89d83cc56..9ad307eea7 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
@@ -117,6 +117,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.R_do_MAKE_CLASS(clazz);
     }
 
+    @Override
+    public Object R_do_new_object(Object classDef) {
+        RFFIUtils.traceUpCall("R_do_new_object", classDef);
+        return delegate.R_do_new_object(classDef);
+    }
+
     @Override
     public Object Rf_findVar(Object symbolArg, Object envArg) {
         RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg);
@@ -579,6 +585,18 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.IS_S4_OBJECT(x);
     }
 
+    @Override
+    public void SET_S4_OBJECT(Object x) {
+        RFFIUtils.traceUpCall("setS4Object");
+        delegate.SET_S4_OBJECT(x);
+    }
+
+    @Override
+    public void UNSET_S4_OBJECT(Object x) {
+        RFFIUtils.traceUpCall("unsetS4Object");
+        delegate.UNSET_S4_OBJECT(x);
+    }
+
     @Override
     public void Rprintf(Object message) {
         RFFIUtils.traceUpCall("Rprintf", message);
@@ -789,4 +807,22 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.isSeekable(x);
     }
 
+    @Override
+    public Object R_do_slot(Object o, Object name) {
+        RFFIUtils.traceUpCall("R_do_slot", o, name);
+        return delegate.R_do_slot(o, name);
+    }
+
+    @Override
+    public Object R_do_slot_assign(Object o, Object name, Object value) {
+        RFFIUtils.traceUpCall("R_do_slot", o, name, value);
+        return delegate.R_do_slot_assign(o, name, value);
+    }
+
+    @Override
+    public Object R_MethodsNamespace() {
+        RFFIUtils.traceUpCall("R_MethodsNamespace");
+        return delegate.R_MethodsNamespace();
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java
index 3acb958ef9..6b57fd298b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,9 @@ import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -90,6 +92,9 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode {
                 throw new SlowPathException();
             }
             Object value = argReads[i].execute(frame);
+            if (value == REmpty.instance || value == RMissing.instance) {
+                value = null;
+            }
             result[i] = valueMissingProfile.profile(value == null) ? "missing" : classHierarchyNodes[i].executeString(promiseHelper.checkEvaluate(frame, value));
         }
         return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
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 dceb6d282d..75132c6fe4 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
@@ -73,6 +74,8 @@ public interface StdUpCallsRFFI {
 
     Object R_do_MAKE_CLASS(@RFFICstring Object clazz);
 
+    Object R_do_new_object(Object classDef);
+
     /**
      * WARNING: argument order reversed from Rf_findVarInFrame!
      */
@@ -216,6 +219,10 @@ public interface StdUpCallsRFFI {
 
     int IS_S4_OBJECT(Object x);
 
+    void SET_S4_OBJECT(Object x);
+
+    void UNSET_S4_OBJECT(Object x);
+
     void Rprintf(@RFFICstring Object message);
 
     void GetRNGstate();
@@ -270,4 +277,10 @@ public interface StdUpCallsRFFI {
 
     boolean isSeekable(Object x);
 
+    Object R_do_slot(Object o, Object name);
+
+    Object R_do_slot_assign(Object o, Object name, Object value);
+
+    Object R_MethodsNamespace();
+
 }
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 98500f6ccb..339c400826 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
@@ -44815,6 +44815,42 @@ age                        0.00561 0.012    0.00872  0.22  1.0 0.64000
 sex                       -1.65487 0.483    0.38527 11.74  1.0 0.00061
 frailty(id, dist = 't', c                           20.33 13.9 0.12000
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod('a')}
+Error in prod("a") : invalid 'type' (character) of argument
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod()}
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(2+3i,42)}
+[1] 84+126i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(2+3i,42+5i)}
+[1] 69+136i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(2+3i,c())}
+[1] 2+3i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(42,2+3i)}
+[1] 84+126i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(NULL)}
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(c())}
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(c(),c())}
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
 #{prod(c(1+2i))}
 [1] 1+2i
@@ -44847,6 +44883,10 @@ frailty(id, dist = 't', c                           20.33 13.9 0.12000
 #{prod(c(TRUE, TRUE))}
 [1] 1
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{prod(list())}
+Error in prod(list()) : invalid 'type' (list) of argument
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.Unknown#
 #{prod(c(1,2,3,4,5,NA),FALSE)}
 [1] NA
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java
index 264a3af783..4adffd95dc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -82,6 +82,16 @@ public class TestBuiltin_prod extends TestBase {
         assertEval("{prod(c(1+2i,1+3i,1+45i))}");
         assertEval("{prod(c(TRUE, TRUE))}");
         assertEval("{prod(c(TRUE, FALSE))}");
+        assertEval("{prod()}");
+        assertEval("{prod(NULL)}");
+        assertEval("{prod(c())}");
+        assertEval("{prod(c(),c())}");
+        assertEval("{prod(2+3i,c())}");
+        assertEval("{prod(2+3i,42+5i)}");
+        assertEval("{prod(2+3i,42)}");
+        assertEval("{prod(42,2+3i)}");
+        assertEval("{prod('a')}");
+        assertEval("{prod(list())}");
     }
 
     @Test
-- 
GitLab


From 2216dcb2097099200618993ab4e45e90da4c28ba Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 30 Mar 2017 11:11:21 +0200
Subject: [PATCH 222/402] Added missing specialization to function 'unlist'.

---
 .../com/oracle/truffle/r/nodes/builtin/base/Unlist.java  | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
index 67b2bbd517..5d2925cfbe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.UnlistNodeGen.RecursiveLengthNodeGen;
 import com.oracle.truffle.r.nodes.unary.PrecedenceNode;
 import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen;
+import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -40,11 +41,12 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-@RBuiltin(name = "unlist", kind = INTERNAL, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE)
+@RBuiltin(name = "unlist", kind = INTERNAL, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE)
 public abstract class Unlist extends RBuiltinNode {
 
     // portions of the algorithm were transcribed from GNU R
@@ -96,6 +98,11 @@ public abstract class Unlist extends RBuiltinNode {
             return 1;
         }
 
+        @Specialization
+        protected int getLength(@SuppressWarnings("unused") RSymbol s) {
+            return 1;
+        }
+
         @Specialization(guards = "!isVectorList(vector)")
         protected int getLength(RAbstractVector vector) {
             return vector.getLength();
-- 
GitLab


From c2d8d037e7c47a4a2b95a402c8b6479e2e5d8928 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 30 Mar 2017 13:20:45 +0200
Subject: [PATCH 223/402] Fix: Re-throwing return exception in function 'eval'
 if it does not belong to the last eval call.

---
 .../truffle/r/nodes/builtin/base/Eval.java    | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
index 00e8d03e3f..a766098384 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
@@ -37,12 +37,14 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.EvalNodeGen.EvalEnvCastNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.FrameFunctions.SysFrame;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctions.Get;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
+import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.ReturnException;
@@ -63,6 +65,11 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 @RBuiltin(name = "eval", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"expr", "envir", "enclos"}, behavior = COMPLEX)
 public abstract class Eval extends RBuiltinNode {
 
+    /**
+     * Profiling for catching {@link ReturnException}s.
+     */
+    private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile();
+
     /**
      * Eval takes two arguments that specify the environment where the expression should be
      * evaluated: 'envir', 'enclos'. These arguments are pre-processed by the means of default
@@ -148,7 +155,11 @@ public abstract class Eval extends RBuiltinNode {
         try {
             return RContext.getEngine().eval(expr, environment, rCaller);
         } catch (ReturnException ret) {
-            return ret.getResult();
+            if (returnTopLevelProfile.profile(ret.getTarget() == rCaller)) {
+                return ret.getResult();
+            } else {
+                throw ret;
+            }
         } finally {
             visibility.executeAfterCall(frame, rCaller);
         }
@@ -161,7 +172,11 @@ public abstract class Eval extends RBuiltinNode {
         try {
             return RContext.getEngine().eval(expr, environment, rCaller);
         } catch (ReturnException ret) {
-            return ret.getResult();
+            if (returnTopLevelProfile.profile(ret.getTarget() == rCaller)) {
+                return ret.getResult();
+            } else {
+                throw ret;
+            }
         } finally {
             visibility.executeAfterCall(frame, rCaller);
         }
-- 
GitLab


From f60694d7bcfa97fc63c1a6abc925173d93c86f99 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 31 Mar 2017 12:12:06 +0200
Subject: [PATCH 224/402] Implemented serialization of active bindings. Fix:
 Serious bug in deserialization of attributes of functions.

---
 .../oracle/truffle/r/runtime/RSerialize.java  | 57 +++++++++++++--
 .../truffle/r/test/ExpectedTestOutput.test    | 70 +++++++++++++++++++
 .../com/oracle/truffle/r/test/S4/TestS4.java  |  1 +
 .../test/builtins/TestBuiltin_serialize.java  |  9 +++
 4 files changed, 131 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index a28f47de13..eda8d1fee8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -33,6 +33,10 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.runtime.conn.RConnection;
@@ -71,6 +75,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
@@ -115,6 +120,7 @@ public class RSerialize {
         static final int LEVELS_SHIFT = 12;
         static final int CACHED_MASK = 1 << 5;
         static final int HASHASH_MASK = 1;
+        static final int IS_ACTIVE_BINDING_MASK = 1 << 15;
 
         private Flags() {
             // prevent construction
@@ -142,6 +148,10 @@ public class RSerialize {
             return (flagsValue & HAS_TAG_BIT_MASK) != 0;
         }
 
+        public static boolean isActiveBinding(int levs) {
+            return (levs & IS_ACTIVE_BINDING_MASK) != 0;
+        }
+
         public static int packFlags(SEXPTYPE type, int gpbits, boolean isObj, boolean hasAttr, boolean hasTag) {
             int val = type.code;
             int levs = gpbits & (~(CACHED_MASK | HASHASH_MASK));
@@ -490,14 +500,13 @@ public class RSerialize {
                                 if (val == RNull.instance) {
                                     continue;
                                 }
-                                RPairList pl = (RPairList) val;
-                                env.safePut(((RSymbol) pl.getTag()).getName(), pl.car());
+                                safePutToEnv(env, (RPairList) val);
                             }
                         }
                     } else {
                         while (frame != RNull.instance) {
                             RPairList pl = (RPairList) frame;
-                            env.safePut(((RSymbol) pl.getTag()).getName(), pl.car());
+                            safePutToEnv(env, pl);
                             frame = pl.cdr();
                         }
                     }
@@ -534,8 +543,14 @@ public class RSerialize {
                     Object attrItem = RNull.instance;
                     Object tagItem = RNull.instance;
                     if (Flags.hasAttr(flags)) {
+                        // create new language parsing context
+                        int safedLangDepth = langDepth;
+                        langDepth = 0;
                         attrItem = readItem();
 
+                        // restore language parsing context
+                        langDepth = safedLangDepth;
+
                     }
                     if (Flags.hasTag(flags)) {
                         tagItem = readItem();
@@ -622,6 +637,10 @@ public class RSerialize {
                         }
 
                         case LISTSXP:
+                            if (Flags.isActiveBinding(levs)) {
+                                assert carItem instanceof RFunction;
+                                carItem = new ActiveBinding(RType.Any, (RFunction) carItem);
+                            }
                             RPairList pairList = RDataFactory.createPairList(carItem, cdrItem, tagItem, type);
                             result = pairList;
                             if (attrItem != RNull.instance) {
@@ -829,6 +848,17 @@ public class RSerialize {
             return checkResult(result);
         }
 
+        private static void safePutToEnv(REnvironment env, RPairList pl) {
+            String name = ((RSymbol) pl.getTag()).getName();
+            Object car = pl.car();
+            if (ActiveBinding.isActiveBinding(car)) {
+                FrameSlot frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(env.getFrame().getFrameDescriptor(), name, FrameSlotKind.Object);
+                FrameSlotChangeMonitor.setActiveBinding(env.getFrame(), frameSlot, (ActiveBinding) car, false, null);
+            } else {
+                env.safePut(name, car);
+            }
+        }
+
         private static Object checkResult(Object result) {
             assert result != null;
             return result;
@@ -1422,7 +1452,7 @@ public class RSerialize {
                          */
                         String[] bindings = env.ls(true, null, false).getDataWithoutCopying();
                         for (String binding : bindings) {
-                            Object value = env.get(binding);
+                            Object value = getValueIgnoreActiveBinding(env.getFrame(), binding);
                             writePairListEntry(binding, value);
                         }
                         terminatePairList();
@@ -1655,6 +1685,16 @@ public class RSerialize {
             } while (tailCall);
         }
 
+        private static Object getValueIgnoreActiveBinding(Frame frame, String key) {
+            FrameDescriptor fd = frame.getFrameDescriptor();
+            FrameSlot slot = fd.findFrameSlot(key);
+            if (slot == null) {
+                return null;
+            } else {
+                return frame.getValue(slot);
+            }
+        }
+
         private Object getPersistentName(Object obj) {
             if (hook == null) {
                 return RNull.instance;
@@ -1728,7 +1768,8 @@ public class RSerialize {
         }
 
         private void writePairListEntry(String name, Object value) throws IOException {
-            stream.writeInt(Flags.packFlags(SEXPTYPE.LISTSXP, 0, false, false, true));
+            boolean isActiveBinding = ActiveBinding.isActiveBinding(value);
+            stream.writeInt(Flags.packFlags(SEXPTYPE.LISTSXP, isActiveBinding ? Flags.IS_ACTIVE_BINDING_MASK : 0, false, false, true));
             RSymbol sym = state.findSymbol(name);
             int refIndex;
             if ((refIndex = getRefIndex(sym)) != -1) {
@@ -1736,7 +1777,11 @@ public class RSerialize {
             } else {
                 writeSymbol(sym);
             }
-            writeItem(value);
+            if (isActiveBinding) {
+                writeItem(((ActiveBinding) value).getFunction());
+            } else {
+                writeItem(value);
+            }
         }
 
         private void writeSymbol(RSymbol name) throws IOException {
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 339c400826..d76ce00c5a 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
@@ -425,6 +425,26 @@ Slots:
 Name:        j
 Class: numeric
 
+##com.oracle.truffle.r.test.S4.TestS4.testClassCreation#
+#{ setClass('foo', contains='standardGeneric'); getClass('foo') }
+Class "foo" [in ".GlobalEnv"]
+
+Slots:
+
+Name:           .Data        generic        package          group
+Class:       function      character      character           list
+
+Name:      valueClass      signature        default       skeleton
+Class:      character      character optionalMethod           call
+
+Extends:
+Class "standardGeneric", directly
+Class "genericFunction", by class "standardGeneric", distance 2
+Class "function", by class "standardGeneric", distance 3
+Class "OptionalFunction", by class "standardGeneric", distance 4
+Class "PossibleMethod", by class "standardGeneric", distance 4
+Class "optionalMethod", by class "standardGeneric", distance 5
+
 ##com.oracle.truffle.r.test.S4.TestS4.testConversions#
 #{  asS4(7:42) }
  [1]  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
@@ -62325,6 +62345,35 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite
 #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv);
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)
+  [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 07 03 00 00 04 02 00 00 00
+ [26] 01 00 04 00 09 00 00 00 09 63 6c 61 73 73 4e 61 6d 65 00 00 02 10 00 00 00
+ [51] 01 00 04 00 09 00 00 00 0a 46 6f 6f 53 65 72 69 61 6c 31 00 00 04 02 00 00
+ [76] 00 01 00 04 00 09 00 00 00 07 70 61 63 6b 61 67 65 00 00 00 10 00 00 00 01
+[101] 00 04 00 09 00 00 00 0a 2e 47 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 04
+[126] 02 00 00 02 ff 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 6c 6f
+[151] 62 61 6c 45 6e 76 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 05 63 6c 61
+[176] 73 73 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 16 63 6c 61 73 73 47 65
+[201] 6e 65 72 61 74 6f 72 46 75 6e 63 74 69 6f 6e 00 00 04 02 00 00 02 ff 00 00
+[226] 00 10 00 00 00 01 00 04 00 09 00 00 00 07 6d 65 74 68 6f 64 73 00 00 00 fe
+[251] 00 00 00 fe 00 00 00 fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 03 2e
+[276] 2e 2e 00 00 00 fb 00 00 00 fe 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00
+[301] 03 6e 65 77 00 00 00 02 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 0a 46
+[326] 6f 6f 53 65 72 69 61 6c 31 00 00 04 02 00 00 02 ff 00 00 00 10 00 00 00 01
+[351] 00 04 00 09 00 00 00 0a 2e 47 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 00
+[376] 06 00 00 04 ff 00 00 00 fe
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); mc <- setClass('FooSerial0', representation(a = 'call')); obj <- new('FooSerial0'); serialize(obj, connection=NULL)
+  [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 03 19 00 00 04 02 00 00 00
+ [26] 01 00 04 00 09 00 00 00 01 61 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00
+ [51] 07 3c 75 6e 64 65 66 3e 00 00 00 fe 00 00 04 02 00 00 00 01 00 04 00 09 00
+ [76] 00 00 05 63 6c 61 73 73 00 00 02 10 00 00 00 01 00 04 00 09 00 00 00 0a 46
+[101] 6f 6f 53 65 72 69 61 6c 30 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 07
+[126] 70 61 63 6b 61 67 65 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47
+[151] 6c 6f 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 fe
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
 #options(keep.source=FALSE); serialize('asdf', connection=NULL)
  [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 10 00 00 00 01 00 04 00
@@ -62759,6 +62808,20 @@ integer(0)
 [51] 00 00 00 01 00 04 00 09 00 00 00 05 6e 61 6d 65 73 00 00 00 10 00 00 00 01
 [76] 00 04 00 09 00 00 00 06 65 6e 63 6c 6f 73 00 00 00 fe
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); data <- serialize(val, connection=NULL); newenv <- unserialize(rawConnection(data)); newenv$a
+[1] "hello"
+[1] "hello"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); serialize(val, connection=NULL)
+  [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 04 00 00 00 00 00 00 00
+ [26] fd 08 00 04 02 00 00 00 01 00 04 00 09 00 00 00 01 61 00 00 04 03 00 00 00
+ [51] fd 00 00 04 02 00 00 00 01 00 04 00 09 00 00 00 01 78 00 00 00 fb 00 00 00
+ [76] fe 00 00 00 06 00 00 00 01 00 04 00 09 00 00 00 05 70 72 69 6e 74 00 00 00
+[101] 02 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 05 68 65 6c 6c 6f 00 00 00
+[126] fe 00 00 00 fe 00 00 00 fe 00 00 00 fe
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
 #options(keep.source=FALSE); val <- new.env(hash=FALSE); serialize(val, connection=NULL)
  [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 00 00 04 00 00 00 00 00 00 00
@@ -62812,6 +62875,13 @@ integer(0)
 [151] 63 6b 61 67 65 00 00 00 10 00 00 00 01 00 04 00 09 00 00 00 0a 2e 47 6c 6f
 [176] 62 61 6c 45 6e 76 00 00 00 fe 00 00 00 fe
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+#{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }
+function ()
+NULL
+attr(,"skeleton")
+`<undef>`()
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_setEncoding.testsetEncoding1#
 #argv <- list('abc', 'UTF-8'); .Internal(setEncoding(argv[[1]], argv[[2]]))
 [1] "abc"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index d5cf915d84..09a616189e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -103,6 +103,7 @@ public class TestS4 extends TestRBase {
     public void testClassCreation() {
         assertEval("{ setClass(\"foo\", representation(j=\"numeric\")); getClass(\"foo\") }");
         assertEval("{ setClass(\"foo\"); setClass(\"bar\", representation(j = \"numeric\"), contains = \"foo\"); is.null(getClass(\"foo\")@prototype) }");
+        assertEval("{ setClass('foo', contains='standardGeneric'); getClass('foo') }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
index 0679742b3e..3e031ad10e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
@@ -101,5 +101,14 @@ public class TestBuiltin_serialize extends TestBase {
         assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$d <- TRUE; serialize(val, connection=NULL)");
         assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$e <- 5+9i; serialize(val, connection=NULL)");
         assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); val$f <- NA; serialize(val, connection=NULL)");
+
+        // active bindings
+        assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); serialize(val, connection=NULL)");
+        assertEval("options(keep.source=FALSE); val <- new.env(hash=FALSE); makeActiveBinding('a', function(x) print('hello'), val); data <- serialize(val, connection=NULL); newenv <- unserialize(rawConnection(data)); newenv$a");
+
+        assertEval("options(keep.source=FALSE); mc <- setClass('FooSerial0', representation(a = 'call')); obj <- new('FooSerial0'); serialize(obj, connection=NULL)");
+        assertEval(Ignored.ImplementationError, "options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)");
+
+        assertEval("{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }");
     }
 }
-- 
GitLab


From 07e9dc520a79e2ee1d6d498890e06d13d788d48b Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 3 Apr 2017 15:24:04 +0200
Subject: [PATCH 225/402] Fix: Invalid argument matching for primitive
 functions with different or implicit signature.

---
 .../oracle/truffle/r/nodes/builtin/base/Eval.java    |  1 -
 .../truffle/r/nodes/objects/ExecuteMethod.java       | 12 +++---------
 .../oracle/truffle/r/test/ExpectedTestOutput.test    |  8 ++++++--
 .../src/com/oracle/truffle/r/test/S4/TestS4.java     |  1 +
 4 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
index a766098384..2164f840c0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
@@ -44,7 +44,6 @@ import com.oracle.truffle.r.nodes.builtin.base.FrameFunctions.SysFrame;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctions.Get;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
-import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.ReturnException;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java
index 4619df7873..636a8b4c95 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -14,14 +14,12 @@ package com.oracle.truffle.r.nodes.objects;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.CallMatcherNode;
-import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNode;
 import com.oracle.truffle.r.nodes.function.signature.CollectArgumentsNodeGen;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RArguments.S4Args;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -45,12 +43,8 @@ final class ExecuteMethod extends RBaseNode {
             callMatcher = insert(CallMatcherNode.create(false));
         }
 
-        FormalArguments formals = ((RRootNode) fdef.getRootNode()).getFormalArguments();
-        ArgumentsSignature signature = formals.getSignature();
-        Object[] oldArgs = collectArgs.execute(frame, signature);
-
         S4Args s4Args = new S4Args(readDefined.execute(frame), readMethod.execute(frame), readTarget.execute(frame), readGeneric.execute(frame), readMethods.execute(frame));
 
-        return callMatcher.execute(frame, signature, oldArgs, fdef, fname, s4Args);
+        return callMatcher.execute(frame, RArguments.getSignature(frame), RArguments.getArguments(frame), fdef, fname, s4Args);
     }
 }
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 d76ce00c5a..322f7f2982 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
@@ -60,7 +60,7 @@ Error: invalid assignment for reference class field ‘a’, should be from clas
 [1] TRUE
 [1] TRUE
 
-##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Output.IgnoreWhitespace#
+##com.oracle.truffle.r.test.S4.TestR5.testFieldAccess#Ignored.OutputFormatting#
 #print(suppressMessages({clazz <- setRefClass('Foo20R5', methods = list(foo = function() NULL)); clazz$methods('foo')}))
 function() NULL
 attr(,"mayCall")
@@ -745,6 +745,10 @@ Error in (function (cl, name, valueClass)  :
 ##com.oracle.truffle.r.test.S4.TestS4.testSlotUpdate#
 #{ x<-initialize@valueClass; initialize@valueClass<-"foo"; initialize@valueClass<-x }
 
+##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
+#{ setClass('A4', representation(a = 'numeric')); setMethod('[[', 'A4', function(x, i, j, ...) NULL); obj <- new('A4'); obj[[1]] }
+NULL
+
 ##com.oracle.truffle.r.test.S4.TestS4.testStdGeneric#
 #{ standardGeneric("") }
 Error in standardGeneric("") :
@@ -62345,7 +62349,7 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite
 #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv);
 integer(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#Ignored.ImplementationError#
 #options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)
   [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 07 03 00 00 04 02 00 00 00
  [26] 01 00 04 00 09 00 00 00 09 63 6c 61 73 73 4e 61 6d 65 00 00 02 10 00 00 00
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index 09a616189e..a69b6a84e1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -142,6 +142,7 @@ public class TestS4 extends TestRBase {
         assertEval("{ standardGeneric(\"\") }");
         assertEval(Output.IgnoreErrorContext, "{ standardGeneric(\"foo\", 42) }");
         assertEval(Output.IgnoreErrorContext, "{ x<-42; class(x)<-character(); standardGeneric(\"foo\", x) }");
+        assertEval("{ setClass('A4', representation(a = 'numeric')); setMethod('[[', 'A4', function(x, i, j, ...) NULL); obj <- new('A4'); obj[[1]] }");
     }
 
     @Test
-- 
GitLab


From c47ff64dc4b39a2e33d4713d7d1d9aa00bd1fe62 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 4 Apr 2017 15:59:40 +0200
Subject: [PATCH 226/402] Fix: Function 'as.function.default' did not properly
 handle all objects.

---
 .../com/oracle/truffle/r/nodes/builtin/base/AsFunction.java    | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
index 6480199a1c..d3f2d8b12a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -105,7 +106,7 @@ public abstract class AsFunction extends RBuiltinNode {
                     } else {
                         defaultValue = ReadVariableNode.create(symbol.getName());
                     }
-                } else if (RRuntime.asAbstractVector(arg) instanceof RAbstractVector) {
+                } else if (RRuntime.asAbstractVector(arg) instanceof RAttributable) {
                     defaultValue = ConstantNode.create(arg);
                 } else {
                     throw RInternalError.unimplemented();
-- 
GitLab


From b8122d74112471f9d2b083adb6a9979fffba2dfb Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 5 Apr 2017 13:24:47 +0200
Subject: [PATCH 227/402] Fix: Vector dimension names were assumed to be a
 vector but in the case of one dimension, it was just a scalar string.

---
 .../truffle/r/nodes/access/vector/CachedExtractVectorNode.java  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index 611ad11ba4..3621333404 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -329,7 +329,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
                     } else if (positionsCheckNode.isEmptyPosition(i, positions[i])) {
                         result = RNull.instance;
                     } else {
-                        result = extract(i, (RAbstractStringVector) dataAt, positions[i], positionProfile[i]);
+                        result = extract(i, (RAbstractStringVector) RRuntime.asAbstractVector(dataAt), positions[i], positionProfile[i]);
                     }
                     newDimNames[dimIndex] = result;
                     if (newDimNamesNames != null) {
-- 
GitLab


From e5fc81f6f58e18ea167e8431d7a5f666de55abef Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 5 Apr 2017 13:26:00 +0200
Subject: [PATCH 228/402] Fix: Tried to create an RSymbol from an unknown,
 maybe not interned string.

---
 .../src/com/oracle/truffle/r/nodes/RASTUtils.java              | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
index 2b3bbc78a7..ba1db0bcff 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
@@ -145,8 +145,7 @@ public class RASTUtils {
             return value;
         } else if (element instanceof RSyntaxLookup) {
             String id = ((RSyntaxLookup) element).getIdentifier();
-            assert Utils.isInterned(id);
-            return RDataFactory.createSymbol(id);
+            return RDataFactory.createSymbolInterned(id);
         } else {
             assert element instanceof RSyntaxCall || element instanceof RSyntaxFunction;
             return RDataFactory.createLanguage(((RSyntaxNode) element).asRNode());
-- 
GitLab


From 8b057ad038648fb29c5d186a3a5a60fa6cdeb8e3 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 5 Apr 2017 13:26:27 +0200
Subject: [PATCH 229/402] Fix: Invalid argument matching for primitive "[<-"
 due to signature '("", ...)' containing unnamed first argument.

---
 .../builtin/base/infix/UpdateSubset.java      | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 51f38ff79a..445e8417ca 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
-@RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
+@RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class UpdateSubset extends RBuiltinNode {
 
     @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSET, false);
@@ -69,21 +69,27 @@ public abstract class UpdateSubset extends RBuiltinNode {
         return null;
     }
 
-    @Specialization(guards = "!args.isEmpty()")
-    protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) {
+    @Specialization(guards = "args.getLength() >= 2")
+    protected Object update(VirtualFrame frame, RArgsValuesAndNames args) {
+        // first argument: object to assign to
+        Object x = args.getArgument(0);
+
+        // last argument: value to assign
         Object value = args.getArgument(args.getLength() - 1);
+
+        // arguments between first and last are assumed to be indices
         Object[] pos;
-        if (argsLengthLargerThanOneProfile.profile(args.getLength() > 1)) {
-            pos = Arrays.copyOf(args.getArguments(), args.getLength() - 1);
+        if (argsLengthLargerThanOneProfile.profile(args.getLength() > 2)) {
+            pos = Arrays.copyOfRange(args.getArguments(), 1, args.getLength() - 1);
         } else {
             pos = new Object[]{RMissing.instance};
         }
         return replaceNode.apply(frame, x, pos, value);
     }
 
-    @Specialization(guards = "args.isEmpty()")
+    @Specialization(guards = "args.getLength() < 2")
     @SuppressWarnings("unused")
-    protected Object getNoInd(Object x, RArgsValuesAndNames args) {
+    protected Object getNoInd(RArgsValuesAndNames args) {
         throw error(RError.Message.INVALID_ARG_NUMBER, "SubAssignArgs");
     }
 }
-- 
GitLab


From aca6b0c2775a15c79f49909ef3315e620710870d Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 5 Apr 2017 13:28:10 +0200
Subject: [PATCH 230/402] Modified ArgumentMatcher to be capable of handling
 unnamed arguments of builtin functions.

---
 .../com/oracle/truffle/r/nodes/function/ArgumentMatcher.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index 3268b3bd76..f03c7f17e1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -562,7 +562,7 @@ public class ArgumentMatcher {
                     }
                     if (!matchedSuppliedArgs[suppliedIndex]) {
                         String suppliedName = signature.getName(suppliedIndex);
-                        if (suppliedName == null || suppliedName.isEmpty()) {
+                        if (suppliedName == null || suppliedName.isEmpty() || formalSignature.getName(formalIndex).isEmpty()) {
                             // unnamed parameter, match by position
                             break;
                         }
-- 
GitLab


From 950a40a80ba8d32fdeaecd8097b70852c1176d7d Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 4 Apr 2017 19:23:40 +0200
Subject: [PATCH 231/402] do not validate JNI refs by default, use fast
 IsSameElement

---
 .../fficall/src/jni/rffiutils.c               | 31 ++++++++++---
 .../fficall/src/jni/rffiutils.h               |  2 +-
 com.oracle.truffle.r.native/version.source    |  2 +-
 .../truffle/r/runtime/ffi/jni/JNI_Call.java   | 45 +++++++++++++------
 4 files changed, 59 insertions(+), 21 deletions(-)

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 2e74a0498f..d7a786a49a 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -85,7 +85,7 @@ void setEmbedded() {
 #ifdef TRACE_ENABLED
 // Helper for debugging purposes: prints out (into the trace file) the java
 // class name for given SEXP
-static const char* fastRInspect(JNIEnv *env, SEXP v) {
+static void fastRInspect(JNIEnv *env, SEXP v) {
     // this invokes getClass().getName()
     jclass cls = (*env)->GetObjectClass(env, v);
     jmethodID getClassMethodID = checkGetMethodID(env, cls, "getClass", "()Ljava/lang/Class;", 0);
@@ -104,7 +104,24 @@ static const char* fastRInspect(JNIEnv *env, SEXP v) {
 #endif
 
 static int isValidJNIRef(JNIEnv *env, SEXP ref) {
+#if VALIDATE_REFS
     return (*env)->GetObjectRefType(env, ref) != JNIInvalidRefType;
+#else
+    return TRUE;
+#endif
+}
+
+static jboolean fast_IsSameObject(jobject a, jobject b) {
+    // this takes some assumptions about jni handles, but it is much faster
+    void** pA = (void**) a;
+    void** pB = (void**) b;
+    if (pA == NULL && pB == NULL) {
+        return TRUE;
+    } else if (pA == NULL || pB == NULL) {
+        return FALSE;
+    } else {
+        return *pA == *pB;
+    }
 }
 
 // native down call depth, indexes nativeArrayTableHwmStack
@@ -193,7 +210,7 @@ void invalidateNativeArray(JNIEnv *env, SEXP oldObj) {
     assert(isValidJNIRef(env, oldObj));
     for (int i = 0; i < nativeArrayTableHwm; i++) {
         NativeArrayElem cv = nativeArrayTable[i];
-        if ((*env)->IsSameObject(env, cv.obj, oldObj)) {
+        if (fast_IsSameObject(cv.obj, oldObj)) {
 #if TRACE_NATIVE_ARRAYS
             fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj);
 #endif
@@ -219,7 +236,7 @@ void updateNativeArrays(JNIEnv *env) {
 static void *findNativeArray(JNIEnv *env, SEXP x) {
     if (nativeArrayTableLastIndex < nativeArrayTableHwm) {
         NativeArrayElem cv = nativeArrayTable[nativeArrayTableLastIndex];
-        if (cv.obj != NULL && (cv.obj == x || (*env)->IsSameObject(env, cv.obj, x))) {
+        if (cv.obj != NULL && (cv.obj == x || fast_IsSameObject(cv.obj, x))) {
             void *data = cv.data;
 #if TRACE_NATIVE_ARRAYS
             fprintf(traceFile, "findNativeArray(%p): found %p (cached)\n", x, data);
@@ -233,7 +250,7 @@ static void *findNativeArray(JNIEnv *env, SEXP x) {
         NativeArrayElem cv = nativeArrayTable[i];
         if (cv.obj != NULL) {
             assert(isValidJNIRef(env, cv.obj));
-            if ((*env)->IsSameObject(env, cv.obj, x)) {
+            if (fast_IsSameObject(cv.obj, x)) {
                 nativeArrayTableLastIndex = i;
                 void *data = cv.data;
 #if TRACE_NATIVE_ARRAYS
@@ -409,7 +426,7 @@ static SEXP findCachedGlobalRef(JNIEnv *env, SEXP obj) {
         if (elem.gref == NULL) {
             continue;
         }
-        if ((*env)->IsSameObject(env, elem.gref, obj)) {
+        if (fast_IsSameObject(elem.gref, obj)) {
 #if TRACE_REF_CACHE
             fprintf(traceFile, "gref: cache hit: %d\n", i);
 #endif
@@ -470,7 +487,7 @@ void releaseGlobalRef(JNIEnv *env, SEXP obj) {
         if (elem.gref == NULL || elem.permanent) {
             continue;
         }
-        if ((*env)->IsSameObject(env, elem.gref, obj)) {
+        if (fast_IsSameObject(elem.gref, obj)) {
 #if TRACE_REF_CACHE
             fprintf(traceFile, "gref: release: index %d, gref: %p\n", i, elem.gref);
 #endif
@@ -481,12 +498,14 @@ void releaseGlobalRef(JNIEnv *env, SEXP obj) {
 }
 
 void validateRef(JNIEnv *env, SEXP x, const char *msg) {
+#ifdef VALIDATE_REFS
     jobjectRefType t = (*env)->GetObjectRefType(env, x);
     if (t == JNIInvalidRefType) {
         char buf[1000];
         sprintf(buf, "%s %p", msg,x);
         fatalError(buf);
     }
+#endif
 }
 
 JNIEnv *getEnv() {
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index 2af57ebd82..e2dc370a32 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -31,7 +31,7 @@
 #include <setjmp.h>
 #include <Connections.h>
 
-#define VALIDATE_REFS 1
+#define VALIDATE_REFS 0
 
 JNIEnv *getEnv();
 void setEnv(JNIEnv *env);
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index d6b24041cf..209e3ef4b6 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-19
+20
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
index f729327eba..115c562a7d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
@@ -59,20 +59,39 @@ public class JNI_Call implements CallRFFI {
                 }
                 try {
                     switch (args.length) {
-                    // @formatter:off
-                        case 0: result = call0(address); break;
-                        case 1: result = call1(address, args[0]); break;
-                        case 2: result = call2(address, args[0], args[1]); break;
-                        case 3: result = call3(address, args[0], args[1], args[2]); break;
-                        case 4: result = call4(address, args[0], args[1], args[2], args[3]); break;
-                        case 5: result = call5(address, args[0], args[1], args[2], args[3], args[4]); break;
-                        case 6: result = call6(address, args[0], args[1], args[2], args[3], args[4], args[5]); break;
-                        case 7: result = call7(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break;
-                        case 8: result = call8(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); break;
-                        case 9: result = call9(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); break;
+                        case 0:
+                            result = call0(address);
+                            break;
+                        case 1:
+                            result = call1(address, args[0]);
+                            break;
+                        case 2:
+                            result = call2(address, args[0], args[1]);
+                            break;
+                        case 3:
+                            result = call3(address, args[0], args[1], args[2]);
+                            break;
+                        case 4:
+                            result = call4(address, args[0], args[1], args[2], args[3]);
+                            break;
+                        case 5:
+                            result = call5(address, args[0], args[1], args[2], args[3], args[4]);
+                            break;
+                        case 6:
+                            result = call6(address, args[0], args[1], args[2], args[3], args[4], args[5]);
+                            break;
+                        case 7:
+                            result = call7(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+                            break;
+                        case 8:
+                            result = call8(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+                            break;
+                        case 9:
+                            result = call9(address, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
+                            break;
                         default:
-                            result = call(address, args); break;
-                           // @formatter:on
+                            result = call(address, args);
+                            break;
                     }
                     return result;
                 } finally {
-- 
GitLab


From cffe071047a654ef02ed924f7a9b779ab1f5a5f0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 4 Apr 2017 17:37:08 +0200
Subject: [PATCH 232/402] Fix: Method readLines of StdConnection always
 included a newline character.

---
 .../truffle/r/engine/shell/JLineConsoleHandler.java       | 6 +-----
 .../src/com/oracle/truffle/r/engine/shell/RCommand.java   | 1 +
 .../truffle/r/engine/shell/StringConsoleHandler.java      | 4 ++--
 .../com/oracle/truffle/r/nodes/builtin/base/Readline.java | 3 ---
 .../r/nodes/builtin/helpers/BrowserInteractNode.java      | 3 ++-
 .../oracle/truffle/r/runtime/context/ConsoleHandler.java  | 8 +++-----
 6 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
index e8f01bbdb7..18ced0d667 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
@@ -77,11 +77,7 @@ class JLineConsoleHandler implements ConsoleHandler {
     public String readLine() {
         try {
             console.getTerminal().init();
-            String line = console.readLine();
-            if (line != null) {
-                line += "\n";
-            }
-            return line;
+            return console.readLine();
         } catch (UserInterruptException e) {
             throw e;
         } catch (Exception ex) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index c5dd80595d..53d4271bb1 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -243,6 +243,7 @@ public class RCommand {
                             if (additionalInput == null) {
                                 throw new EOFException();
                             }
+                            sb.append('\n');
                             sb.append(additionalInput);
                             source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
                             // The only continuation in the while loop
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
index 60af1f537c..51af0bead2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@ class StringConsoleHandler implements ConsoleHandler {
                 output.print(prompt);
                 output.println(lines.get(currentLine));
             }
-            return lines.get(currentLine++) + "\n";
+            return lines.get(currentLine++);
         } else {
             return null;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
index 8f51dffb91..bc5411859c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
@@ -51,9 +51,6 @@ public abstract class Readline extends RBuiltinNode {
         String savedPrompt = consoleHandler.getPrompt();
         consoleHandler.setPrompt(prompt.getDataAt(0));
         String input = consoleHandler.readLine();
-        // The readLine method always appends the newline character, as opposed to the readline
-        // builtin. Therefore, the trailing newline must be cut off.
-        input = input.substring(0, input.length() - 1);
         consoleHandler.setPrompt(savedPrompt);
         return input;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
index 78c4fd4820..71c6062bdd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -154,6 +154,7 @@ public abstract class BrowserInteractNode extends RNode {
                             } catch (IncompleteSourceException e) {
                                 // read another line of input
                                 ch.setPrompt("+ ");
+                                sb.append('\n');
                                 sb.append(ch.readLine());
                                 // The only continuation in the while loop
                                 continue;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
index f238108b70..c30feafca9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,10 +67,8 @@ public interface ConsoleHandler {
     void printError(String s);
 
     /**
-     * Read a line of input, newline included in result. Returns null if {@link #isInteractive() ==
-     * false}. The rationale for including the readline is to ensure that the accumulated input,
-     * whether it be from a file or the console accurately reflects the the source. TODO worry about
-     * "\r\n"?
+     * Read a line of input, newline is <b>NOT</b> included in result. Returns null if
+     * {@link #isInteractive() == false}. TODO worry about "\r\n"?
      */
     @TruffleBoundary
     String readLine();
-- 
GitLab


From ec935d559ef9dc3993bd8c08ebec1d9467c3bcfa Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 4 Apr 2017 18:55:05 +0200
Subject: [PATCH 233/402] Fix: Invalid argument matching for cbind2.

---
 .../com/oracle/truffle/r/nodes/builtin/base/Bind.java |  7 ++++++-
 .../com/oracle/truffle/r/test/ExpectedTestOutput.test | 11 +++++++++++
 .../truffle/r/test/builtins/TestBuiltin_cbind.java    |  6 ++++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 4f6dba39bc..acc4e16ed1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -585,7 +585,12 @@ public abstract class Bind extends RBaseNode {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
                     bind = insert(BindNodeGen.create(type));
                 }
-                return bind.execute(frame, deparseLevel, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments()));
+                Object firstArg = RArguments.getArgument(frame, 0);
+                RArgsValuesAndNames promisedArgs = args;
+                if (firstArg instanceof RArgsValuesAndNames) {
+                    promisedArgs = (RArgsValuesAndNames) firstArg;
+                }
+                return bind.execute(frame, deparseLevel, args.getArguments(), promisedArgs, precedence(args.getArguments()));
             }
         }
 
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 322f7f2982..4a91d4b30c 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
@@ -13334,6 +13334,17 @@ structure(integer(0), .Dim = c(0L, 3L), .Dimnames = list(NULL,
 5th break 1201 1466
 6th break 1467 1600
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testcbind6#
+#cbind2(3, 4)
+     [,1] [,2]
+[1,]    3    4
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testcbind6#
+#cbind2(matrix(1:10, 2, 2), matrix(11:20, 2, 2))
+     [,1] [,2] [,3] [,4]
+[1,]    1    3   11   13
+[2,]    2    4   12   14
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ceiling.testCeiling#
 #{ ceiling(c(0.2,-3.4,NA,0/0,1/0)) }
 [1]   1  -3  NA NaN Inf
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
index cccb74db2a..d675297dfd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
@@ -49,6 +49,12 @@ public class TestBuiltin_cbind extends TestBase {
                         "do.call('cbind', argv)");
     }
 
+    @Test
+    public void testcbind6() {
+        assertEval("cbind2(3, 4)");
+        assertEval("cbind2(matrix(1:10, 2, 2), matrix(11:20, 2, 2))");
+    }
+
     @Test
     public void testCbind() {
         assertEval("{ cbind() }");
-- 
GitLab


From 49deb91813fa8a6a3c81fae49959ad71badfd23a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 6 Apr 2017 08:07:50 +0200
Subject: [PATCH 234/402] Fix: Violation of RSyntaxLookup.getIdentifier's
 contract. It must always return an interned string but some implementations
 did not.

---
 .../src/com/oracle/truffle/r/nodes/RASTUtils.java             | 3 ++-
 .../src/com/oracle/truffle/r/nodes/function/PromiseNode.java  | 3 ++-
 .../com/oracle/truffle/r/nodes/function/RCallSpecialNode.java | 3 ++-
 .../src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java | 4 +++-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
index ba1db0bcff..2b3bbc78a7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
@@ -145,7 +145,8 @@ public class RASTUtils {
             return value;
         } else if (element instanceof RSyntaxLookup) {
             String id = ((RSyntaxLookup) element).getIdentifier();
-            return RDataFactory.createSymbolInterned(id);
+            assert Utils.isInterned(id);
+            return RDataFactory.createSymbol(id);
         } else {
             assert element instanceof RSyntaxCall || element instanceof RSyntaxFunction;
             return RDataFactory.createLanguage(((RSyntaxNode) element).asRNode());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
index 7887b85553..fb72a30e67 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -46,6 +46,7 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
@@ -334,7 +335,7 @@ public abstract class PromiseNode extends RNode {
         @TruffleBoundary
         public String getIdentifier() {
             int num = index + 1;
-            return (num < 10 ? ".." : ".") + num;
+            return Utils.intern((num < 10 ? ".." : ".") + num);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
index a23f58a4a2..5ba452ebe4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RVisibility;
+import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -61,7 +62,7 @@ final class PeekLocalVariableNode extends RNode implements RSyntaxLookup {
     @Child private SetVisibilityNode visibility;
 
     PeekLocalVariableNode(String name) {
-        this.read = LocalReadVariableNode.create(name, false);
+        this.read = LocalReadVariableNode.create(Utils.intern(name), false);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java
index eb5d2c888e..b4024e0347 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxLookup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.runtime.nodes;
 
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.Utils;
 
 /**
  * Represents a symbol lookup in the tree of elements that make up an R closure.
@@ -55,6 +56,7 @@ public interface RSyntaxLookup extends RSyntaxElement {
 
             @Override
             public String getIdentifier() {
+                assert Utils.isInterned(identifier);
                 return identifier;
             }
 
-- 
GitLab


From e5e3f7edd635104c050e6063fcad36071dcbe4c4 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 13:51:13 +0200
Subject: [PATCH 235/402] FastR Grid: unit visitor and unit length without
 Truffle DSL

---
 .../r/library/fastrGrid/DoSetViewPort.java    |  4 +-
 .../truffle/r/library/fastrGrid/Unit.java     | 64 +++++++++++++++++++
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index 0d83e296f4..e789b7fb20 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -181,11 +181,11 @@ final class DoSetViewPort extends RBaseNode {
         // gives us how much of width/height is left after we take up the space by physical units
         Object[] layoutData = asList(viewPort.getDataAt(ViewPort.VP_LAYOUT)).getDataWithoutCopying();
         RAbstractContainer layoutWidths = asAbstractContainer(layoutData[ViewPort.LAYOUT_WIDTHS]);
-        assert layoutWidths.getLength() == layoutSize.ncol : "inconsistent layout size with layout widths";
+        assert Unit.getLength(layoutWidths) == layoutSize.ncol : "inconsistent layout size with layout widths";
         double reducedWidth = getReducedDimension(layoutWidths, npcWidths, relativeWidths, size.getWidth(), conversionCtx, true);
 
         RAbstractContainer layoutHeights = asAbstractContainer(layoutData[ViewPort.LAYOUT_HEIGHTS]);
-        assert layoutHeights.getLength() == layoutSize.nrow : "inconsistent layout size with layout height";
+        assert Unit.getLength(layoutHeights) == layoutSize.nrow : "inconsistent layout size with layout height";
         double reducedHeight = getReducedDimension(layoutHeights, npcHeights, relativeHeights, size.getHeight(), conversionCtx, false);
 
         // npcHeight (and npcWidth) has some 'holes' in them, at indexes with
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 295d97a42e..6146701001 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -48,6 +48,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
@@ -322,6 +323,20 @@ public final class Unit {
         throw RInternalError.shouldNotReachHere("unexpected arithmetic unit type");
     }
 
+    public static boolean isSimpleUnit(RAbstractContainer unit) {
+        RStringVector classAttr = unit.getClassAttr();
+        if (classAttr == null || classAttr.getLength() == 0) {
+            return true;
+        }
+        for (int i = 0; i < classAttr.getLength(); i++) {
+            String x = classAttr.getDataAt(i);
+            if (Unit.UNIT_ARITHMETIC_CLASS.equals(x) || Unit.UNIT_LIST_CLASS.equals(x)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private static final class ArithmeticUnit {
         public final String op;
         public final RAbstractContainer arg1;
@@ -359,6 +374,55 @@ public final class Unit {
         }
     }
 
+    private abstract static class UnitVisitor<T> {
+        public T visit(RAbstractContainer unit) {
+            RStringVector clazz = unit.getClassAttr();
+            if (clazz == null || clazz.getLength() == 0) {
+                return visitSimpleUnit((RAbstractVector) unit);
+            }
+            for (int i = 0; i < clazz.getLength(); i++) {
+                String className = clazz.getDataAt(i);
+                if (UNIT_ARITHMETIC_CLASS.equals(className)) {
+                    return visitArithmeticUnit(ArithmeticUnit.asArithmeticUnit(asList(unit)));
+                }
+                if (UNIT_LIST_CLASS.equals(className)) {
+                    return visitListUnit(asList(unit));
+                }
+            }
+            return visitSimpleUnit((RAbstractVector) unit);
+        }
+
+        protected abstract T visitListUnit(RList unit);
+
+        protected abstract T visitArithmeticUnit(ArithmeticUnit unit);
+
+        protected abstract T visitSimpleUnit(RAbstractVector unit);
+    }
+
+    private static final class UnitLengthVisitor extends UnitVisitor<Integer> {
+        private static final UnitLengthVisitor INSTANCE = new UnitLengthVisitor();
+
+        @Override
+        protected Integer visitListUnit(RList unit) {
+            return unit.getLength();
+        }
+
+        @Override
+        protected Integer visitArithmeticUnit(ArithmeticUnit unit) {
+            // length of aggregate functions, max, min, etc. is 1
+            return unit.isBinary() ? Math.max(visit(unit.arg1), visit(unit.arg2)) : 1;
+        }
+
+        @Override
+        protected Integer visitSimpleUnit(RAbstractVector unit) {
+            return unit.getLength();
+        }
+    }
+
+    public static int getLength(RAbstractContainer unit) {
+        return UnitLengthVisitor.INSTANCE.visit(unit);
+    }
+
     abstract static class UnitNodeBase extends RBaseNode {
         @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode(UNIT_ARITHMETIC_CLASS);
         @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode(UNIT_LIST_CLASS);
-- 
GitLab


From 8b8fc3b81db8de88092fda7fc70439dc103c8444 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 13:53:43 +0200
Subject: [PATCH 236/402] FastR Grid: helper to run internal R code from
 outside of fast path

---
 .../r/library/fastrGrid/GridContext.java       | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 4f14e7b14e..f00b510ec4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -30,14 +30,21 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseExcep
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
+import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalCode;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
  * Encapsulated the access to the global grid state.
  */
 public final class GridContext {
     private static final GridContext INSTANCE = new GridContext();
+
+    private RInternalCode internalCode;
     private final GridState gridState = new GridState();
     /**
      * This list should correspond to the names inside {@code .Devices} variable in R.
@@ -100,6 +107,17 @@ public final class GridContext {
         }
     }
 
+    /**
+     * Runs arbitrary function from 'fastrGrid.R' file and returns its result.
+     */
+    public Object evalInternalRFunction(String functionName, Object... args) {
+        if (internalCode == null) {
+            internalCode = RInternalCode.lookup(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(LInitGrid.class, "fastrGrid.R"));
+        }
+        RFunction redrawAll = internalCode.lookupFunction(functionName);
+        return RContext.getEngine().evalFunction(redrawAll, REnvironment.baseEnv().getFrame(), RCaller.topLevel, null, args);
+    }
+
     private static final class DeviceAndState {
         final GridDevice device;
         final GridDeviceState state;
-- 
GitLab


From 433e338a31c88d8a0f6861b8811bada164b84489 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 13:57:07 +0200
Subject: [PATCH 237/402] FastR Grid: fix unit conversion for grob units

---
 .../oracle/truffle/r/library/fastrGrid/Unit.java   | 14 ++++++++++----
 .../oracle/truffle/r/library/fastrGrid/fastrGrid.R |  4 ++--
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 6146701001..3eeed3ad38 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -676,6 +676,7 @@ public final class Unit {
         @Child private RGridCodeCall getUnitXY = new RGridCodeCall("grobConversionGetUnitXY");
         @Child private RGridCodeCall postDrawCode = new RGridCodeCall("grobConversionPostDraw");
         @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+        @Child private UnitToInchesNode unitToInches = createToInchesNode();
 
         @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
         @Child private UnitToInchesNode unitToInchesNode;
@@ -703,7 +704,7 @@ public final class Unit {
             ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
 
             // getUnitXY returns a list with either one or two items
-            RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId}, ArgumentsSignature.empty(2)));
+            RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId, value}, ArgumentsSignature.empty(3)));
             double result;
             switch (unitId) {
                 case GROBX:
@@ -715,11 +716,15 @@ public final class Unit {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
                         result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else {
-                        throw RInternalError.unimplemented("GrobUnitToInches from unit.c: 610");
+                        double[][] inversed = TransformMatrix.inversion(vpTransform.transform);
+                        Point loc = Point.fromUnits(unitToInches, (RAbstractVector) unitxy.getDataAt(0), (RAbstractVector) unitxy.getDataAt(1), 0, conversionCtx);
+                        Point transLoc = TransformMatrix.transLocation(loc, vpTransform.transform);
+                        Point p = TransformMatrix.transLocation(transLoc, inversed);
+                        result = unitId == GROBX ? p.x : p.y;
                     }
                     break;
                 default:
-                    // should still be GROB_SOMETHING unit
+                    // should still be GROB_SOMETHING unit: width, height, ascent, descent
                     if (isRelativeUnit.execute(unitxy.getDataAt(0), 0)) {
                         // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
                         // GROBHEIGHT, bug?
@@ -736,13 +741,14 @@ public final class Unit {
                             result = unitToInchesNode.convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                         }
                     }
+                    result *= value;
                     break;
             }
 
             postDrawCode.call(updatedGrob);
             ctx.getGridState().setGpar(savedGPar);
             ctx.getGridState().setCurrentGrob(savedGrob);
-            return value * result;
+            return result;
         }
 
         private void initUnitToInchesNode() {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index e41d42f3be..4614a924ef 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -181,9 +181,9 @@ grobConversionPreDraw <- function(grobIn) {
     grid:::preDraw(grob)
 }
 
-grobConversionGetUnitXY <- function(grob, unitId) {
+grobConversionGetUnitXY <- function(grob, unitId, theta) {
     if (unitId == L_GROBX || unitId == L_GROBY) {
-        return(list(grid:::xDetails(grob), grid:::yDetails(grob)))
+        return(list(grid:::xDetails(grob, theta), grid:::yDetails(grob, theta)))
     } else if (unitId == L_GROBWIDTH) {
         return(list(grid:::width(grob)))
     } else if (unitId == L_GROBHEIGHT) {
-- 
GitLab


From 109b64fe292b54ccbeeb47da68f83abd22717796 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 13:59:31 +0200
Subject: [PATCH 238/402] FastR Grid: turn-off recording when running grid code
 internally

---
 .../truffle/r/library/fastrGrid/GridState.java       | 12 ++++++++++++
 .../com/oracle/truffle/r/library/fastrGrid/Unit.java | 10 ++++++++++
 2 files changed, 22 insertions(+)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 8da78932bd..63585c1837 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -11,6 +11,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import java.util.function.Supplier;
+
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -29,6 +31,16 @@ public final class GridState {
     GridState() {
     }
 
+    <T> T runWithoutRecording(Supplier<T> code) {
+        boolean recording = isDisplayListOn();
+        setIsDisplayListOn(false);
+        try {
+            return code.get();
+        } finally {
+            setIsDisplayListOn(recording);
+        }
+    }
+
     void setDeviceState(GridDeviceState state) {
         devState = state;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 3eeed3ad38..281eeabb89 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -444,6 +444,11 @@ public final class Unit {
         @Child private RGridCodeCall isPureNullCall = new RGridCodeCall("isPureNullUnit");
 
         public boolean execute(Object unit, int index) {
+            GridState gridState = GridContext.getContext().getGridState();
+            return gridState.runWithoutRecording(() -> executeImpl(unit, index));
+        }
+
+        private boolean executeImpl(Object unit, int index) {
             // Note: converting 0-based java index to 1-based R index
             Object result = isPureNullCall.execute(new RArgsValuesAndNames(new Object[]{unit, index + 1}, ArgumentsSignature.empty(2)));
             byte resultByte;
@@ -684,6 +689,11 @@ public final class Unit {
         // transcribed from unit.c function evaluateGrobUnit
 
         public double execute(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
+            GridState gridState = GridContext.getContext().getGridState();
+            return gridState.runWithoutRecording(() -> executeImpl(value, unitId, grob, conversionCtx));
+        }
+
+        private double executeImpl(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
             GridContext ctx = GridContext.getContext();
             RList currentVP = ctx.getGridState().getViewPort();
             getViewPortTransform.execute(currentVP, conversionCtx.device);
-- 
GitLab


From e5f18727de61fcd8764bff77d6bc5082b41e9e24 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 14:01:17 +0200
Subject: [PATCH 239/402] FastR Grid: fix: LConvert accepts arithmetic units
 too

---
 .../oracle/truffle/r/library/fastrGrid/LConvert.java  | 11 +++++++++--
 .../truffle/r/library/fastrGrid/LValidUnit.java       |  2 +-
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index 134def4c4e..ce0d219dce 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -15,6 +15,7 @@ import static com.oracle.truffle.r.library.fastrGrid.Unit.NATIVE;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.NPC;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.isArithmeticUnit;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.isListUnit;
+import static com.oracle.truffle.r.library.fastrGrid.Unit.isSimpleUnit;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 
@@ -64,7 +65,10 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         int length = unitLength.execute(units);
         double[] result = new double[length];
 
-        RAbstractIntVector unitIds = GridUtils.asIntVector(units.getAttr(Unit.VALID_UNIT_ATTR));
+        RAbstractIntVector unitIds = null;
+        if (isSimpleUnit(units)) {
+            unitIds = GridUtils.asIntVector(units.getAttr(Unit.VALID_UNIT_ATTR));
+        }
         boolean fromUnitIsSimple = !isArithmeticUnit(units) && !isListUnit(units);
 
         for (int i = 0; i < length; i++) {
@@ -75,7 +79,10 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
             double vpToSize = axisTo.isHorizontal() ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
             double vpFromSize = axisFrom.isHorizontal() ? vpTransform.size.getWidth() : vpTransform.size.getHeight();
             int unitTo = unitToVec.getDataAt(i % unitToVec.getLength());
-            int fromUnitId = unitIds.getDataAt(i % unitIds.getLength());
+            int fromUnitId = -1;    // invalid, and definitely not relative unit
+            if (unitIds != null) {
+                fromUnitId = unitIds.getDataAt(i % unitIds.getLength());
+            }
 
             // actual conversion:
             // if the units are both relative, we are converting compatible axes and the vpSize for
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
index e7d405b43f..a4080e1ae7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
@@ -59,7 +59,7 @@ public abstract class LValidUnit extends RExternalBuiltinNode.Arg1 {
     private int convertSingleSlowPath(String name) {
         Integer result = NamesHolder.NAMES.get(name);
         if (result == null) {
-            error(Message.GENERIC, "invalid unit");
+            throw error(Message.GENERIC, "invalid unit");
         }
         return result;
     }
-- 
GitLab


From b367942a1e8449e0cd6045afaedd0bab050be958 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 14:03:01 +0200
Subject: [PATCH 240/402] FastR Grid: implement 'bounds' versions of rectangle,
 points, and circle

---
 .../r/library/fastrGrid/EdgeDetection.java    | 60 ++++++++++++-
 .../fastrGrid/FastRGridExternalLookup.java    |  8 ++
 .../r/library/fastrGrid/GridUtils.java        |  5 ++
 .../truffle/r/library/fastrGrid/LCircle.java  |  4 +
 .../r/library/fastrGrid/LCircleBounds.java    | 85 +++++++++++++++++++
 .../r/library/fastrGrid/LLocnBounds.java      | 83 ++++++++++++++++++
 .../truffle/r/library/fastrGrid/LRect.java    |  6 +-
 .../r/library/fastrGrid/LRectBounds.java      | 81 ++++++++++++++++++
 .../truffle/r/library/fastrGrid/Size.java     |  4 +
 .../r/library/fastrGrid/TransformMatrix.java  | 25 ++++++
 .../truffle/r/library/fastrGrid/fastrGrid.R   |  9 ++
 mx.fastr/copyrights/overrides                 |  3 +
 12 files changed, 369 insertions(+), 4 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
index b9d4070415..b78840d401 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java
@@ -21,6 +21,9 @@ import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 /**
  * Contains static method related to edge detection for bounds calculations.
@@ -106,9 +109,9 @@ final class EdgeDetection {
                 }
             } else { /* Intersect with top/bottom */
                 if (sinTheta > 0) { /* Top */
-                    return new Point(ymax, xm + dy / tanTheta);
+                    return new Point(xm + dy / tanTheta, ymax);
                 } else { /* Bottom */
-                    return new Point(ymin, xm - dy / tanTheta);
+                    return new Point(xm - dy / tanTheta, ymin);
                 }
             }
         }
@@ -200,6 +203,25 @@ final class EdgeDetection {
         return new Point(xm + ua * (x2 - xm), ym + ua * (y2 - ym));
     }
 
+    public static Point hullEdge(GridContext ctx, double[] xx, double[] yy, double theta) {
+        RDoubleVector xVec = RDataFactory.createDoubleVector(xx, RDataFactory.COMPLETE_VECTOR);
+        RDoubleVector yVec = RDataFactory.createDoubleVector(yy, RDataFactory.COMPLETE_VECTOR);
+        Object hullObj = ctx.evalInternalRFunction("chullWrapper", xVec, yVec);
+        RAbstractIntVector hull = GridUtils.asIntVector(hullObj);
+        double[] newXX = new double[hull.getLength()];
+        double[] newYY = new double[hull.getLength()];
+        for (int i = 0; i < hull.getLength(); i++) {
+            newXX[i] = xx[hull.getDataAt(i) - 1];
+            newYY[i] = yy[hull.getDataAt(i) - 1];
+        }
+        return polygonEdge(newXX, newYY, newXX.length, theta);
+    }
+
+    public static Point circleEdge(Point loc, double radius, double theta) {
+        double angle = theta / 180 * Math.PI;
+        return new Point(loc.x + radius * Math.cos(angle), loc.y + radius * Math.sin(angle));
+    }
+
     /**
      * An arbitrarily-oriented rectangle. The vertices are assumed to be in order going
      * anticlockwise around the rectangle.
@@ -220,4 +242,38 @@ final class EdgeDetection {
                             edgesIntersect(this.x[3], this.x[0], this.y[3], this.y[0], r2);
         }
     }
+
+    /**
+     * Represents min and max value for X and Y coordinates and provides convenient methods to
+     * update them.
+     */
+    public static final class Bounds {
+        public double minX = Double.MAX_VALUE;
+        public double maxX = Double.MIN_VALUE;
+        public double minY = Double.MAX_VALUE;
+        public double maxY = Double.MIN_VALUE;
+
+        public void update(Point p) {
+            updateX(p.x);
+            updateY(p.y);
+        }
+
+        public void updateX(double... values) {
+            minX = GridUtils.fmin(minX, values);
+            maxX = GridUtils.fmax(maxX, values);
+        }
+
+        public void updateY(double... values) {
+            minY = GridUtils.fmin(minY, values);
+            maxY = GridUtils.fmax(maxY, values);
+        }
+
+        public double getWidth() {
+            return maxX - minX;
+        }
+
+        public double getHeight() {
+            return maxY - minY;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index 80d6a41600..1292153015 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -120,6 +120,14 @@ public final class FastRGridExternalLookup {
             case "L_points":
                 return LPoints.create();
 
+            // Bounds primitive:
+            case "L_rectBounds":
+                return LRectBounds.create();
+            case "L_locnBounds":
+                return LLocnBounds.create();
+            case "L_circleBounds":
+                return LCircleBounds.create();
+
             // Simple grid state access
             case "L_getGPar":
                 return new GridStateGetNode(GridState::getGpar);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 8784637eb9..ebb3a04377 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -20,6 +20,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -82,6 +83,10 @@ final class GridUtils {
         return result;
     }
 
+    static RDoubleVector createDoubleVector(double... values) {
+        return RDataFactory.createDoubleVector(values, RDataFactory.COMPLETE_VECTOR);
+    }
+
     static boolean hasRClass(RAttributable obj, String clazz) {
         RStringVector classAttr = obj.getClassAttr();
         if (classAttr == null) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 07ff0d4e40..537905c612 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -31,6 +31,10 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(LCircle.class);
+        addCircleCasts(casts);
+    }
+
+    static void addCircleCasts(Casts casts) {
         casts.arg(0).mustBe(abstractVectorValue());
         casts.arg(1).mustBe(abstractVectorValue());
         casts.arg(2).mustBe(abstractVectorValue());
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
new file mode 100644
index 0000000000..3b18079922
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
@@ -0,0 +1,85 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nmath.RMath;
+
+public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+
+    static {
+        Casts casts = new Casts(LCircleBounds.class);
+        LCircle.addCircleCasts(casts);
+        casts.arg(3).mustBe(numericValue()).asDoubleVector().findFirst();
+    }
+
+    public static LCircleBounds create() {
+        return LCircleBoundsNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object doCircle(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector radiusVec, double theta) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
+
+        int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
+        Bounds bounds = new Bounds();
+        int count = 0;
+        Point loc = null;  // we remember the last position and radius
+        double radius = -1;
+        for (int i = 0; i < length; i++) {
+            Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
+            radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
+            loc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            if (loc.isFinite() && Double.isFinite(radius)) {
+                bounds.updateX(loc.x - radius, loc.x + radius);
+                bounds.updateY(loc.y - radius, loc.y + radius);
+                count++;
+            }
+        }
+
+        if (count == 0) {
+            return RNull.instance;
+        }
+        Point result;
+        assert loc != null;
+        if (count == 1) {
+            result = EdgeDetection.circleEdge(loc, radius, theta);
+        } else {
+            result = EdgeDetection.rectEdge(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, theta);
+        }
+
+        double scale = ctx.getGridState().getScale();
+        return GridUtils.createDoubleVector(result.x / scale, result.y / scale, bounds.getWidth() / scale, bounds.getHeight() / scale);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
new file mode 100644
index 0000000000..cd63a6165e
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
@@ -0,0 +1,83 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+
+    static {
+        Casts casts = new Casts(LLocnBounds.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(numericValue()).asDoubleVector().findFirst();
+    }
+
+    public static LLocnBounds create() {
+        return LLocnBoundsNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object doBounds(RAbstractVector xVec, RAbstractVector yVec, double theta) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
+
+        int length = Math.max(Unit.getLength(xVec), Unit.getLength(yVec));
+        if (length == 0) {
+            return RNull.instance;
+        }
+
+        double[] xx = new double[length];
+        double[] yy = new double[length];
+        Bounds bounds = new Bounds();
+        int count = 0;
+        for (int i = 0; i < length; i++) {
+            Point loc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            xx[i] = loc.x;
+            yy[i] = loc.y;
+            if (loc.isFinite()) {
+                bounds.update(loc);
+                count++;
+            }
+        }
+
+        if (count == 0) {
+            return RNull.instance;
+        }
+
+        Point edge = EdgeDetection.hullEdge(ctx, xx, yy, theta);
+        double scale = ctx.getGridState().getScale();
+        return GridUtils.createDoubleVector(edge.x / scale, edge.y / scale, bounds.getWidth() / scale, bounds.getHeight() / scale);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index 8fc3969d15..2edc48e95a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -33,6 +33,10 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
 
     static {
         Casts casts = new Casts(LRect.class);
+        addRectCasts(casts);
+    }
+
+    static void addRectCasts(Casts casts) {
         casts.arg(0).mustBe(abstractVectorValue());
         casts.arg(1).mustBe(abstractVectorValue());
         casts.arg(2).mustBe(abstractVectorValue());
@@ -60,8 +64,6 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
         int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
             Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
-            // Note: once this is factored to drawing/recording: this transformation is necessary
-            // only for drawing
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
new file mode 100644
index 0000000000..133bee5ddc
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
@@ -0,0 +1,81 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.EdgeDetection.rectEdge;
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
+    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
+    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
+    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
+
+    static {
+        Casts casts = new Casts(LRectBounds.class);
+        LRect.addRectCasts(casts);
+        casts.arg(6).mustBe(numericValue()).asDoubleVector().findFirst();
+    }
+
+    public static LRectBounds create() {
+        return LRectBoundsNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object execute(RAbstractVector xVec, RAbstractVector yVec, RAbstractVector wVec, RAbstractVector hVec, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust, double theta) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
+
+        int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
+        Bounds bounds = new Bounds();
+        int nrect = 0;
+        for (int i = 0; i < length; i++) {
+            Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            // just calculate the bounds, no transformation necessary
+            Point loc = origLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
+            if (size.isFinite() && loc.isFinite()) {
+                bounds.updateX(loc.x, loc.x + size.getWidth());
+                bounds.updateY(loc.y, loc.y + size.getHeight());
+                nrect++;
+            }
+        }
+
+        if (nrect == 0) {
+            return RNull.instance;
+        }
+
+        Point edge = rectEdge(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, theta);
+        double scale = ctx.getGridState().getScale();
+        return RDataFactory.createDoubleVector(new double[]{edge.x / scale, edge.y / scale, bounds.getWidth() / scale, bounds.getHeight() / scale}, RDataFactory.COMPLETE_VECTOR);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
index c428af3df6..5ab5ed6373 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
@@ -48,4 +48,8 @@ public final class Size {
     public double getHeight() {
         return height;
     }
+
+    public boolean isFinite() {
+        return Double.isFinite(width) && Double.isFinite(height);
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
index e1051c98a4..28ed32b803 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java
@@ -13,6 +13,11 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import static com.oracle.truffle.r.runtime.nmath.MathConstants.M_PI;
 
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+
+// transcribed from matrix.c
+
 /**
  * Operations on transformation (3x3) matrices.
  */
@@ -115,4 +120,24 @@ final class TransformMatrix {
         }
         return res;
     }
+
+    public static double[][] inversion(double[][] t) {
+        double det = t[0][0] * (t[2][2] * t[1][1] - t[2][1] * t[1][2]) -
+                        t[1][0] * (t[2][2] * t[0][1] - t[2][1] * t[0][2]) +
+                        t[2][0] * (t[1][2] * t[0][1] - t[1][1] * t[0][2]);
+        if (det == 0) {
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "singular transformation matrix");
+        }
+        double[][] invt = new double[3][3];
+        invt[0][0] = 1 / det * (t[2][2] * t[1][1] - t[2][1] * t[1][2]);
+        invt[0][1] = -1 / det * (t[2][2] * t[0][1] - t[2][1] * t[0][2]);
+        invt[0][2] = 1 / det * (t[1][2] * t[0][1] - t[1][1] * t[0][2]);
+        invt[1][0] = -1 / det * (t[2][2] * t[1][0] - t[2][0] * t[1][2]);
+        invt[1][1] = 1 / det * (t[2][2] * t[0][0] - t[2][0] * t[0][2]);
+        invt[1][2] = -1 / det * (t[1][2] * t[0][0] - t[1][0] * t[0][2]);
+        invt[2][0] = 1 / det * (t[2][1] * t[1][0] - t[2][0] * t[1][1]);
+        invt[2][1] = -1 / det * (t[2][1] * t[0][0] - t[2][0] * t[0][1]);
+        invt[2][2] = 1 / det * (t[1][1] * t[0][0] - t[1][0] * t[0][1]);
+        return invt;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index 4614a924ef..70cf79d4d7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -15,6 +15,15 @@
 # logic to R. Some functions implement whole externals, like L_downvppath, some implement coherent
 # parts of the logic and the rest is in Java.
 
+
+# chull from grDevices package is used in EdgeDetection.java
+# Note: chull calls to native function, which we may consider
+# porting or calling directly in the future.
+chullWrapper <- function(x, y) {
+    library(grDevices)
+    grDevices:::chull(x, y)
+}
+
 # Returns list with elements [[1]] - depth, zero if not found, [[2]] - the viewport, NULL if not found
 # We are searching for child "name" in "pvp", if the "path" is not missing,
 # then also pathMatch(path, currPath) must hold.
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 2298d75da7..a72c103a9a 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -744,6 +744,9 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
-- 
GitLab


From fa618c7ac97254f45d85320a9cfe8ee06ff458cb Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 15:09:15 +0200
Subject: [PATCH 241/402] FastR Grid: replace UnitLengthNode with method
 getLength

---
 .../r/library/fastrGrid/GridLinesNode.java    |  8 ++--
 .../r/library/fastrGrid/GridTextNode.java     |  7 ++--
 .../r/library/fastrGrid/GridUtils.java        |  5 +--
 .../truffle/r/library/fastrGrid/LCircle.java  |  3 +-
 .../r/library/fastrGrid/LCircleBounds.java    |  3 +-
 .../truffle/r/library/fastrGrid/LConvert.java |  3 +-
 .../r/library/fastrGrid/LLocnBounds.java      |  3 +-
 .../truffle/r/library/fastrGrid/LPoints.java  |  4 +-
 .../truffle/r/library/fastrGrid/LRect.java    |  3 +-
 .../r/library/fastrGrid/LRectBounds.java      |  3 +-
 .../r/library/fastrGrid/LSegments.java        |  3 +-
 .../truffle/r/library/fastrGrid/Unit.java     | 40 +++----------------
 12 files changed, 25 insertions(+), 60 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index 32c5d9c52b..e70b56cf70 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -20,6 +20,7 @@ import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTrans
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -28,9 +29,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  * lines, but only the later connects the last point with the first point and only the former draws
  * arrows (which is not implemented yet). Note: the third parameter contains sequences
  * {@code 1:max(length(x),length(y))}, where the 'length' dispatches to S3 method giving us unit
- * length like {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode}. This means that
- * we do not have to use the {@link com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode} to
- * get the length.
+ * length like {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)}.
+ * This means that we do not have to use the
+ * {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)} to get the
+ * length.
  */
 public abstract class GridLinesNode extends Node {
     public static GridLinesNode createLines() {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index a088244c1b..3916bba868 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -43,6 +43,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -52,11 +53,11 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * Implements what is in the original grid code implemented by {@code gridText} function.
  *
  * Note: the third parameter contains sequences {@code 1:max(length(x),length(y))}, where the
- * 'length' dispatches to S3 method giving us unit length like {@link Unit.UnitLengthNode}.
+ * 'length' dispatches to S3 method giving us unit length like
+ * {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)}.
  */
 public final class GridTextNode extends RBaseNode {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile();
@@ -100,7 +101,7 @@ public final class GridTextNode extends RBaseNode {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = GridUtils.maxLength(unitLength, x, y);
+        int length = GridUtils.maxLength(x, y);
 
         // following variables will hold the (intermediate) results of bounds checking
         int boundsCount = 0;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index ebb3a04377..b6aac6f088 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -15,7 +15,6 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
 import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2;
 
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -57,10 +56,10 @@ final class GridUtils {
     }
 
     @ExplodeLoop
-    static int maxLength(UnitLengthNode unitLength, RAbstractVector... units) {
+    static int maxLength(RAbstractVector... units) {
         int result = 0;
         for (RAbstractVector unit : units) {
-            result = Math.max(result, unitLength.execute(unit));
+            result = Math.max(result, Unit.getLength(unit));
         }
         return result;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 537905c612..441a703d2a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -26,7 +26,6 @@ import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
@@ -56,7 +55,7 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
+        int length = GridUtils.maxLength(xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
             Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
             double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
index 3b18079922..36e207aa10 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
@@ -27,7 +27,6 @@ import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
@@ -52,7 +51,7 @@ public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = GridUtils.maxLength(unitLength, xVec, yVec, radiusVec);
+        int length = GridUtils.maxLength(xVec, yVec, radiusVec);
         Bounds bounds = new Bounds();
         int count = 0;
         Point loc = null;  // we remember the last position and radius
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index ce0d219dce..e99d0b36f9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
@@ -62,7 +61,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = unitLength.execute(units);
+        int length = Unit.getLength(units);
         double[] result = new double[length];
 
         RAbstractIntVector unitIds = null;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
index cd63a6165e..efcdc7d8db 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
@@ -27,7 +27,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
@@ -53,7 +52,7 @@ public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = Math.max(Unit.getLength(xVec), Unit.getLength(yVec));
+        int length = GridUtils.maxLength(xVec, yVec);
         if (length == 0) {
             return RNull.instance;
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 4931572555..f92e35e494 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -17,7 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitLengthNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
@@ -42,7 +41,6 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
 
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
-    @Child private UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
 
     static {
@@ -72,7 +70,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         // Note: unlike in other drawing primitives, we only consider length of x
-        int length = unitLength.execute(xVec);
+        int length = Unit.getLength(xVec);
         DrawingContext initialDrawingCtx = gpar.getDrawingContext(0);
         PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor());
         for (int i = 0; i < length; i++) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index 2edc48e95a..c99f7401c1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LRect extends RExternalBuiltinNode.Arg6 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
@@ -61,7 +60,7 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
+        int length = GridUtils.maxLength(xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
             Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
             Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
index 133bee5ddc..9eebc15292 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
@@ -55,7 +54,7 @@ public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = GridUtils.maxLength(unitLength, xVec, yVec, wVec, hVec);
+        int length = GridUtils.maxLength(xVec, yVec, wVec, hVec);
         Bounds bounds = new Bounds();
         int nrect = 0;
         for (int i = 0; i < length; i++) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index 4904a3dd0e..e3fa28dd48 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -29,7 +29,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  */
 public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
     @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private Unit.UnitLengthNode unitLength = Unit.createLengthNode();
     @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
     @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
 
@@ -63,7 +62,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
-        int length = GridUtils.maxLength(unitLength, x0, y0, x1, y1);
+        int length = GridUtils.maxLength(x0, y0, x1, y1);
         double[] xx = new double[2];
         double[] yy = new double[2];
         for (int i = 0; i < length; i++) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 281eeabb89..0886305f2d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitLengthNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
 import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
@@ -141,10 +140,6 @@ public final class Unit {
         return result;
     }
 
-    public static UnitLengthNode createLengthNode() {
-        return UnitLengthNode.create();
-    }
-
     public static UnitToInchesNode createToInchesNode() {
         return UnitToInchesNode.create();
     }
@@ -419,6 +414,11 @@ public final class Unit {
         }
     }
 
+    /**
+     * Arithmetic unit objects can represent 'vectorized' expressions, e.g.
+     * {@code 3*c(unit(1,'cm'), unit(2,'mm'))}, in such case the 'length' is not simply the length
+     * of the underlying vector/list.
+     */
     public static int getLength(RAbstractContainer unit) {
         return UnitLengthVisitor.INSTANCE.visit(unit);
     }
@@ -463,33 +463,6 @@ public final class Unit {
         }
     }
 
-    /**
-     * Arithmetic unit objects can represent 'vectorized' expressions, in such case the 'length' is
-     * not simply the length of the underlying vector/list.
-     */
-    public abstract static class UnitLengthNode extends UnitNodeBase {
-        public static UnitLengthNode create() {
-            return UnitLengthNodeGen.create();
-        }
-
-        public abstract int execute(RAbstractContainer vector);
-
-        @Specialization(guards = "!isArithmetic(value)")
-        int doNormal(RAbstractContainer value) {
-            return value.getLength();
-        }
-
-        @Specialization(guards = "isArithmetic(list)")
-        int doArithmetic(RList list,
-                        @Cached("create()") UnitLengthNode recursiveLen) {
-            ArithmeticUnit arithmeticUnit = ArithmeticUnit.asArithmeticUnit(list);
-            if (arithmeticUnit.isBinary()) {
-                return Math.max(recursiveLen.execute(arithmeticUnit.arg1), recursiveLen.execute(arithmeticUnit.arg2));
-            }
-            return 1;   // op is max, min, sum
-        }
-    }
-
     /**
      * Used to discriminate between x axis, y axis, width, and height when doing unit conversions.
      * The order should be the same as used in e.g. {@code L_convert}, which is 0 means x, 1 means
@@ -613,7 +586,6 @@ public final class Unit {
 
         @Specialization(guards = "isArithmetic(list)")
         double doArithmetic(RList list, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
-                        @Cached("create()") UnitLengthNode unitLengthNode,
                         @Cached("create()") UnitToInchesNode recursiveNode) {
             ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit(list);
             BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> recursiveNode.execute(x, index, getNewCtx(ctx, axisOrDim, newNullAMode), axisOrDim);
@@ -631,7 +603,7 @@ public final class Unit {
 
             // must be aggregate operation
             UnitConversionContext newCtx = getNewCtx(ctx, axisOrDim, getNullAMode(expr.op));
-            int len = unitLengthNode.execute(expr.arg1);
+            int len = getLength(expr.arg1);
             double[] values = new double[len];
             for (int i = 0; i < len; i++) {
                 values[i] = recursiveNode.execute(expr.arg1, i, newCtx, axisOrDim);
-- 
GitLab


From bc95d2f4db8044d450d74015b7202ac3b745d79c Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 15:12:28 +0200
Subject: [PATCH 242/402] FastR Grid: pure null unit value re-implemented using
 the UnitVisitor

---
 .../truffle/r/library/fastrGrid/Unit.java     | 81 +++++++++++++------
 1 file changed, 55 insertions(+), 26 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 0886305f2d..cbea8a2a2e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -279,28 +279,29 @@ public final class Unit {
         return unitId >= GROBX && unitId <= GROBDESCENT;
     }
 
-    static double pureNullUnitValue(RAbstractContainer unit, int index) {
-        // TODO: convert to unit visitor
-        if (unit instanceof RAbstractDoubleVector) {
-            RAbstractDoubleVector simpleUnit = (RAbstractDoubleVector) unit;
-            return simpleUnit.getDataAt(index % simpleUnit.getLength());
-        } else if (isListUnit(unit)) {
-            return pureNullUnitValue((RAbstractContainer) ((RList) unit).getDataAt(index % unit.getLength()), 0);
-        } else if (isArithmeticUnit(unit)) {
-            ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit((RList) unit);
+    private static final class PureNullUniValueVisitor extends UnitVisitor<Double, Integer> {
+        private static final PureNullUniValueVisitor INSTANCE = new PureNullUniValueVisitor();
+
+        @Override
+        protected Double visitListUnit(RList unit, Integer index) {
+            return visit(asAbstractContainer(unit.getDataAt(index % unit.getLength())), 0);
+        }
+
+        @Override
+        protected Double visitArithmeticUnit(ArithmeticUnit expr, Integer index) {
             switch (expr.op) {
                 case "+":
-                    return pureNullUnitValue(expr.arg1, index) + pureNullUnitValue(expr.arg2, index);
+                    return visit(expr.arg1, index) + visit(expr.arg2, index);
                 case "-":
-                    return pureNullUnitValue(expr.arg1, index) - pureNullUnitValue(expr.arg2, index);
+                    return visit(expr.arg1, index) - visit(expr.arg2, index);
                 case "*":
-                    return asDouble(expr.arg1) * pureNullUnitValue(expr.arg2, index);
+                    return asDouble(expr.arg1) * visit(expr.arg2, index);
                 case "min":
                 case "max":
                 case "sum":
                     double[] values = new double[expr.arg1.getLength()];
                     for (int i = 0; i < values.length; i++) {
-                        values[i] = pureNullUnitValue(expr.arg1, i);
+                        values[i] = visit(expr.arg1, i);
                     }
                     switch (expr.op) {
                         case "min":
@@ -309,13 +310,19 @@ public final class Unit {
                             return fmax(Double.MIN_VALUE, values);
                         case "sum":
                             return sum(values);
-                        default:
-                            throw RInternalError.shouldNotReachHere("unexpected arithmetic unit operation");
                     }
             }
+            throw RInternalError.shouldNotReachHere("unexpected arithmetic unit operation");
+        }
 
+        @Override
+        protected Double visitSimpleUnit(RAbstractVector unit, Integer index) {
+            return GridUtils.getDoubleAt(unit, index);
         }
-        throw RInternalError.shouldNotReachHere("unexpected arithmetic unit type");
+    }
+
+    static double pureNullUnitValue(RAbstractContainer unit, int index) {
+        return PureNullUniValueVisitor.INSTANCE.visit(unit, index);
     }
 
     public static boolean isSimpleUnit(RAbstractContainer unit) {
@@ -369,32 +376,54 @@ public final class Unit {
         }
     }
 
-    private abstract static class UnitVisitor<T> {
-        public T visit(RAbstractContainer unit) {
+    private abstract static class UnitVisitor<T, R> {
+        public T visit(RAbstractContainer unit, R arg) {
             RStringVector clazz = unit.getClassAttr();
             if (clazz == null || clazz.getLength() == 0) {
-                return visitSimpleUnit((RAbstractVector) unit);
+                return visitSimpleUnit((RAbstractVector) unit, arg);
             }
             for (int i = 0; i < clazz.getLength(); i++) {
                 String className = clazz.getDataAt(i);
                 if (UNIT_ARITHMETIC_CLASS.equals(className)) {
-                    return visitArithmeticUnit(ArithmeticUnit.asArithmeticUnit(asList(unit)));
+                    return visitArithmeticUnit(ArithmeticUnit.asArithmeticUnit(asList(unit)), arg);
                 }
                 if (UNIT_LIST_CLASS.equals(className)) {
-                    return visitListUnit(asList(unit));
+                    return visitListUnit(asList(unit), arg);
                 }
             }
-            return visitSimpleUnit((RAbstractVector) unit);
+            return visitSimpleUnit((RAbstractVector) unit, arg);
         }
 
-        protected abstract T visitListUnit(RList unit);
+        public T visit(RAbstractContainer unit) {
+            return visit(unit, null);
+        }
+
+        protected T visitListUnit(RList unit) {
+            throw RInternalError.shouldNotReachHere();
+        }
+
+        protected T visitArithmeticUnit(ArithmeticUnit unit) {
+            throw RInternalError.shouldNotReachHere();
+        }
 
-        protected abstract T visitArithmeticUnit(ArithmeticUnit unit);
+        protected T visitSimpleUnit(RAbstractVector unit) {
+            throw RInternalError.shouldNotReachHere();
+        }
+
+        protected T visitListUnit(RList unit, R arg) {
+            return visitListUnit(unit);
+        }
 
-        protected abstract T visitSimpleUnit(RAbstractVector unit);
+        protected T visitArithmeticUnit(ArithmeticUnit unit, R arg) {
+            return visitArithmeticUnit(unit);
+        }
+
+        protected T visitSimpleUnit(RAbstractVector unit, R arg) {
+            return visitSimpleUnit(unit);
+        }
     }
 
-    private static final class UnitLengthVisitor extends UnitVisitor<Integer> {
+    private static final class UnitLengthVisitor extends UnitVisitor<Integer, Object> {
         private static final UnitLengthVisitor INSTANCE = new UnitLengthVisitor();
 
         @Override
-- 
GitLab


From d38431d4d174ddecccea1b21d48da29d20bd8b54 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 4 Apr 2017 15:26:51 +0200
Subject: [PATCH 243/402] FastR Grid: replace IsRelativeUnit node with static
 function

---
 .../r/library/fastrGrid/DoSetViewPort.java    |  4 +-
 .../truffle/r/library/fastrGrid/Unit.java     | 40 +++++++------------
 2 files changed, 15 insertions(+), 29 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index e789b7fb20..a70e2cfa41 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -25,7 +25,6 @@ import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
 import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.library.fastrGrid.Unit.IsRelativeUnitNode;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
@@ -50,7 +49,6 @@ final class DoSetViewPort extends RBaseNode {
     @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
     @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
     @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
-    @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
 
     @TruffleBoundary
     public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
@@ -327,7 +325,7 @@ final class DoSetViewPort extends RBaseNode {
                     boolean isWidth) {
         double reducedSize = initialSize;
         for (int i = 0; i < npcItems.length; i++) {
-            boolean currIsRel = isRelativeUnit.execute(layoutItems, i);
+            boolean currIsRel = Unit.isRelativeUnit(GridContext.getContext(), layoutItems, i);
             relativeItems[i] = currIsRel;
             if (!currIsRel) {
                 npcItems[i] = unitsToInches.convertDimension(layoutItems, i, conversionCtx, isWidth);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index cbea8a2a2e..eca26778b9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -50,7 +50,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -469,27 +468,17 @@ public final class Unit {
         }
     }
 
-    public static final class IsRelativeUnitNode extends UnitNodeBase {
-        @Child private RGridCodeCall isPureNullCall = new RGridCodeCall("isPureNullUnit");
-
-        public boolean execute(Object unit, int index) {
-            GridState gridState = GridContext.getContext().getGridState();
-            return gridState.runWithoutRecording(() -> executeImpl(unit, index));
-        }
-
-        private boolean executeImpl(Object unit, int index) {
-            // Note: converting 0-based java index to 1-based R index
-            Object result = isPureNullCall.execute(new RArgsValuesAndNames(new Object[]{unit, index + 1}, ArgumentsSignature.empty(2)));
-            byte resultByte;
-            if (result instanceof Byte) {
-                resultByte = (Byte) result;
-            } else if (result instanceof RAbstractLogicalVector) {
-                resultByte = ((RAbstractLogicalVector) result).getDataAt(0);
-            } else {
-                throw RInternalError.shouldNotReachHere("unexpected result type form isPuteNullUnit");
-            }
-            return RRuntime.fromLogical(resultByte);
-        }
+    /**
+     * Returns {@code true} if the given unit object represents a unit without actual unit type,
+     * i.e. the unit type is {@link #NULL}. Such units are used internally for layouting, and the
+     * interpretation is to take-up all the left space (evenly if there are more such units).
+     */
+    public static boolean isRelativeUnit(GridContext ctx, Object unit, int index) {
+        GridState gridState = ctx.getGridState();
+        return gridState.runWithoutRecording(() -> {
+            Object result = ctx.evalInternalRFunction("isPureNullUnit", unit, index + 1);
+            return RRuntime.fromLogical(RRuntime.asLogicalObject(result));
+        });
     }
 
     /**
@@ -684,7 +673,6 @@ public final class Unit {
         @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
         @Child private UnitToInchesNode unitToInches = createToInchesNode();
 
-        @Child private IsRelativeUnitNode isRelativeUnit = new IsRelativeUnitNode();
         @Child private UnitToInchesNode unitToInchesNode;
 
         // transcribed from unit.c function evaluateGrobUnit
@@ -720,10 +708,10 @@ public final class Unit {
             switch (unitId) {
                 case GROBX:
                 case GROBY:
-                    if (unitId == GROBY && isRelativeUnit.execute(unitxy.getDataAt(1), 0)) {
+                    if (unitId == GROBY && isRelativeUnit(ctx, unitxy.getDataAt(1), 0)) {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
                         result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
-                    } else if (isRelativeUnit.execute(unitxy.getDataAt(0), 0)) {
+                    } else if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
                         result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
                     } else {
@@ -736,7 +724,7 @@ public final class Unit {
                     break;
                 default:
                     // should still be GROB_SOMETHING unit: width, height, ascent, descent
-                    if (isRelativeUnit.execute(unitxy.getDataAt(0), 0)) {
+                    if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
                         // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
                         // GROBHEIGHT, bug?
                         double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-- 
GitLab


From 177965a3572ccd4b3e01503b95db473de5440149 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 5 Apr 2017 09:36:29 +0200
Subject: [PATCH 244/402] FastR Grid: replace unit conversion related nodes
 with static methods

---
 .../{DrawArrowsNode.java => Arrows.java}      |  14 +-
 .../r/library/fastrGrid/DoSetViewPort.java    |  95 +++---
 .../fastrGrid/DoSetViewPortBuiltin.java       |   4 +-
 .../r/library/fastrGrid/GridLinesNode.java    |  11 +-
 .../r/library/fastrGrid/GridTextNode.java     |   7 +-
 .../r/library/fastrGrid/GridUtils.java        |   8 +
 .../truffle/r/library/fastrGrid/LCircle.java  |   9 +-
 .../r/library/fastrGrid/LCircleBounds.java    |   9 +-
 .../truffle/r/library/fastrGrid/LConvert.java |  13 +-
 .../r/library/fastrGrid/LLocnBounds.java      |   7 +-
 .../truffle/r/library/fastrGrid/LNewPage.java |   2 +-
 .../truffle/r/library/fastrGrid/LPoints.java  |  12 +-
 .../truffle/r/library/fastrGrid/LRect.java    |   9 +-
 .../r/library/fastrGrid/LRectBounds.java      |   9 +-
 .../r/library/fastrGrid/LSegments.java        |  13 +-
 .../r/library/fastrGrid/LUnsetViewPort.java   |   4 +-
 .../r/library/fastrGrid/LValidUnit.java       |   2 +-
 .../truffle/r/library/fastrGrid/Point.java    |   7 +-
 .../r/library/fastrGrid/RGridCodeCall.java    |  61 ----
 .../truffle/r/library/fastrGrid/Size.java     |   7 +-
 .../truffle/r/library/fastrGrid/Unit.java     | 298 +++++++-----------
 .../truffle/r/library/fastrGrid/ViewPort.java |   3 +-
 .../library/fastrGrid/ViewPortTransform.java  |  46 +--
 mx.fastr/copyrights/overrides                 |   2 +-
 24 files changed, 226 insertions(+), 426 deletions(-)
 rename com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/{DrawArrowsNode.java => Arrows.java} (83%)
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java
similarity index 83%
rename from com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
rename to com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java
index 656d5fd698..c2cd454c00 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java
@@ -15,15 +15,13 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asAbstractContain
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asDouble;
 import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asInt;
 
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
-final class DrawArrowsNode extends Node {
+final class Arrows {
     // Structure of an arrow description
     private static final int ARROWANGLE = 0;
     private static final int ARROWLENGTH = 1;
@@ -33,8 +31,6 @@ final class DrawArrowsNode extends Node {
     private static final int ARROWTYPE_LINES = 1;
     private static final int ARROWTYPE_POLYGON = 2;
 
-    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
-
     /**
      * Draws arrows at the start and end of given lines.
      *
@@ -49,7 +45,7 @@ final class DrawArrowsNode extends Node {
      * @param end should we draw end arrow if the arrow list says so. Otherwise never draw it.
      * @param conversionCtx needed for unit conversions.
      */
-    public void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) {
+    public static void drawArrows(double[] x, double[] y, int startIndex, int length, int parentIndex, RList arrow, boolean start, boolean end, UnitConversionContext conversionCtx) {
         assert x.length == y.length;
         int endsVal = asInt(arrow.getDataAt(ARROWENDS), parentIndex);
         boolean first = endsVal != 2;
@@ -62,8 +58,8 @@ final class DrawArrowsNode extends Node {
         double angle = asDouble(arrow.getDataAt(ARROWANGLE), parentIndex);
         int arrowType = asInt(arrow.getDataAt(ARROWTYPE), parentIndex);
         RAbstractContainer lengthVec = asAbstractContainer(arrow.getDataAt(ARROWLENGTH));
-        double arrowLength = unitToInches.convertHeight(lengthVec, parentIndex, conversionCtx);
-        arrowLength = Math.max(arrowLength, unitToInches.convertWidth(lengthVec, parentIndex, conversionCtx));
+        double arrowLength = Unit.convertHeight(lengthVec, parentIndex, conversionCtx);
+        arrowLength = Math.max(arrowLength, Unit.convertWidth(lengthVec, parentIndex, conversionCtx));
         // draw the arrows
         GridDevice device = conversionCtx.device;
         DrawingContext drawingCtx = conversionCtx.gpar.getDrawingContext(parentIndex);
@@ -76,7 +72,7 @@ final class DrawArrowsNode extends Node {
         }
     }
 
-    private void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) {
+    private static void drawArrow(DrawingContext drawingCtx, GridDevice device, int arrowType, double x0, double y0, double x1, double y1, double angle, double length) {
         double a = Math.toRadians(angle);
         double xc = x1 - x0;
         double yc = y1 - y0;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
index a70e2cfa41..f2d1290c6e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java
@@ -22,43 +22,44 @@ import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.multiply;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.rotation;
 import static com.oracle.truffle.r.library.fastrGrid.TransformMatrix.translation;
 import static com.oracle.truffle.r.library.fastrGrid.Unit.newUnit;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutPos;
 import com.oracle.truffle.r.library.fastrGrid.ViewPort.LayoutSize;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-final class DoSetViewPort extends RBaseNode {
-    @Child private CastNode castScalarDouble = newCastBuilder().asDoubleVector().findFirst().buildCastNode();
-    @Child private CastNode castDoubleVector = newCastBuilder().asDoubleVector().buildCastNode();
-    @Child private CastNode castChildrenEnv = newCastBuilder().mustBe(REnvironment.class).buildCastNode();
-    @Child private Unit.UnitToInchesNode unitsToInches = Unit.UnitToInchesNode.create();
+final class DoSetViewPort {
 
+    private DoSetViewPort() {
+        // only static members
+    }
+
+    /**
+     * Prepares the given view-port to be set as the current view-port, calculates necessary
+     * information for the new current view-port.
+     *
+     * @see #calcViewportTransform(RList, Object, boolean, GridDevice, GPar)
+     */
     @TruffleBoundary
-    public RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
+    public static RList doSetViewPort(RList pushedViewPort, boolean hasParent, boolean pushing) {
         GridState gridState = GridContext.getContext().getGridState();
         Object[] pushedVPData = pushedViewPort.getDataWithoutCopying();
         if (hasParent && pushing) {
             RList parent = gridState.getViewPort();
             pushedVPData[ViewPort.PVP_PARENT] = parent;
-            REnvironment children = (REnvironment) castChildrenEnv.execute(parent.getDataAt(ViewPort.PVP_CHILDREN));
-            safePutToEnv(pushedViewPort, pushedVPData[ViewPort.VP_NAME], children);
+            REnvironment children = GridUtils.asEnvironment(parent.getDataAt(ViewPort.PVP_CHILDREN));
+            children.safePut(RRuntime.asString(pushedVPData[ViewPort.VP_NAME]), pushedViewPort);
         }
 
         GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
@@ -90,7 +91,7 @@ final class DoSetViewPort extends RBaseNode {
      *            order to convert units for the top level view port
      */
     @TruffleBoundary
-    public void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) {
+    public static void calcViewportTransform(RList viewPort, Object parent, boolean incremental, GridDevice device, GPar deviceTopLevelGpar) {
         double[][] parentTransform;
         ViewPortContext parentContext;
         ViewPortLocation vpl;
@@ -111,8 +112,8 @@ final class DoSetViewPort extends RBaseNode {
             if (!incremental) {
                 calcViewportTransform(parentVPList, parentData[ViewPort.PVP_PARENT], false, device, deviceTopLevelGpar);
             }
-            parentSize = new Size(Unit.cmToInches(castScalar(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(castScalar(parentData[ViewPort.PVP_HEIGHTCM])));
-            parentTransform = fromFlat(castDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
+            parentSize = new Size(Unit.cmToInches(GridUtils.asDouble(parentData[ViewPort.PVP_WIDTHCM])), Unit.cmToInches(GridUtils.asDouble(parentData[ViewPort.PVP_HEIGHTCM])));
+            parentTransform = fromFlat(GridUtils.asDoubleVector(parentData[ViewPort.PVP_TRANS]).materialize().getDataWithoutCopying());
             parentContext = ViewPortContext.fromViewPort(parentVPList);
             parentAngle = asDouble(parentData[ViewPort.PVP_ROTATION]);
 
@@ -126,13 +127,13 @@ final class DoSetViewPort extends RBaseNode {
         }
 
         UnitConversionContext conversionCtx = new UnitConversionContext(parentSize, parentContext, device, drawingContext);
-        double xInches = unitsToInches.convertX(vpl.x, 0, conversionCtx);
-        double yInches = unitsToInches.convertY(vpl.y, 0, conversionCtx);
-        double width = unitsToInches.convertWidth(vpl.width, 0, conversionCtx);
-        double height = unitsToInches.convertHeight(vpl.height, 0, conversionCtx);
+        double xInches = Unit.convertX(vpl.x, 0, conversionCtx);
+        double yInches = Unit.convertY(vpl.y, 0, conversionCtx);
+        double width = Unit.convertWidth(vpl.width, 0, conversionCtx);
+        double height = Unit.convertHeight(vpl.height, 0, conversionCtx);
 
         if (!Double.isFinite(xInches) || !Double.isFinite(yInches) || !Double.isFinite(width) || !Double.isFinite(height)) {
-            throw error(Message.GENERIC, "non-finite location and/or size for viewport");
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "non-finite location and/or size for viewport");
         }
 
         double xadj = GridUtils.justification(width, vpl.hjust);
@@ -166,7 +167,7 @@ final class DoSetViewPort extends RBaseNode {
         viewPortData[ViewPort.PVP_TRANS] = RDataFactory.createDoubleVector(flatten(transform), RDataFactory.COMPLETE_VECTOR, new int[]{3, 3});
     }
 
-    private void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) {
+    private static void calcViewPortLayout(RList viewPort, Size size, ViewPortContext parentVPCtx, GridDevice device, GPar gpar) {
         LayoutSize layoutSize = LayoutSize.fromViewPort(viewPort);
         double[] npcWidths = new double[layoutSize.ncol];
         double[] npcHeights = new double[layoutSize.nrow];
@@ -257,7 +258,7 @@ final class DoSetViewPort extends RBaseNode {
         vpData[ViewPort.PVP_HEIGHTS] = RDataFactory.createDoubleVector(npcHeights, RDataFactory.COMPLETE_VECTOR);
     }
 
-    private void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
+    private static void allocateRelativeDim(LayoutSize layoutSize, RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double reducedDim, int respect, int[] layoutRespectMat,
                     GridDevice device, GPar gpar, ViewPortContext parentVPCtx, boolean isWidth) {
         assert relativeItems.length == npcItems.length;
         UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
@@ -265,7 +266,7 @@ final class DoSetViewPort extends RBaseNode {
         if (reducedDim > 0) {
             for (int i = 0; i < relativeItems.length; i++) {
                 if (relativeItems[i] && !rowColRespected(respect, i, layoutRespectMat, layoutSize, isWidth)) {
-                    totalUnrespectedSize += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
+                    totalUnrespectedSize += Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
                 }
             }
         }
@@ -275,17 +276,17 @@ final class DoSetViewPort extends RBaseNode {
                 npcItems[i] = 0;
                 if (totalUnrespectedSize > 0) {
                     // if there was some with left, then totalUnrespectedSize contains sum of it
-                    npcItems[i] = reducedDim * unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth) / totalUnrespectedSize;
+                    npcItems[i] = reducedDim * Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth) / totalUnrespectedSize;
                 }
             }
         }
     }
 
-    private boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
+    private static boolean rowColRespected(int respected, int rowOrCol, int[] layoutRespectMat, LayoutSize layoutSize, boolean isColumn) {
         return isColumn ? colRespected(respected, rowOrCol, layoutRespectMat, layoutSize) : rowRespected(respected, rowOrCol, layoutRespectMat, layoutSize);
     }
 
-    private boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
+    private static boolean rowRespected(int respected, int row, int[] layoutRespectMat, LayoutSize layoutSize) {
         if (respected == 1) {
             return true;
         }
@@ -297,7 +298,7 @@ final class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private boolean colRespected(int respected, int col, int[] layoutRespectMat, LayoutSize layoutSize) {
+    private static boolean colRespected(int respected, int col, int[] layoutRespectMat, LayoutSize layoutSize) {
         if (respected == 1) {
             return true;
         }
@@ -309,58 +310,42 @@ final class DoSetViewPort extends RBaseNode {
         return false;
     }
 
-    private double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar,
+    private static double sumRelativeDimension(RAbstractContainer layoutItems, boolean[] relativeItems, ViewPortContext parentVPCtx, GridDevice device, GPar gpar,
                     boolean isWidth) {
         UnitConversionContext layoutModeCtx = new UnitConversionContext(new Size(0, 0), parentVPCtx, device, gpar, 1, 0);
         double totalWidth = 0;
         for (int i = 0; i < relativeItems.length; i++) {
             if (relativeItems[i]) {
-                totalWidth += unitsToInches.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
+                totalWidth += Unit.convertDimension(layoutItems, i, layoutModeCtx, isWidth);
             }
         }
         return totalWidth;
     }
 
-    private double getReducedDimension(RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double initialSize, UnitConversionContext conversionCtx,
+    private static double getReducedDimension(RAbstractContainer layoutItems, double[] npcItems, boolean[] relativeItems, double initialSize, UnitConversionContext conversionCtx,
                     boolean isWidth) {
         double reducedSize = initialSize;
         for (int i = 0; i < npcItems.length; i++) {
             boolean currIsRel = Unit.isRelativeUnit(GridContext.getContext(), layoutItems, i);
             relativeItems[i] = currIsRel;
             if (!currIsRel) {
-                npcItems[i] = unitsToInches.convertDimension(layoutItems, i, conversionCtx, isWidth);
+                npcItems[i] = Unit.convertDimension(layoutItems, i, conversionCtx, isWidth);
                 reducedSize -= npcItems[i];
             }
         }
         return reducedSize;
     }
 
-    private RAbstractDoubleVector castDoubleVector(Object obj) {
-        return (RAbstractDoubleVector) castDoubleVector.execute(obj);
-    }
-
-    private double castScalar(Object obj) {
-        return (double) castScalarDouble.execute(obj);
-    }
-
     private static RDoubleVector scalar(double val) {
         return RDataFactory.createDoubleVectorFromScalar(val);
     }
 
-    private static void safePutToEnv(RList pushedViewPort, Object pushedVPDatum, REnvironment children) {
-        try {
-            children.put(RRuntime.asString(pushedVPDatum), pushedViewPort);
-        } catch (PutException e) {
-            throw RInternalError.shouldNotReachHere("Cannot update children environment in a view port list");
-        }
-    }
-
     // Note: unlike the GnuR counterpart of this method, we expect the LayoutPos to have the NULL
     // positions replaced with nrow/ncol already.
-    private ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) {
+    private static ViewPortLocation calcViewportLocationFromLayout(LayoutPos pos, RList parentVP, Size parentSize) {
         // unlike in GnuR, we maintain parent viewport widths/heights in inches like anything else
-        double[] widths = castDoubleVector(parentVP.getDataAt(ViewPort.PVP_WIDTHS)).materialize().getDataWithoutCopying();
-        double[] heights = castDoubleVector(parentVP.getDataAt(ViewPort.PVP_HEIGHTS)).materialize().getDataWithoutCopying();
+        double[] widths = GridUtils.asDoubleVector(parentVP.getDataAt(ViewPort.PVP_WIDTHS)).materialize().getDataWithoutCopying();
+        double[] heights = GridUtils.asDoubleVector(parentVP.getDataAt(ViewPort.PVP_HEIGHTS)).materialize().getDataWithoutCopying();
         double totalWidth = sum(widths, 0, pos.layoutSize.ncol);
         double totalHeight = sum(heights, 0, pos.layoutSize.nrow);
         double width = sum(widths, pos.colMin, pos.colMax - pos.colMin + 1);
@@ -376,7 +361,7 @@ final class DoSetViewPort extends RBaseNode {
         return result;
     }
 
-    private LayoutPos getLayoutPos(RList vp, RList parent) {
+    private static LayoutPos getLayoutPos(RList vp, RList parent) {
         LayoutSize size = LayoutSize.fromViewPort(parent);
         Object rowObj = vp.getDataAt(ViewPort.VP_VALIDLPOSROW);
         int rowMin = 1;
@@ -385,7 +370,7 @@ final class DoSetViewPort extends RBaseNode {
             rowMin = ((RAbstractIntVector) rowObj).getDataAt(0);
             rowMax = ((RAbstractIntVector) rowObj).getDataAt(1);
             if (rowMin < 1 || rowMax > size.nrow) {
-                throw error(Message.GENERIC, "invalid 'layout.pos.row'");
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "invalid 'layout.pos.row'");
             }
         }
         Object colObj = vp.getDataAt(ViewPort.VP_VALIDLPOSCOL);
@@ -395,7 +380,7 @@ final class DoSetViewPort extends RBaseNode {
             colMin = ((RAbstractIntVector) colObj).getDataAt(0);
             colMax = ((RAbstractIntVector) colObj).getDataAt(1);
             if (colMin < 1 || colMax > size.ncol) {
-                throw error(Message.GENERIC, "invalid 'layout.pos.row'");
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, "invalid 'layout.pos.row'");
             }
         }
         // the indexes in LayoutPos are to be interpreted as 0-based
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
index d8b2359414..60ce02957f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
@@ -11,6 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.DoSetViewPort.doSetViewPort;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 
@@ -29,7 +30,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
  */
 @RBuiltin(name = ".fastr.grid.doSetViewPort", parameterNames = {"vp", "hasParent", "pushing"}, kind = RBuiltinKind.INTERNAL, behavior = RBehavior.COMPLEX)
 public abstract class DoSetViewPortBuiltin extends RBuiltinNode {
-    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
 
     static {
         Casts casts = new Casts(DoSetViewPortBuiltin.class);
@@ -40,7 +40,7 @@ public abstract class DoSetViewPortBuiltin extends RBuiltinNode {
 
     @Specialization
     RNull doIt(RList pushedVP, boolean hasParent, boolean pushing) {
-        RList vp = doSetViewPort.doSetViewPort(pushedVP, hasParent, pushing);
+        RList vp = doSetViewPort(pushedVP, hasParent, pushing);
         GridContext.getContext().getGridState().setViewPort(vp);
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
index e70b56cf70..1287407d6e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.asIntVector;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -43,10 +42,6 @@ public abstract class GridLinesNode extends Node {
         return new GridLinesPolygon();
     }
 
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
-
     @TruffleBoundary
     void execute(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) {
         GridContext ctx = GridContext.getContext();
@@ -54,7 +49,7 @@ public abstract class GridLinesNode extends Node {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -79,7 +74,7 @@ public abstract class GridLinesNode extends Node {
             // such series as a polyline
             for (int i = 0; i < unitIndexesLen; i++) {
                 int unitIndex = unitIndexes.getDataAt(i) - 1;   // converting R's 1-based index
-                Point origLoc = Point.fromUnits(unitToInches, x, y, unitIndex, conversionCtx);
+                Point origLoc = Point.fromUnits(x, y, unitIndex, conversionCtx);
                 Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
                 xx[i] = loc.x;
                 yy[i] = loc.y;
@@ -102,7 +97,7 @@ public abstract class GridLinesNode extends Node {
                         if (arrow != null) {
                             // Can draw an arrow at the start if the points include the first point.
                             // Draw an arrow at the end only if this is the last series
-                            drawArrowsNode.drawArrows(xx, yy, start, length, unitIndex, arrow, start == 0, lastIter, conversionCtx);
+                            Arrows.drawArrows(xx, yy, start, length, unitIndex, arrow, start == 0, lastIter, conversionCtx);
                         }
                     }
                 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 3916bba868..76ccd7660b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -35,7 +35,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Rectangle;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
@@ -57,8 +56,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * {@link com.oracle.truffle.r.library.fastrGrid.Unit#getLength(RAbstractContainer)}.
  */
 public final class GridTextNode extends RBaseNode {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     private final ConditionProfile checkOverlapProfile = ConditionProfile.createBinaryProfile();
     private final boolean draw;
@@ -97,7 +94,7 @@ public final class GridTextNode extends RBaseNode {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -117,7 +114,7 @@ public final class GridTextNode extends RBaseNode {
         }
 
         for (int i = 0; i < length; i++) {
-            Point loc = Point.fromUnits(unitToInches, x, y, i, conversionCtx);
+            Point loc = Point.fromUnits(x, y, i, conversionCtx);
             if (draw) {
                 // transformation not necessary for bounds calculation
                 loc = transLocation(loc, vpTransform.transform);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index b6aac6f088..284a984505 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 final class GridUtils {
     private GridUtils() {
@@ -207,6 +208,13 @@ final class GridUtils {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected non abstract container type " + value.getClass().getSimpleName());
     }
 
+    static REnvironment asEnvironment(Object value) {
+        if (value instanceof REnvironment) {
+            return (REnvironment) value;
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Unexpected: value is not environment " + value.getClass().getSimpleName());
+    }
+
     static double sum(double[] values) {
         return sum(values, 0, values.length);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
index 441a703d2a..cacc0eec42 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -25,8 +24,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LCircle.class);
@@ -51,15 +48,15 @@ public abstract class LCircle extends RExternalBuiltinNode.Arg3 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(xVec, yVec, radiusVec);
         for (int i = 0; i < length; i++) {
-            Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
+            Size radiusSizes = Size.fromUnits(radiusVec, radiusVec, i, conversionCtx);
             double radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
-            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             Point loc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             dev.drawCircle(gpar.getDrawingContext(i), loc.x, loc.y, radius);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
index 36e207aa10..bab570f2e8 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java
@@ -17,7 +17,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -26,8 +25,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nmath.RMath;
 
 public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LCircleBounds.class);
@@ -47,7 +44,7 @@ public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -57,9 +54,9 @@ public abstract class LCircleBounds extends RExternalBuiltinNode.Arg4 {
         Point loc = null;  // we remember the last position and radius
         double radius = -1;
         for (int i = 0; i < length; i++) {
-            Size radiusSizes = Size.fromUnits(unitToInches, radiusVec, radiusVec, i, conversionCtx);
+            Size radiusSizes = Size.fromUnits(radiusVec, radiusVec, i, conversionCtx);
             radius = RMath.fmin2(radiusSizes.getWidth(), radiusSizes.getHeight());
-            loc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            loc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(radius)) {
                 bounds.updateX(loc.x - radius, loc.x + radius);
                 bounds.updateY(loc.y - radius, loc.y + radius);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index e99d0b36f9..a66bbdb689 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.AxisOrDimension;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -33,8 +32,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LConvert.class);
@@ -57,7 +54,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -110,15 +107,15 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         double inches;
         if (axisFrom.isHorizontal()) {
             if (axisFrom.isDimension()) {
-                inches = unitToInches.convertWidth(units, index, conversionCtx);
+                inches = Unit.convertWidth(units, index, conversionCtx);
             } else {
-                inches = unitToInches.convertX(units, index, conversionCtx);
+                inches = Unit.convertX(units, index, conversionCtx);
             }
         } else {
             if (axisFrom.isDimension()) {
-                inches = unitToInches.convertHeight(units, index, conversionCtx);
+                inches = Unit.convertHeight(units, index, conversionCtx);
             } else {
-                inches = unitToInches.convertY(units, index, conversionCtx);
+                inches = Unit.convertY(units, index, conversionCtx);
             }
         }
         return inches;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
index efcdc7d8db..97536e3dd0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java
@@ -18,7 +18,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -26,8 +25,6 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LLocnBounds.class);
@@ -48,7 +45,7 @@ public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -62,7 +59,7 @@ public abstract class LLocnBounds extends RExternalBuiltinNode.Arg3 {
         Bounds bounds = new Bounds();
         int count = 0;
         for (int i = 0; i < length; i++) {
-            Point loc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Point loc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             xx[i] = loc.x;
             yy[i] = loc.y;
             if (loc.isFinite()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 2f491ea4cc..95c5e9bcfd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -33,7 +33,7 @@ final class LNewPage extends RExternalBuiltinNode {
             return RNull.instance;
         }
         // There are some exceptions to the rule that any external call from grid R code is
-        // preceeded by L_gridDirty call, L_newpage is one of them.
+        // preceded by L_gridDirty call, L_newpage is one of them.
         CompilerDirectives.transferToInterpreter();
         return gridDirty.call(frame, RArgsValuesAndNames.EMPTY);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index f92e35e494..02d7c1b47f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -17,8 +17,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
@@ -39,10 +37,6 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
     private static final double TRC1 = 1.34677368708859836060; /* TRC0 * sqrt(3) / 2 */
     private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
 
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-
-    @Child private UnitToInchesNode unitToInches = Unit.createToInchesNode();
-
     static {
         Casts casts = new Casts(LPoints.class);
         casts.arg(0).mustBe(abstractVectorValue());
@@ -65,7 +59,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         RList gparList = ctx.getGridState().getGpar();
         GPar gpar = GPar.create(gparList);
         double cex = GPar.getCex(gparList);
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -74,8 +68,8 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         DrawingContext initialDrawingCtx = gpar.getDrawingContext(0);
         PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor());
         for (int i = 0; i < length; i++) {
-            Point loc = TransformMatrix.transLocation(Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx), vpTransform.transform);
-            double size = unitToInches.convertWidth(sizeVec, i, conversionCtx);
+            Point loc = TransformMatrix.transLocation(Point.fromUnits(xVec, yVec, i, conversionCtx), vpTransform.transform);
+            double size = Unit.convertWidth(sizeVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(size)) {
                 pointDrawingCtx = pointDrawingCtx.update(gpar.getDrawingContext(i));
                 pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
index c99f7401c1..1d2ce1bdb6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java
@@ -18,7 +18,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -27,8 +26,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LRect extends RExternalBuiltinNode.Arg6 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LRect.class);
@@ -56,14 +53,14 @@ public abstract class LRect extends RExternalBuiltinNode.Arg6 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
         int length = GridUtils.maxLength(xVec, yVec, wVec, hVec);
         for (int i = 0; i < length; i++) {
-            Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
-            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Size size = Size.fromUnits(wVec, hVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
             Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
             dev.drawRect(gpar.getDrawingContext(i), loc.x, loc.y, size.getWidth(), size.getHeight(), Math.toRadians(vpTransform.rotationAngle));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
index 9eebc15292..2aff9d698f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java
@@ -19,7 +19,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.EdgeDetection.Bounds;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -29,8 +28,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
 
     static {
         Casts casts = new Casts(LRectBounds.class);
@@ -50,7 +47,7 @@ public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -58,8 +55,8 @@ public abstract class LRectBounds extends RExternalBuiltinNode.Arg7 {
         Bounds bounds = new Bounds();
         int nrect = 0;
         for (int i = 0; i < length; i++) {
-            Size size = Size.fromUnits(unitToInches, wVec, hVec, i, conversionCtx);
-            Point origLoc = Point.fromUnits(unitToInches, xVec, yVec, i, conversionCtx);
+            Size size = Size.fromUnits(wVec, hVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
             // just calculate the bounds, no transformation necessary
             Point loc = origLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
             if (size.isFinite() && loc.isFinite()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
index e3fa28dd48..2c384f0488 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java
@@ -16,7 +16,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVect
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -28,10 +27,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  * which gets a vector of points and connects them all.
  */
 public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
-    @Child private Unit.UnitToInchesNode unitToInches = Unit.createToInchesNode();
-    @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-    @Child private DrawArrowsNode drawArrowsNode = new DrawArrowsNode();
-
     static {
         Casts casts = new Casts(LSegments.class);
         casts.arg(0).mustBe(abstractVectorValue());
@@ -58,7 +53,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
 
         RList currentVP = ctx.getGridState().getViewPort();
         GPar gpar = GPar.create(ctx.getGridState().getGpar());
-        ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, dev);
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
         ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
         UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
 
@@ -66,8 +61,8 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
         double[] xx = new double[2];
         double[] yy = new double[2];
         for (int i = 0; i < length; i++) {
-            Point loc1 = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x0, y0, i, conversionCtx), vpTransform.transform);
-            Point loc2 = TransformMatrix.transLocation(Point.fromUnits(unitToInches, x1, y1, i, conversionCtx), vpTransform.transform);
+            Point loc1 = TransformMatrix.transLocation(Point.fromUnits(x0, y0, i, conversionCtx), vpTransform.transform);
+            Point loc2 = TransformMatrix.transLocation(Point.fromUnits(x1, y1, i, conversionCtx), vpTransform.transform);
             if (!loc1.isFinite() || !loc2.isFinite()) {
                 continue;
             }
@@ -77,7 +72,7 @@ public abstract class LSegments extends RExternalBuiltinNode.Arg5 {
             yy[1] = loc2.y;
             dev.drawPolyLines(gpar.getDrawingContext(i), xx, yy, 0, 2);
             if (arrow != null) {
-                drawArrowsNode.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
+                Arrows.drawArrows(xx, yy, 0, 2, i, arrow, true, true, conversionCtx);
             }
         }
         return RNull.instance;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
index f23564cd26..f8fb9b0e6d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -28,8 +28,6 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 
 public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
-    @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
-
     static {
         Casts casts = new Casts(LUnsetViewPort.class);
         casts.arg(0).mustBe(numericValue()).asIntegerVector().findFirst();
@@ -67,7 +65,7 @@ public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
         if (ViewPort.updateDeviceSizeInVP(newVp, device)) {
             // Note: like in other places calling this, why incremental == true, given that the
             // device has changed? Don't we want to recalculate the whole tree?
-            doSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
+            DoSetViewPort.calcViewportTransform(newVp, newVp.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
         }
 
         gridState.setGpar(asList(newVp.getDataAt(ViewPort.PVP_GPAR)));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
index a4080e1ae7..e2b1505d66 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java
@@ -47,7 +47,7 @@ public abstract class LValidUnit extends RExternalBuiltinNode.Arg1 {
         return RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
     }
 
-    protected int convertSingle(String name) {
+    private int convertSingle(String name) {
         if (name.equals("npc")) {
             // seems to be by far the most common unit
             return Unit.NPC;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
index ba2c513520..bd5311e916 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Point.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class Point {
@@ -35,10 +34,8 @@ public final class Point {
         this.y = y;
     }
 
-    public static Point fromUnits(UnitToInchesNode unitToInches, RAbstractVector x, RAbstractVector y, int index, UnitConversionContext ctx) {
-        double newX = unitToInches.convertX(x, index, ctx);
-        double newY = unitToInches.convertY(y, index, ctx);
-        return new Point(newX, newY);
+    public static Point fromUnits(RAbstractVector x, RAbstractVector y, int index, UnitConversionContext ctx) {
+        return new Point(Unit.convertX(x, index, ctx), Unit.convertY(y, index, ctx));
     }
 
     public Point justify(Size size, double hjust, double vjust) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
deleted file mode 100644
index 6ff0c0c5f2..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/RGridCodeCall.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.library.fastrGrid;
-
-import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.FrameDescriptor;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.RInternalCode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
-
-/**
- * Allows to call arbitrary R function from {@code fastrGrid.R} source.
- */
-final class RGridCodeCall extends Node {
-    private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("<fastrGrid.R tmp frame>");
-    @Child private RInternalCodeBuiltinNode child;
-
-    RGridCodeCall(String functionName) {
-        child = new RInternalCodeBuiltinNode(RContext.getInstance(), "grid", RInternalCode.loadSourceRelativeTo(GPar.class, "fastrGrid.R"), functionName);
-    }
-
-    static {
-        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<fastrGrid.R tmp frame>", emptyFrameDescriptor);
-    }
-
-    public Object call(Object arg1) {
-        return execute(new RArgsValuesAndNames(new Object[]{arg1}, ArgumentsSignature.empty(1)));
-    }
-
-    public Object execute(RArgsValuesAndNames args) {
-        Object[] dummyFrameArgs = RArguments.createUnitialized();
-        VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor);
-        return child.call(dummyFrame, args);
-    }
-}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
index 5ab5ed6373..1dd7e55ce6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Size.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
-import com.oracle.truffle.r.library.fastrGrid.Unit.UnitToInchesNode;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class Size {
@@ -35,9 +34,9 @@ public final class Size {
         this.height = height;
     }
 
-    public static Size fromUnits(UnitToInchesNode unitToInches, RAbstractVector wVec, RAbstractVector hVec, int index, UnitConversionContext conversionCtx) {
-        double w = unitToInches.convertWidth(wVec, index, conversionCtx);
-        double h = unitToInches.convertHeight(hVec, index, conversionCtx);
+    public static Size fromUnits(RAbstractVector wVec, RAbstractVector hVec, int index, UnitConversionContext conversionCtx) {
+        double w = Unit.convertWidth(wVec, index, conversionCtx);
+        double h = Unit.convertHeight(hVec, index, conversionCtx);
         return new Size(w, h);
     }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index eca26778b9..1d6405efaf 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -27,21 +27,12 @@ import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_
 
 import java.util.function.BiFunction;
 
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.library.fastrGrid.UnitFactory.UnitToInchesNodeGen;
-import com.oracle.truffle.r.library.fastrGrid.ViewPortTransform.GetViewPortTransformNode;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -51,7 +42,6 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Note: internally in FastR Grid everything is in inches. However, some lists that are exposed to
@@ -139,10 +129,6 @@ public final class Unit {
         return result;
     }
 
-    public static UnitToInchesNode createToInchesNode() {
-        return UnitToInchesNode.create();
-    }
-
     static double convertFromInches(double value, int unitId, double vpSize, double scalemin, double scalemax, boolean isDimension, DrawingContext drawingCtx) {
         switch (unitId) {
             case NATIVE:
@@ -228,16 +214,16 @@ public final class Unit {
             case MYSTRINGWIDTH:
                 str = RRuntime.asString(data.getDataAt(0));
                 lines = str.split("\n");
-                for (int i = 0; i < lines.length; i++) {
-                    result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), lines[i]));
+                for (String line1 : lines) {
+                    result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), line1));
                 }
                 return value * result;
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
                 str = RRuntime.asString(data.getDataAt(0));
                 lines = str.split("\n");
-                for (int i = 0; i < lines.length; i++) {
-                    result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), lines[i]);
+                for (String line : lines) {
+                    result += ctx.device.getStringHeight(ctx.gpar.getDrawingContext(index), line);
                 }
                 return value * result;
             case NULL:
@@ -451,23 +437,6 @@ public final class Unit {
         return UnitLengthVisitor.INSTANCE.visit(unit);
     }
 
-    abstract static class UnitNodeBase extends RBaseNode {
-        @Child private InheritsCheckNode inheritsArithmeticCheckNode = new InheritsCheckNode(UNIT_ARITHMETIC_CLASS);
-        @Child private InheritsCheckNode inheritsUnitListCheckNode = new InheritsCheckNode(UNIT_LIST_CLASS);
-
-        boolean isSimple(Object obj) {
-            return !inheritsArithmeticCheckNode.execute(obj) && !inheritsUnitListCheckNode.execute(obj);
-        }
-
-        boolean isArithmetic(Object obj) {
-            return inheritsArithmeticCheckNode.execute(obj);
-        }
-
-        boolean isUnitList(Object obj) {
-            return inheritsUnitListCheckNode.execute(obj);
-        }
-    }
-
     /**
      * Returns {@code true} if the given unit object represents a unit without actual unit type,
      * i.e. the unit type is {@link #NULL}. Such units are used internally for layouting, and the
@@ -548,65 +517,41 @@ public final class Unit {
         }
     }
 
-    /**
-     * Normalizes grid unit object to a double value in inches. For convenience the index is
-     * interpreted as cyclic.
-     */
-    public abstract static class UnitToInchesNode extends UnitNodeBase {
-        @Child GrobUnitToInches grobUnitToInches;
+    private static final class UnitConversionArgs {
+        public final UnitConversionContext ctx;
+        public final AxisOrDimension axisOrDim;
+        public final int index;
 
-        public static UnitToInchesNode create() {
-            return UnitToInchesNodeGen.create();
-        }
-
-        public double convertX(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.X);
-        }
-
-        public double convertY(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.Y);
-        }
-
-        public double convertWidth(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.WIDTH);
-        }
-
-        public double convertHeight(RAbstractContainer vector, int index, UnitConversionContext ctx) {
-            return execute(vector, index, ctx, AxisOrDimension.HEIGHT);
-        }
-
-        public double convertDimension(RAbstractContainer vector, int index, UnitConversionContext ctx, boolean isWidth) {
-            return isWidth ? convertWidth(vector, index, ctx) : convertHeight(vector, index, ctx);
+        UnitConversionArgs(int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+            this.ctx = ctx;
+            this.axisOrDim = axisOrDim;
+            this.index = index;
         }
+    }
 
-        public abstract double execute(RAbstractContainer vector, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim);
+    private static final class UnitConvertVisitor extends UnitVisitor<Double, UnitConversionArgs> {
+        private static final UnitConvertVisitor INSTANCE = new UnitConvertVisitor();
 
-        @Specialization(guards = "isSimple(value)")
-        double doNormal(RAbstractVector value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
-            int unitId = getDataAtMod(asIntVector(value.getAttr(UNIT_ATTR_UNIT_ID)), index);
-            double scalarValue = getDoubleAt(value, index % value.getLength());
+        @Override
+        protected Double visitSimpleUnit(RAbstractVector value, UnitConversionArgs args) {
+            int unitId = getDataAtMod(asIntVector(value.getAttr(UNIT_ATTR_UNIT_ID)), args.index);
+            double scalarValue = getDoubleAt(value, args.index % value.getLength());
             if (isGrobUnit(unitId)) {
                 RList grobList = asList(value.getAttr(UNIT_ATTR_DATA));
-                return getGrobUnitToInchesNode().execute(scalarValue, unitId, grobList.getDataAt(index % grobList.getLength()), ctx);
+                return grobUnitToInches(scalarValue, unitId, grobList.getDataAt(args.index % grobList.getLength()), args.ctx);
             }
-            return convertToInches(scalarValue, index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), ctx, axisOrDim);
+            return convertToInches(scalarValue, args.index, unitId, asListOrNull(value.getAttr(UNIT_ATTR_DATA)), args.ctx, args.axisOrDim);
         }
 
-        @Specialization(guards = "isUnitList(value)")
-        double doList(RList value, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
-                        @Cached("create()") UnitToInchesNode recursiveNode) {
-            Object unwrapped = value.getDataAt(index % value.getLength());
-            if (unwrapped instanceof RAbstractVector) {
-                return recursiveNode.execute((RAbstractContainer) unwrapped, 0, ctx, axisOrDim);
-            }
-            throw error(Message.GENERIC, "Unexpected unit list with non-vector like element at index " + index);
+        @Override
+        protected Double visitListUnit(RList unit, UnitConversionArgs args) {
+            return visit(asAbstractContainer(unit.getDataAt(args.index % unit.getLength())), new UnitConversionArgs(0, args.ctx, args.axisOrDim));
         }
 
-        @Specialization(guards = "isArithmetic(list)")
-        double doArithmetic(RList list, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim,
-                        @Cached("create()") UnitToInchesNode recursiveNode) {
-            ArithmeticUnit expr = ArithmeticUnit.asArithmeticUnit(list);
-            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> recursiveNode.execute(x, index, getNewCtx(ctx, axisOrDim, newNullAMode), axisOrDim);
+        @Override
+        protected Double visitArithmeticUnit(ArithmeticUnit expr, UnitConversionArgs args) {
+            BiFunction<RAbstractContainer, Integer, Double> recursive = (x, newNullAMode) -> visit(x,
+                            new UnitConversionArgs(args.index, getNewCtx(args.ctx, args.axisOrDim, newNullAMode), args.axisOrDim));
             switch (expr.op) {
                 case "+":
                     return recursive.apply(expr.arg1, L_adding) + recursive.apply(expr.arg2, L_adding);
@@ -614,17 +559,17 @@ public final class Unit {
                     return recursive.apply(expr.arg1, L_subtracting) - recursive.apply(expr.arg2, L_subtracting);
                 case "*":
                     RAbstractDoubleVector left = asDoubleVector(expr.arg1);
-                    return left.getDataAt(index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying);
+                    return left.getDataAt(args.index % left.getLength()) * recursive.apply(expr.arg2, L_multiplying);
                 default:
                     break;
             }
 
             // must be aggregate operation
-            UnitConversionContext newCtx = getNewCtx(ctx, axisOrDim, getNullAMode(expr.op));
+            UnitConversionContext newCtx = getNewCtx(args.ctx, args.axisOrDim, getNullAMode(expr.op));
             int len = getLength(expr.arg1);
             double[] values = new double[len];
             for (int i = 0; i < len; i++) {
-                values[i] = recursiveNode.execute(expr.arg1, i, newCtx, axisOrDim);
+                values[i] = visit(expr.arg1, new UnitConversionArgs(i, newCtx, args.axisOrDim));
             }
 
             switch (expr.op) {
@@ -656,105 +601,100 @@ public final class Unit {
             }
             return L_plain;
         }
+    }
 
-        private GrobUnitToInches getGrobUnitToInchesNode() {
-            if (grobUnitToInches == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                grobUnitToInches = insert(new GrobUnitToInches());
-            }
-            return grobUnitToInches;
-        }
+    public static double convert(RAbstractContainer unit, int index, UnitConversionContext ctx, AxisOrDimension axisOrDim) {
+        return UnitConvertVisitor.INSTANCE.visit(unit, new UnitConversionArgs(index, ctx, axisOrDim));
     }
 
-    public static final class GrobUnitToInches extends Node {
-        @Child private RGridCodeCall preDrawCode = new RGridCodeCall("grobConversionPreDraw");
-        @Child private RGridCodeCall getUnitXY = new RGridCodeCall("grobConversionGetUnitXY");
-        @Child private RGridCodeCall postDrawCode = new RGridCodeCall("grobConversionPostDraw");
-        @Child private GetViewPortTransformNode getViewPortTransform = new GetViewPortTransformNode();
-        @Child private UnitToInchesNode unitToInches = createToInchesNode();
-
-        @Child private UnitToInchesNode unitToInchesNode;
-
-        // transcribed from unit.c function evaluateGrobUnit
-
-        public double execute(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
-            GridState gridState = GridContext.getContext().getGridState();
-            return gridState.runWithoutRecording(() -> executeImpl(value, unitId, grob, conversionCtx));
-        }
-
-        private double executeImpl(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
-            GridContext ctx = GridContext.getContext();
-            RList currentVP = ctx.getGridState().getViewPort();
-            getViewPortTransform.execute(currentVP, conversionCtx.device);
-
-            RList savedGPar = ctx.getGridState().getGpar();
-            Object savedGrob = ctx.getGridState().getCurrentGrob();
-
-            Object updatedGrob = preDrawCode.call(grob);
-
-            /*
-             * The call to preDraw may have pushed viewports and/or enforced gpar settings, SO we
-             * need to re-establish the current viewport and gpar settings before evaluating the
-             * width unit.
-             */
-            currentVP = ctx.getGridState().getViewPort();
-            RList currentGP = ctx.getGridState().getGpar();
-            ViewPortTransform vpTransform = getViewPortTransform.execute(currentVP, conversionCtx.device);
-            ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
-
-            // getUnitXY returns a list with either one or two items
-            RList unitxy = (RList) getUnitXY.execute(new RArgsValuesAndNames(new Object[]{updatedGrob, unitId, value}, ArgumentsSignature.empty(3)));
-            double result;
-            switch (unitId) {
-                case GROBX:
-                case GROBY:
-                    if (unitId == GROBY && isRelativeUnit(ctx, unitxy.getDataAt(1), 0)) {
-                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
-                    } else if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
-                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
-                    } else {
-                        double[][] inversed = TransformMatrix.inversion(vpTransform.transform);
-                        Point loc = Point.fromUnits(unitToInches, (RAbstractVector) unitxy.getDataAt(0), (RAbstractVector) unitxy.getDataAt(1), 0, conversionCtx);
-                        Point transLoc = TransformMatrix.transLocation(loc, vpTransform.transform);
-                        Point p = TransformMatrix.transLocation(transLoc, inversed);
-                        result = unitId == GROBX ? p.x : p.y;
-                    }
-                    break;
-                default:
-                    // should still be GROB_SOMETHING unit: width, height, ascent, descent
-                    if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
-                        // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
-                        // GROBHEIGHT, bug?
-                        double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
-                        result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+    public static double convertX(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.X);
+    }
+
+    public static double convertY(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.Y);
+    }
+
+    public static double convertWidth(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.WIDTH);
+    }
+
+    public static double convertHeight(RAbstractContainer unit, int index, UnitConversionContext ctx) {
+        return convert(unit, index, ctx, AxisOrDimension.HEIGHT);
+    }
+
+    public static double convertDimension(RAbstractContainer unit, int index, UnitConversionContext ctx, boolean isWidth) {
+        return convert(unit, index, ctx, isWidth ? AxisOrDimension.WIDTH : AxisOrDimension.HEIGHT);
+    }
+
+    private static double grobUnitToInches(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
+        return GridContext.getContext().getGridState().runWithoutRecording(() -> grobUnitToInchesImpl(value, unitId, grob, conversionCtx));
+    }
+
+    private static double grobUnitToInchesImpl(double value, int unitId, Object grob, UnitConversionContext conversionCtx) {
+        GridContext ctx = GridContext.getContext();
+        RList currentVP = ctx.getGridState().getViewPort();
+        // This may update the VP if the device size has changed
+        ViewPortTransform.get(currentVP, conversionCtx.device);
+
+        RList savedGPar = ctx.getGridState().getGpar();
+        Object savedGrob = ctx.getGridState().getCurrentGrob();
+
+        Object updatedGrob = ctx.evalInternalRFunction("grobConversionPreDraw", grob);
+
+        /*
+         * The call to preDraw may have pushed viewports and/or enforced gpar settings, SO we need
+         * to re-establish the current viewport and gpar settings before evaluating the width unit.
+         */
+        currentVP = ctx.getGridState().getViewPort();
+        RList currentGP = ctx.getGridState().getGpar();
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, conversionCtx.device);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
+
+        // getUnitXY returns a list with either one or two items
+        RList unitxy = (RList) ctx.evalInternalRFunction("grobConversionGetUnitXY", updatedGrob, unitId, value);
+        double result;
+        switch (unitId) {
+            case GROBX:
+            case GROBY:
+                if (unitId == GROBY && isRelativeUnit(ctx, unitxy.getDataAt(1), 0)) {
+                    double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(1), 0);
+                    result = evaluateNullUnit(nullUnitValue, vpTransform.size.getHeight(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+                } else if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
+                    double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
+                    result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+                } else {
+                    double[][] inversed = TransformMatrix.inversion(vpTransform.transform);
+                    Point loc = Point.fromUnits((RAbstractVector) unitxy.getDataAt(0), (RAbstractVector) unitxy.getDataAt(1), 0, conversionCtx);
+                    Point transLoc = TransformMatrix.transLocation(loc, vpTransform.transform);
+                    Point p = TransformMatrix.transLocation(transLoc, inversed);
+                    result = unitId == GROBX ? p.x : p.y;
+                }
+                break;
+            default:
+                // should still be GROB_SOMETHING unit: width, height, ascent, descent
+                if (isRelativeUnit(ctx, unitxy.getDataAt(0), 0)) {
+                    // Note: GnuR uses equivalent of vpTransform.size.getWidth() even for
+                    // GROBHEIGHT, bug?
+                    double nullUnitValue = pureNullUnitValue((RAbstractContainer) unitxy.getDataAt(0), 0);
+                    result = evaluateNullUnit(nullUnitValue, vpTransform.size.getWidth(), conversionCtx.nullLayoutMode, conversionCtx.nullArithmeticMode);
+                } else {
+                    UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP));
+                    if (unitId == GROBWIDTH) {
+                        result = convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                     } else {
-                        UnitConversionContext newConversionCtx = new UnitConversionContext(vpTransform.size, vpContext, conversionCtx.device, GPar.create(currentGP));
-                        initUnitToInchesNode();
-                        if (unitId == GROBWIDTH) {
-                            result = unitToInchesNode.convertWidth((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
-                        } else {
-                            // Note: GnuR uses height transform for both grobascent, grobdescent and
-                            // for height
-                            result = unitToInchesNode.convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
-                        }
+                        // Note: GnuR uses height transform for both grobascent, grobdescent and
+                        // for height
+                        result = convertHeight((RAbstractContainer) unitxy.getDataAt(0), 0, newConversionCtx);
                     }
-                    result *= value;
-                    break;
-            }
-
-            postDrawCode.call(updatedGrob);
-            ctx.getGridState().setGpar(savedGPar);
-            ctx.getGridState().setCurrentGrob(savedGrob);
-            return result;
+                }
+                result *= value;
+                break;
         }
 
-        private void initUnitToInchesNode() {
-            if (unitToInchesNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                unitToInchesNode = UnitToInchesNode.create();
-            }
-        }
+        ctx.evalInternalRFunction("grobConversionPostDraw", updatedGrob);
+        ctx.getGridState().setGpar(savedGPar);
+        ctx.getGridState().setCurrentGrob(savedGrob);
+        return result;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
index 80e93f6270..6bd2592e16 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java
@@ -148,7 +148,6 @@ final class ViewPort {
     public static final class InitViewPortNode extends Node {
         @Child private ReadVariableNode readGridTopLevel = ReadVariableNode.create("grid.top.level.vp");
         @Child private RExplicitCallNode callNode = RExplicitCallNode.create();
-        @Child private DoSetViewPort doSetViewPort = new DoSetViewPort();
 
         public RList execute(VirtualFrame frame) {
             RFunction gridTopLevel = (RFunction) readGridTopLevel.execute(frame);
@@ -161,7 +160,7 @@ final class ViewPort {
             data[ViewPort.VP_XSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getWidth()}, RDataFactory.COMPLETE_VECTOR);
             data[ViewPort.VP_YSCALE] = RDataFactory.createDoubleVector(new double[]{0, device.getHeight()}, RDataFactory.COMPLETE_VECTOR);
             data[ViewPort.PVP_GPAR] = GridContext.getContext().getGridState().getGpar();
-            return doSetViewPort.doSetViewPort(topVP, false, true);
+            return DoSetViewPort.doSetViewPort(topVP, false, true);
         }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
index bed955d7f2..179ec60d18 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java
@@ -11,13 +11,7 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.casts.fluent.CastNodeBuilder.newCastBuilder;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
@@ -38,35 +32,17 @@ public final class ViewPortTransform {
         this.transform = transform;
     }
 
-    public static final class GetViewPortTransformNode extends Node {
-        @Child private CastNode castDoubleVector = newCastBuilder().mustBe(numericValue()).asDoubleVector().buildCastNode();
-        @Child private CastNode castScalarDouble = newCastBuilder().mustBe(numericValue()).asDoubleVector().findFirst().buildCastNode();
-        @Child private DoSetViewPort doSetViewPort;
-
-        public ViewPortTransform execute(RList viewPort, GridDevice device) {
-            if (ViewPort.updateDeviceSizeInVP(viewPort, device)) {
-                // Note: GnuR sets incremental parameter to true, but don't we need to recalculate
-                // the parent(s) as well?
-                initDoSetViewportNode();
-                doSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
-            }
-            double width = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
-            double height = Unit.cmToInches(getScalar(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
-            double rotationAngle = getScalar(viewPort.getDataAt(ViewPort.VP_ANGLE));
-            RAbstractDoubleVector trans = (RAbstractDoubleVector) castDoubleVector.execute(viewPort.getDataAt(ViewPort.PVP_TRANS));
-            double[][] transform = TransformMatrix.fromFlat(trans.materialize().getDataWithoutCopying());
-            return new ViewPortTransform(width, height, rotationAngle, transform);
-        }
-
-        private void initDoSetViewportNode() {
-            if (doSetViewPort == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                doSetViewPort = new DoSetViewPort();
-            }
-        }
-
-        private double getScalar(Object value) {
-            return (double) castScalarDouble.execute(value);
+    public static ViewPortTransform get(RList viewPort, GridDevice device) {
+        if (ViewPort.updateDeviceSizeInVP(viewPort, device)) {
+            // Note: GnuR sets incremental parameter to true, but don't we need to recalculate
+            // the parent(s) as well?
+            DoSetViewPort.calcViewportTransform(viewPort, viewPort.getDataAt(ViewPort.PVP_PARENT), true, device, GridState.getInitialGPar(device));
         }
+        double width = Unit.cmToInches(GridUtils.asDouble(viewPort.getDataAt(ViewPort.PVP_WIDTHCM)));
+        double height = Unit.cmToInches(GridUtils.asDouble(viewPort.getDataAt(ViewPort.PVP_HEIGHTCM)));
+        double rotationAngle = GridUtils.asDouble(viewPort.getDataAt(ViewPort.VP_ANGLE));
+        RAbstractDoubleVector trans = GridUtils.asDoubleVector(viewPort.getDataAt(ViewPort.PVP_TRANS));
+        double[][] transform = TransformMatrix.fromFlat(trans.materialize().getDataWithoutCopying());
+        return new ViewPortTransform(width, height, rotationAngle, transform);
     }
 }
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index a72c103a9a..e5dac23416 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -747,7 +747,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.ja
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DrawArrowsNode.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
-- 
GitLab


From 4d806b8ba9fd21caa793e9cf9868333007db9870 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 6 Apr 2017 11:19:58 +0200
Subject: [PATCH 245/402] remove remaining post-merge tasks from ci-hocon

---
 ci.hocon | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/ci.hocon b/ci.hocon
index b49df18470..947bcff284 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -152,11 +152,11 @@ internalPkgtest: ${common} {
 # The standard set of gate builds. N.B. the style/builtin checks are only run on Linux as they are not OS-dependent.
 
 builds = [
-  ${gateTestLinux}            {capabilities : [linux, amd64, fast],  targets : [gate, post-merge], name: "gate-test-linux-amd64"}
-#  ${gateTestLinuxNFI}         {capabilities : [linux, amd64, fast],  targets : [gate, post-merge], name: "gate-test-linux-nfi-amd64"}
-  ${gateTestNoSpecialsLinux}  {capabilities : [linux, amd64, fast],  targets : [gate, post-merge], name: "gate-test-linux-amd64-nospecials"}
-  ${gateTestDarwin}           {capabilities : [darwin, amd64], targets : [gate, post-merge], name: "gate-test-darwin-amd64"}
-  ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-style-linux-amd64"}
-  ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-rbcheck-linux-amd64"}
-  ${internalPkgtest}          {capabilities : [linux, amd64],  targets : [gate, post-merge], name: "gate-internal-pkgtest-linux-amd64"}
+  ${gateTestLinux}            {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-amd64"}
+#  ${gateTestLinuxNFI}         {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-nfi-amd64"}
+  ${gateTestNoSpecialsLinux}  {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-amd64-nospecials"}
+  ${gateTestDarwin}           {capabilities : [darwin, amd64], targets : [gate], name: "gate-test-darwin-amd64"}
+  ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate], name: "gate-style-linux-amd64"}
+  ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate], name: "gate-rbcheck-linux-amd64"}
+  ${internalPkgtest}          {capabilities : [linux, amd64],  targets : [gate], name: "gate-internal-pkgtest-linux-amd64"}
 ]
-- 
GitLab


From 4748f22f692fee4a656f286694303a2b8651c6f0 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 5 Apr 2017 15:09:55 +0200
Subject: [PATCH 246/402] better profiling in Combine

---
 .../truffle/r/nodes/builtin/base/Combine.java | 141 +++++++++---------
 1 file changed, 74 insertions(+), 67 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 8670e1bfc8..54e0f519e7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -41,16 +41,16 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.base.CombineNodeGen.CombineInputCastNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
@@ -76,7 +76,6 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "c", kind = PRIMITIVE, parameterNames = {"...", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
@@ -90,10 +89,11 @@ public abstract class Combine extends RBuiltinNode {
 
     protected static final int COMBINE_CACHED_LIMIT = PrecedenceNode.NUMBER_OF_PRECEDENCES;
 
-    private static final int MAX_PROFILES = 4;
+    private static final int MAX_PROFILES = 8;
 
     @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create();
-    @Child private CombineInputCast inputCast = CombineInputCastNodeGen.create(null);
+    @Children private final CombineInputCast[] inputCasts = new CombineInputCast[MAX_PROFILES];
+    @Child private CombineInputCast overflowInputCast;
     @Child private CastToVectorNode castVector;
 
     private final BranchProfile naBranch = BranchProfile.create();
@@ -101,7 +101,6 @@ public abstract class Combine extends RBuiltinNode {
     private final ConditionProfile fastNamesMerge = ConditionProfile.createBinaryProfile();
     private final ConditionProfile isAbstractVectorProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile hasNewNamesProfile = ConditionProfile.createBinaryProfile();
-    @CompilationFinal private final ValueProfile[] argProfiles = new ValueProfile[MAX_PROFILES];
 
     static {
         Casts casts = new Casts(Combine.class);
@@ -119,10 +118,24 @@ public abstract class Combine extends RBuiltinNode {
         return args.getArgument(0);
     }
 
+    private CombineInputCast getCast(int index) {
+        CombineInputCast cast = index < MAX_PROFILES ? inputCasts[index] : overflowInputCast;
+        if (cast == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            cast = insert(new CombineInputCast());
+            if (index < MAX_PROFILES) {
+                inputCasts[index] = cast;
+            } else {
+                overflowInputCast = cast;
+            }
+        }
+        return cast;
+    }
+
     @Specialization(replaces = "combineSimple", limit = "1", guards = {"!recursive", "args.getSignature() == cachedSignature", "cachedPrecedence == precedence(args, cachedSignature.getLength())"})
     protected Object combineCached(RArgsValuesAndNames args, @SuppressWarnings("unused") boolean recursive,
                     @Cached("args.getSignature()") ArgumentsSignature cachedSignature,
-                    @Cached("precedence( args, cachedSignature.getLength())") int cachedPrecedence,
+                    @Cached("precedence(args, cachedSignature.getLength())") int cachedPrecedence,
                     @Cached("createCast(cachedPrecedence)") CastNode cast,
                     @Cached("create()") BranchProfile naNameBranch,
                     @Cached("create()") NACheck naNameCheck,
@@ -172,9 +185,7 @@ public abstract class Combine extends RBuiltinNode {
         return combineRecursive(args, recursiveCombine, useNewArgsProfile);
     }
 
-    @SuppressWarnings("static-method")
-    @ExplodeLoop
-    private Object combineRecursive(RArgsValuesAndNames args, Combine recursiveCombine, ConditionProfile useNewArgsProfile) {
+    private static Object combineRecursive(RArgsValuesAndNames args, Combine recursiveCombine, ConditionProfile useNewArgsProfile) {
         Object[] argsArray = args.getArguments();
         Object[] newArgsArray = new Object[argsArray.length];
         boolean useNewArgs = false;
@@ -202,14 +213,10 @@ public abstract class Combine extends RBuiltinNode {
     private int prepareElements(Object[] args, CastNode cast, int precedence, Object[] elements) {
         int size = 0;
         for (int i = 0; i < elements.length; i++) {
-            Object element = readAndCast(cast, args[i], precedence);
-            if (i < argProfiles.length) {
-                if (argProfiles[i] == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    argProfiles[i] = ValueProfile.createClassProfile();
-                }
-                element = argProfiles[i].profile(element);
-            }
+            CombineInputCast inputCast = getCast(i);
+            Object value = args[i];
+            Object element = (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : cast.execute(inputCast.cast(value));
+            element = inputCast.valueProfile.profile(element);
             elements[i] = element;
             size += getElementSize(element);
         }
@@ -230,10 +237,7 @@ public abstract class Combine extends RBuiltinNode {
     @ExplodeLoop
     private boolean hasNames(Object[] elements, GetNamesAttributeNode getNamesNode) {
         for (int i = 0; i < elements.length; i++) {
-            Object element = elements[i];
-            if (i < argProfiles.length) {
-                element = argProfiles[i].profile(element);
-            }
+            Object element = getCast(i).valueProfile.profile(elements[i]);
             if (element instanceof RAbstractVector) {
                 RAbstractVector vector = (RAbstractVector) element;
                 if (getNamesNode.getNames(vector) != null) {
@@ -250,10 +254,7 @@ public abstract class Combine extends RBuiltinNode {
         result.incRefCount();
         int pos = 0;
         for (int i = 0; i < elements.length; i++) {
-            Object element = elements[i];
-            if (i < argProfiles.length) {
-                element = argProfiles[i].profile(element);
-            }
+            Object element = getCast(i).valueProfile.profile(elements[i]);
             pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element, i, signature, getNamesNode);
         }
         return result;
@@ -302,7 +303,8 @@ public abstract class Combine extends RBuiltinNode {
     private RVector<?> foldContents(int cachedPrecedence, Object[] elements, int size, RStringVector namesVector) {
         RVector<?> result = createResultVector(cachedPrecedence, size, namesVector);
         int pos = 0;
-        for (Object element : elements) {
+        for (int i = 0; i < elements.length; i++) {
+            Object element = getCast(i).valueProfile.profile(elements[i]);
             pos += processContentElement(result, pos, element);
         }
         return result;
@@ -339,11 +341,6 @@ public abstract class Combine extends RBuiltinNode {
         return combine.executeCombine(new RArgsValuesAndNames(new Object[]{args}, EMPTY_SIGNATURE), recursive);
     }
 
-    private Object readAndCast(CastNode castNode, Object arg, int precedence) {
-        Object value = inputCast.execute(arg);
-        return (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : castNode.execute(value);
-    }
-
     protected int precedence(RArgsValuesAndNames args) {
         int precedence = NO_PRECEDENCE;
         Object[] array = args.getArguments();
@@ -455,49 +452,59 @@ public abstract class Combine extends RBuiltinNode {
         return names;
     }
 
-    @NodeChild
-    protected abstract static class CombineInputCast extends RNode {
-
-        @Child private GetDimNamesAttributeNode getDimNamesNode = GetDimNamesAttributeNode.create();
-        @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
-
-        public abstract Object execute(Object operand);
+    protected static final class CombineInputCast extends Node {
 
-        @Specialization(guards = "!isVector(operand)")
-        protected Object pass(Object operand) {
-            return operand;
-        }
+        @Child private GetDimNamesAttributeNode getDimNamesNode;
+        @Child private GetNamesAttributeNode getNamesNode;
 
-        protected static boolean isVector(Object operand) {
-            return operand instanceof RVector;
-        }
+        private final ValueProfile valueProfile = ValueProfile.createClassProfile();
+        private final ValueProfile inputValueProfile = ValueProfile.createClassProfile();
 
-        @Specialization(guards = "needsCopy(vector)")
-        protected RAbstractVector noCopy(RAbstractVector vector,
-                        @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile hasDimNamesProfile) {
-            RVector<?> materialized = vector.materialize();
-            RVector<?> result = materialized.copyDropAttributes();
+        @CompilationFinal private ConditionProfile hasNamesProfile;
+        @CompilationFinal private ConditionProfile hasDimNamesProfile;
 
-            RStringVector vecNames = getNamesNode.getNames(materialized);
-            if (hasNamesProfile.profile(vecNames != null)) {
-                result.initAttributes(RAttributesLayout.createNames(vecNames));
-            } else {
-                RList dimNames = getDimNamesNode.getDimNames(materialized);
-                if (hasDimNamesProfile.profile(dimNames != null)) {
-                    result.initAttributes(RAttributesLayout.createDimNames(dimNames));
+        public Object cast(Object operand) {
+            Object profiled = inputValueProfile.profile(operand);
+            if (profiled instanceof RVector<?>) {
+                RVector<?> vector = (RVector<?>) profiled;
+                if (vector.getAttributes() != null) {
+                    if (getNamesNode == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        getNamesNode = insert(GetNamesAttributeNode.create());
+                    }
+                    if (hasNamesProfile == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        hasNamesProfile = ConditionProfile.createBinaryProfile();
+                    }
+                    RStringVector vecNames = getNamesNode.getNames(vector);
+                    if (hasNamesProfile.profile(vecNames != null)) {
+                        RVector<?> result = vector.copyDropAttributes();
+                        result.initAttributes(RAttributesLayout.createNames(vecNames));
+                        return result;
+                    } else {
+                        if (getDimNamesNode == null) {
+                            CompilerDirectives.transferToInterpreterAndInvalidate();
+                            getDimNamesNode = insert(GetDimNamesAttributeNode.create());
+                        }
+                        if (hasDimNamesProfile == null) {
+                            CompilerDirectives.transferToInterpreterAndInvalidate();
+                            hasDimNamesProfile = ConditionProfile.createBinaryProfile();
+                        }
+                        RList dimNames = getDimNamesNode.getDimNames(vector);
+                        if (hasDimNamesProfile.profile(dimNames != null)) {
+                            RVector<?> result = vector.copyDropAttributes();
+                            result.initAttributes(RAttributesLayout.createDimNames(dimNames));
+                            return result;
+                        }
+                    }
                 }
             }
-            return result;
-        }
-
-        @Specialization(guards = "!needsCopy(vector)")
-        protected RAbstractVector prepareVector(RAbstractVector vector) {
-            return vector;
+            return profiled;
         }
 
-        protected boolean needsCopy(RAbstractVector vector) {
-            return vector.getAttributes() != null || getNamesNode.getNames(vector) != null || getDimNamesNode.getDimNames(vector) != null;
+        @Override
+        public NodeCost getCost() {
+            return NodeCost.NONE;
         }
     }
 }
-- 
GitLab


From afd0c5f054b625341d2e7739ff9f16b447babb95 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 5 Apr 2017 15:10:45 +0200
Subject: [PATCH 247/402] more efficient ordering of conditions in
 CachedReplaceVectorNode

---
 .../r/nodes/access/vector/CachedReplaceVectorNode.java      | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
index 68c08d76c2..bcd95f77d8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
@@ -81,7 +81,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
     private final BranchProfile warningBranch = BranchProfile.create();
     private final ConditionProfile valueIsNA = ConditionProfile.createBinaryProfile();
     private final BranchProfile resizeProfile = BranchProfile.create();
-    private final BranchProfile sharedProfile = BranchProfile.create();
     private final ConditionProfile rlanguageAttributesProfile = ConditionProfile.createBinaryProfile();
 
     private final ConditionProfile valueLengthOneProfile = ConditionProfile.createBinaryProfile();
@@ -509,8 +508,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         if (returnVector instanceof RShareable) {
             RShareable shareable = (RShareable) returnVector;
             // TODO find out if we need to copy always in the recursive case
-            if (sharedConditionProfile.execute(shareable.isShared()) || recursive || valueEqualsVectorProfile.profile(vector == value)) {
-                sharedProfile.enter();
+            if (recursive || sharedConditionProfile.execute(shareable.isShared()) || valueEqualsVectorProfile.profile(vector == value)) {
                 shareable = (RShareable) returnVector.copy();
                 returnVector = (RAbstractVector) shareable;
                 assert shareable.isTemporary();
@@ -523,7 +521,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         return returnVector;
     }
 
-    // TODO (chumer) this is way to compilicated at the moment
+    // TODO (chumer) this is way to complicated at the moment
     // not yet worth compiling. we should introduce some nodes for this
     @TruffleBoundary
     private static void copyAttributes(RAbstractVector vector, RList result) {
-- 
GitLab


From 8e31795c8ffb0fb529363863a6ca5bb017ca45e6 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 5 Apr 2017 15:11:15 +0200
Subject: [PATCH 248/402] better profiling, simplifications and fixes in rep

---
 .../truffle/r/nodes/builtin/base/Repeat.java  | 160 ++++++++----------
 .../truffle/r/test/ExpectedTestOutput.test    |  28 +++
 .../r/test/builtins/TestBuiltin_rep.java      |   7 +
 3 files changed, 106 insertions(+), 89 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index 1d3f608b04..2da580ca12 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -33,13 +33,15 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.util.Arrays;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
-import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
+import com.oracle.truffle.api.profiles.PrimitiveValueProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.RepeatNodeGen.FastRInternalRepeatNodeGen;
@@ -53,6 +55,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -94,17 +97,6 @@ public abstract class Repeat extends RBuiltinNode {
     private static final int ARG_IDX_LENGHT_OUT;
     private static final int ARG_IDX_EACH;
 
-    @Child private FastRInternalRepeat internalNode = FastRInternalRepeatNodeGen.create();
-    @Child private CastNode castTimes = PB_TIMES.buildNode();
-    @Child private CastNode castLengthOut = PB_LENGTH_OUT.buildNode();
-    @Child private CastNode castEach = PB_EACH.buildNode();
-    @Child private PrepareMatchInternalArguments prepareArgs = PrepareMatchInternalArgumentsNodeGen.create(FORMALS, this);
-
-    @Override
-    public Object[] getDefaultParameterValues() {
-        return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY};
-    }
-
     static {
         Casts casts = new Casts(Repeat.class);
         casts.arg("x").mustBe(abstractVectorValue(), RError.Message.ATTEMPT_TO_REPLICATE, typeName());
@@ -130,6 +122,17 @@ public abstract class Repeat extends RBuiltinNode {
         FORMALS = FormalArguments.createForBuiltin(new Object[]{1, RRuntime.INT_NA, 1}, signature);
     }
 
+    @Child private FastRInternalRepeat internalNode = FastRInternalRepeatNodeGen.create();
+    @Child private CastNode castTimes = PB_TIMES.buildNode();
+    @Child private CastNode castLengthOut = PB_LENGTH_OUT.buildNode();
+    @Child private CastNode castEach = PB_EACH.buildNode();
+    @Child private PrepareMatchInternalArguments prepareArgs = PrepareMatchInternalArgumentsNodeGen.create(FORMALS, this);
+
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY};
+    }
+
     @Specialization
     protected Object repeat(VirtualFrame frame, RAbstractVector x, RArgsValuesAndNames args) {
         RArgsValuesAndNames margs = prepareArgs.execute(args, null);
@@ -144,87 +147,73 @@ public abstract class Repeat extends RBuiltinNode {
 
     @TypeSystemReference(RTypes.class)
     abstract static class FastRInternalRepeat extends RBaseNode {
+
         private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile();
         private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile();
 
         @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
 
-        public abstract RAbstractVector execute(VirtualFrame frame, Object... args);
-
-        protected boolean hasNames(RAbstractVector x) {
-            return getNames.getNames(x) != null;
-        }
+        @CompilationFinal private boolean trySimple = true;
 
-        @Specialization(guards = {"x.getLength() == 1", "times.getLength() == 1", "each <= 1", "!hasNames(x)"})
-        protected RAbstractVector repNoEachNoNamesSimple(RAbstractDoubleVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
-            int t = times.getDataAt(0);
-            if (t < 0) {
-                throw error(RError.Message.INVALID_ARGUMENT, "times");
-            }
-            int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
-            double[] data = new double[length];
-            Arrays.fill(data, x.getDataAt(0));
-            return RDataFactory.createDoubleVector(data, !RRuntime.isNA(x.getDataAt(0)));
-        }
+        public abstract RAbstractVector execute(VirtualFrame frame, Object... args);
 
-        @Specialization(guards = {"each > 1", "!hasNames(x)"})
-        protected RAbstractVector repEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) {
-            if (times.getLength() > 1) {
-                throw error(RError.Message.INVALID_ARGUMENT, "times");
-            }
-            RAbstractVector input = handleEach(x, each);
-            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-                return handleLengthOut(input, lengthOut, false);
-            } else {
-                return handleTimes(input, times, false);
-            }
-        }
+        @Specialization
+        protected RAbstractVector rep(RAbstractVector xIn, RAbstractIntVector timesIn, int lengthOutIn, int eachIn,
+                        @Cached("createClassProfile()") ValueProfile xProfile,
+                        @Cached("createClassProfile()") ValueProfile timesProfile,
+                        @Cached("createEqualityProfile()") PrimitiveValueProfile lengthOutProfile,
+                        @Cached("createEqualityProfile()") PrimitiveValueProfile eachProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) {
+            RAbstractVector x = xProfile.profile(xIn);
+            RAbstractIntVector times = timesProfile.profile(timesIn);
+            int lengthOut = lengthOutProfile.profile(lengthOutIn);
+            int each = eachProfile.profile(eachIn);
 
-        @Specialization(guards = {"each <= 1", "!hasNames(x)"})
-        protected RAbstractVector repNoEachNoNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) {
-            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-                return handleLengthOut(x, lengthOut, true);
-            } else {
-                return handleTimes(x, times, true);
+            // fast path for very simple case of filling with a single double values:
+            if (trySimple) {
+                if (x instanceof RAbstractDoubleVector && x.getLength() == 1 && times.getLength() == 1 && each == 1 && getNames.getNames(x) == null) {
+                    RAbstractDoubleVector doubleVector = (RAbstractDoubleVector) x;
+                    int t = times.getDataAt(0);
+                    if (t < 0) {
+                        throw error(RError.Message.INVALID_ARGUMENT, "times");
+                    }
+                    int length = lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut)) ? lengthOut : t;
+                    double[] data = new double[length];
+                    Arrays.fill(data, doubleVector.getDataAt(0));
+                    return RDataFactory.createDoubleVector(data, !RRuntime.isNA(doubleVector.getDataAt(0)));
+                } else {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    trySimple = false;
+                }
             }
+            return repInternal(x, times, lengthOut, each, hasNamesProfile);
         }
 
-        @Specialization(guards = {"each > 1", "hasNames(x)"})
-        protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each,
-                        @Cached("create()") InitAttributesNode initAttributes,
-                        @Cached("createNames()") SetFixedAttributeNode putNames) {
-            if (times.getLength() > 1) {
-                throw error(RError.Message.INVALID_ARGUMENT, "times");
+        private RAbstractVector repInternal(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, ConditionProfile hasNamesProfile) {
+            RAbstractVector input = x;
+            if (each != 1) {
+                if (each <= 0) {
+                    throw error(RError.Message.INVALID_ARGUMENT, "times");
+                }
+                if (times.getLength() > 1) {
+                    throw error(RError.Message.INVALID_ARGUMENT, "times");
+                }
+                input = handleEach(input, each);
             }
-            RAbstractVector input = handleEach(x, each);
-            RStringVector names = (RStringVector) handleEach(getNames.getNames(x), each);
             RVector<?> r;
-            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-                names = (RStringVector) handleLengthOut(names, lengthOut, false);
-                r = handleLengthOut(input, lengthOut, false);
+            if (lengthOutOrTimes.profile(RRuntime.isNA(lengthOut))) {
+                r = handleTimes(input, times);
             } else {
-                names = (RStringVector) handleTimes(names, times, false);
-                r = handleTimes(input, times, false);
+                r = handleLengthOut(input, lengthOut);
             }
-            putNames.execute(initAttributes.execute(r), names);
-            return r;
-        }
-
-        @Specialization(guards = {"each <= 1", "hasNames(x)"})
-        protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each,
-                        @Cached("create()") InitAttributesNode initAttributes,
-                        @Cached("createNames()") SetFixedAttributeNode putNames) {
-            RStringVector names;
-            RVector<?> r;
-            if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) {
-                names = (RStringVector) handleLengthOut(getNames.getNames(x), lengthOut, true);
-                r = handleLengthOut(x, lengthOut, true);
-            } else {
-                names = (RStringVector) handleTimes(getNames.getNames(x), times, true);
-                r = handleTimes(x, times, true);
+            if (hasNamesProfile != null) {
+                RStringVector names = getNames.getNames(x);
+                if (hasNamesProfile.profile(names != null)) {
+                    // handle names - passing null as hasNamesProfile stops the recursion
+                    names = (RStringVector) repInternal(names, times, lengthOut, each, null);
+                    r.initAttributes(RAttributesLayout.createNames(names));
+                }
             }
-            putNames.execute(initAttributes.execute(r), names);
             return r;
         }
 
@@ -244,28 +233,21 @@ public abstract class Repeat extends RBuiltinNode {
         /**
          * Extend or truncate the vector to a specified length.
          */
-        private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut, boolean copyIfSameSize) {
-            if (x.getLength() == lengthOut) {
-                return (RVector<?>) (copyIfSameSize ? x.copy() : x);
-            }
+        private static RVector<?> handleLengthOut(RAbstractVector x, int lengthOut) {
             return x.copyResized(lengthOut, false);
         }
 
         /**
          * Replicate the vector a given number of times.
          */
-        private RVector<?> handleTimes(RAbstractVector x, RAbstractIntVector times, boolean copyIfSameSize) {
+        private RVector<?> handleTimes(RAbstractVector x, RAbstractIntVector times) {
             if (oneTimeGiven.profile(times.getLength() == 1)) {
                 // only one times value is given
-                final int howManyTimes = times.getDataAt(0);
+                int howManyTimes = times.getDataAt(0);
                 if (howManyTimes < 0) {
                     throw error(RError.Message.INVALID_ARGUMENT, "times");
                 }
-                if (replicateOnce.profile(howManyTimes == 1)) {
-                    return (RVector<?>) (copyIfSameSize ? x.copy() : x);
-                } else {
-                    return x.copyResized(x.getLength() * howManyTimes, false);
-                }
+                return x.copyResized(x.getLength() * howManyTimes, false);
             } else {
                 // times is a vector with several elements
                 if (x.getLength() != times.getLength()) {
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 4a91d4b30c..2558fbb5f9 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
@@ -47286,6 +47286,34 @@ attr(,"useBytes")
 #rep(x<-42)
 [1] 42
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 1)
+asdf
+   1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 2)
+asdf asdf
+   1    1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; rep(v, 1)
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; rep(v, 2)
+[1] 1 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; names(v) <- 'asdf'; rep(v, 1)
+asdf
+   1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; names(v) <- 'asdf'; rep(v, 2)
+asdf asdf
+   1    1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
 #{ rep("hello", 3) }
 [1] "hello" "hello" "hello"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
index b5dbe71e52..df9b448fc3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
@@ -224,5 +224,12 @@ public class TestBuiltin_rep extends TestBase {
         assertEval("{ rep(7, times=-1) }");
         assertEval("{ rep(c(7, 42), times=c(2, NA)) }");
         assertEval(Output.IgnoreWarningContext, "{ rep(7, times=\"foo\") }");
+
+        assertEval("v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 1)");
+        assertEval("v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 2)");
+        assertEval("v <- 1; names(v) <- 'asdf'; rep(v, 1)");
+        assertEval("v <- 1; names(v) <- 'asdf'; rep(v, 2)");
+        assertEval("v <- 1; class(v) <- 'asdf'; rep(v, 1)");
+        assertEval("v <- 1; class(v) <- 'asdf'; rep(v, 2)");
     }
 }
-- 
GitLab


From 16c4aedc792f01a5d4468322de10dadcecc6fb34 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Feb 2017 18:29:36 +0100
Subject: [PATCH 249/402] profile arguments in Match

---
 .../truffle/r/nodes/builtin/base/Match.java   | 41 +++++++++++++++----
 .../oracle/truffle/r/nodes/ffi/MiscNodes.java |  2 +-
 2 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index e8ba5a9eed..48c9080808 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -34,10 +34,12 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.MatchNodeGen.MatchInternalNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.MatchNodeGen.ProfiledMatchInternalNodeGen;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
 import com.oracle.truffle.r.nodes.helpers.RFactorNodes;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
@@ -86,8 +88,8 @@ public abstract class Match extends RBuiltinNode {
                         logicalFalse());
     }
 
-    protected static MatchInternalNode createInternal() {
-        return MatchInternalNodeGen.create();
+    protected static ProfiledMatchInternalNode createInternal() {
+        return ProfiledMatchInternalNodeGen.create();
     }
 
     @Specialization
@@ -120,7 +122,7 @@ public abstract class Match extends RBuiltinNode {
     @Specialization(guards = {"isFactor(x)", "isFactor(table)"})
     protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
                     @Cached("create()") RFactorNodes.GetLevels getLevelsNode,
-                    @Cached("createInternal()") MatchInternalNode match) {
+                    @Cached("createInternal()") ProfiledMatchInternalNode match) {
         return match.execute(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)),
                         RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch);
     }
@@ -128,27 +130,27 @@ public abstract class Match extends RBuiltinNode {
     @Specialization(guards = {"isFactor(x)", "!isFactor(table)"})
     protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
                     @Cached("create()") RFactorNodes.GetLevels getLevelsNode,
-                    @Cached("createInternal()") MatchInternalNode match) {
+                    @Cached("createInternal()") ProfiledMatchInternalNode match) {
         return match.execute(RClosures.createFactorToVector(x, true, getLevelsNode.execute(x)), table, nomatch);
     }
 
     @Specialization(guards = {"!isFactor(x)", "isFactor(table)"})
     protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, int nomatch, @SuppressWarnings("unused") Object incomparables,
                     @Cached("create()") RFactorNodes.GetLevels getLevelsNode,
-                    @Cached("createInternal()") MatchInternalNode match) {
+                    @Cached("createInternal()") ProfiledMatchInternalNode match) {
         return match.execute(x, RClosures.createFactorToVector(table, true, getLevelsNode.execute(table)), nomatch);
     }
 
     @Specialization(guards = {"!isRAbstractIntVector(table) || !isFactor(table)"})
     protected Object matchList(RAbstractListVector x, RAbstractVector table, int nomatchObj, @SuppressWarnings("unused") Object incomparables,
                     @Cached("create()") CastStringNode cast,
-                    @Cached("createInternal()") MatchInternalNode match) {
+                    @Cached("createInternal()") ProfiledMatchInternalNode match) {
         return match.execute((RAbstractVector) cast.execute(x), table, nomatchObj);
     }
 
     @Specialization(guards = {"!isRAbstractListVector(x)", "!isRAbstractIntVector(x) || !isFactor(x)", "!isRAbstractIntVector(table) || !isFactor(table)"})
     protected Object match(RAbstractVector x, RAbstractVector table, int noMatch, @SuppressWarnings("unused") Object incomparables,
-                    @Cached("createInternal()") MatchInternalNode match) {
+                    @Cached("createInternal()") ProfiledMatchInternalNode match) {
         return match.execute(x, table, noMatch);
     }
 
@@ -158,6 +160,31 @@ public abstract class Match extends RBuiltinNode {
         throw error(MATCH_VECTOR_ARGS);
     }
 
+    protected abstract static class ProfiledMatchInternalNode extends Node {
+
+        protected static final int PROFILE_LIMIT = 2;
+
+        protected abstract Object execute(RAbstractVector x, RAbstractVector table, int noMatch);
+
+        protected static MatchInternalNode createInternal() {
+            return MatchInternalNodeGen.create();
+        }
+
+        @Specialization(limit = "PROFILE_LIMIT", guards = {"x.getClass() == xClass", "table.getClass() == tableClass"})
+        protected static Object matchProfiled(RAbstractVector x, RAbstractVector table, int noMatch,
+                        @Cached("x.getClass()") Class<? extends RAbstractVector> xClass,
+                        @Cached("table.getClass()") Class<? extends RAbstractVector> tableClass,
+                        @Cached("createInternal()") MatchInternalNode match) {
+            return match.execute(xClass.cast(x), tableClass.cast(table), noMatch);
+        }
+
+        @Specialization(replaces = "matchProfiled")
+        protected static Object match(RAbstractVector x, RAbstractVector table, int noMatch,
+                        @Cached("createInternal()") MatchInternalNode match) {
+            return match.execute(x, table, noMatch);
+        }
+    }
+
     protected abstract static class MatchInternalNode extends RBaseNode {
 
         private static final int TABLE_SIZE_FACTOR = 10;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
index 3a1ee7f7de..1391299116 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
@@ -103,7 +103,7 @@ public final class MiscNodes {
         }
 
         @Fallback
-        Object doSlot(@SuppressWarnings("unused") Object o, @SuppressWarnings("unused") Object name) {
+        Object doSlot(@SuppressWarnings("unused") Object o, Object name) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name());
         }
 
-- 
GitLab


From addbd3c3ac12ceed4bd7e5927cc3985d28aed038 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 10 Feb 2017 09:05:51 +0100
Subject: [PATCH 250/402] simplify PromiseHelperNode

---
 .../r/nodes/function/PromiseHelperNode.java   | 42 +++++++++----------
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index 836a0029fc..303eef2165 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
@@ -155,7 +156,6 @@ public class PromiseHelperNode extends RBaseNode {
             return value;
         }
 
-        Object obj;
         int state = optStateProfile.profile(promise.getState());
         if (PromiseState.isExplicit(state)) {
             CompilerDirectives.transferToInterpreter();
@@ -165,17 +165,9 @@ public class PromiseHelperNode extends RBaseNode {
             return evaluateSlowPath(frame, promise);
         }
         if (PromiseState.isDefaultOpt(state)) {
-            obj = generateValueDefault(frame, promise);
+            return generateValueDefault(frame, promise);
         } else {
-            obj = generateValueEager(frame, state, (EagerPromise) promise);
-        }
-        if (isEvaluated(promise)) {
-            // TODO: this only happens if compilation is in play and, as such, is difficult to track
-            // why (there is no obvious call path...)
-            return promise.getValue();
-        } else {
-            setValue(obj, promise);
-            return obj;
+            return generateValueNonDefault(frame, state, (EagerPromise) promise);
         }
     }
 
@@ -190,28 +182,34 @@ public class PromiseHelperNode extends RBaseNode {
                 promiseClosureCache = insert(InlineCacheNode.createPromise(FastROptions.PromiseCacheSize.getNonNegativeIntValue()));
             }
             promise.setUnderEvaluation();
-            if (isInOriginFrame(frame, promise)) {
-                return promiseClosureCache.execute(frame, promise.getClosure());
-            } else {
-                return promiseClosureCache.execute(wrapPromiseFrame(frame, promiseFrameProfile.profile(promise.getFrame())), promise.getClosure());
-            }
+            Frame execFrame = isInOriginFrame(frame, promise) ? frame : wrapPromiseFrame(frame, promiseFrameProfile.profile(promise.getFrame()));
+            Object value = promiseClosureCache.execute(execFrame, promise.getClosure());
+            assert promise.getRawValue() == null;
+            assert value != null;
+            promise.setValue(value);
+            return value;
         } finally {
             promise.resetUnderEvaluation();
         }
     }
 
-    private Object generateValueEager(VirtualFrame frame, int state, EagerPromise promise) {
+    private Object generateValueNonDefault(VirtualFrame frame, int state, EagerPromise promise) {
         assert !PromiseState.isDefaultOpt(state);
         if (!isDeoptimized(promise)) {
             Assumption eagerAssumption = isValidAssumptionProfile.profile(promise.getIsValidAssumption());
             if (eagerAssumption.isValid()) {
-                if (!PromiseState.isEager(state)) {
-                    RPromise nextPromise = (RPromise) promise.getEagerValue();
-                    return checkNextNode().evaluate(frame, nextPromise);
-                } else {
+                Object value;
+                if (PromiseState.isEager(state)) {
                     assert PromiseState.isEager(state);
-                    return getEagerValue(frame, promise);
+                    value = getEagerValue(frame, promise);
+                } else {
+                    RPromise nextPromise = (RPromise) promise.getEagerValue();
+                    value = checkNextNode().evaluate(frame, nextPromise);
                 }
+                assert promise.getRawValue() == null;
+                assert value != null;
+                promise.setValue(value);
+                return value;
             } else {
                 CompilerDirectives.transferToInterpreter();
                 promise.notifyFailure();
-- 
GitLab


From 28e8ad8914bdc5cf5d5ddc8802fb779eb7e6ef9e Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 3 Mar 2017 13:15:45 +0100
Subject: [PATCH 251/402] some more profiles in AsVector, IsElementFastPath and
 OptForcedEagerPromiseNode

---
 .../r/nodes/builtin/base/AsVector.java        | 24 +++++++++++++------
 .../base/fastpaths/IsElementFastPath.java     | 15 ++++++++++--
 .../opt/OptForcedEagerPromiseNode.java        | 12 ++++++----
 3 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index b0ce114681..7a32d4cc10 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -64,11 +64,13 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
 public abstract class AsVector extends RBuiltinNode {
@@ -169,7 +171,7 @@ public abstract class AsVector extends RBuiltinNode {
             return drop.execute(cast == null ? x : cast.execute(x));
         }
 
-        public abstract static class DropAttributesNode extends Node {
+        public abstract static class DropAttributesNode extends RBaseNode {
 
             public abstract Object execute(Object o);
 
@@ -181,15 +183,23 @@ public abstract class AsVector extends RBuiltinNode {
                 return clazz.cast(o).getAttributes() != null;
             }
 
-            @Specialization(guards = {"o.getClass() == oClass", "hasAttributes(oClass, o)"})
+            @Specialization(guards = "o.getAttributes() == null")
+            protected static RSharingAttributeStorage drop(RSharingAttributeStorage o) {
+                // quickly reject any RSharingAttributeStorage without attributes
+                return o;
+            }
+
+            @Specialization(guards = "o.getClass() == oClass")
             protected RAbstractVector dropCached(RAbstractAtomicVector o,
-                            @Cached("o.getClass()") Class<? extends RAbstractAtomicVector> oClass) {
-                return oClass.cast(o).copyDropAttributes();
+                            @Cached("o.getClass()") Class<? extends RAbstractAtomicVector> oClass,
+                            @Cached("createBinaryProfile()") ConditionProfile profile) {
+                return profile.profile(hasAttributes(oClass, o)) ? oClass.cast(o).copyDropAttributes() : o;
             }
 
-            @Specialization(replaces = "dropCached", guards = "o.getAttributes() != null")
-            protected RAbstractVector drop(RAbstractAtomicVector o) {
-                return o.copyDropAttributes();
+            @Specialization(replaces = "dropCached")
+            protected RAbstractVector drop(RAbstractAtomicVector o,
+                            @Cached("createBinaryProfile()") ConditionProfile profile) {
+                return profile.profile(o.getAttributes() != null) ? o.copyDropAttributes() : o;
             }
 
             @Specialization(guards = "o.getAttributes() != null")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java
index 3239623be3..c211bb753e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IsElementFastPath.java
@@ -37,10 +37,14 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public abstract class IsElementFastPath extends RFastPathNode {
 
-    @Specialization(guards = "el.getLength() == 1")
-    protected Byte iselementOne(RAbstractStringVector el, RAbstractStringVector set,
+    @Specialization(guards = {"elIn.getLength() == 1", "elIn.getClass() == elClass", "setIn.getClass() == setClass"})
+    protected Byte iselementOneCachedString(RAbstractStringVector elIn, RAbstractStringVector setIn,
+                    @Cached("elIn.getClass()") Class<? extends RAbstractStringVector> elClass,
+                    @Cached("setIn.getClass()") Class<? extends RAbstractStringVector> setClass,
                     @Cached("create()") BranchProfile trueProfile,
                     @Cached("create()") BranchProfile falseProfile) {
+        RAbstractStringVector el = elClass.cast(elIn);
+        RAbstractStringVector set = setClass.cast(setIn);
         String element = el.getDataAt(0);
         int length = set.getLength();
         for (int i = 0; i < length; i++) {
@@ -53,6 +57,13 @@ public abstract class IsElementFastPath extends RFastPathNode {
         return RRuntime.LOGICAL_FALSE;
     }
 
+    @Specialization(replaces = "iselementOneCachedString")
+    protected Byte iselementOne(RAbstractStringVector elIn, RAbstractStringVector setIn,
+                    @Cached("create()") BranchProfile trueProfile,
+                    @Cached("create()") BranchProfile falseProfile) {
+        return iselementOneCachedString(elIn, setIn, RAbstractStringVector.class, RAbstractStringVector.class, trueProfile, falseProfile);
+    }
+
     @Specialization
     protected Byte iselementOne(double el, double set) {
         return RRuntime.asLogical(el == set);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java
index 5ffc0cef62..73380b076b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptForcedEagerPromiseNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.function.ArgumentStatePush;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.PromiseNode;
@@ -46,8 +47,9 @@ public final class OptForcedEagerPromiseNode extends PromiseNode {
     @Child private RNode expr;
     @Child private PromiseHelperNode promiseHelper;
 
+    private final ConditionProfile firstPromise = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile promiseCallerProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile nonPromiseProfile = BranchProfile.create();
-    private final BranchProfile promiseCallerProfile = BranchProfile.create();
     private final RPromiseFactory factory;
     private final int wrapIndex;
 
@@ -83,9 +85,11 @@ public final class OptForcedEagerPromiseNode extends PromiseNode {
             nonPromiseProfile.enter();
         }
         RCaller call = RArguments.getCall(frame);
-        while (call.isPromise()) {
-            promiseCallerProfile.enter();
+        if (firstPromise.profile(call.isPromise())) {
             call = call.getParent();
+            while (promiseCallerProfile.profile(call.isPromise())) {
+                call = call.getParent();
+            }
         }
         return factory.createEagerSuppliedPromise(value, alwaysValidAssumption, call, null, wrapIndex);
     }
-- 
GitLab


From 9fe7d0ba62b4f8e3f194c28e937033b30d7d0d93 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Mar 2017 11:22:33 +0100
Subject: [PATCH 252/402] =?UTF-8?q?don=E2=80=99t=20materialize=20in=20Upda?=
 =?UTF-8?q?teDimNames?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index c0f0bca8f3..edaea94aab 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -73,7 +73,7 @@ public abstract class UpdateDimNames extends RBuiltinNode {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVectorNode = insert(CastToVectorNodeGen.create(false));
         }
-        return ((RAbstractVector) castVectorNode.execute(value)).materialize();
+        return ((RAbstractVector) castVectorNode.execute(value));
     }
 
     public abstract RAbstractContainer executeRAbstractContainer(RAbstractContainer container, Object o);
-- 
GitLab


From 5207e957b50bfb04229b54ec5539860dc8332573 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 7 Mar 2017 17:20:34 +0100
Subject: [PATCH 253/402] one-pass intersection for sorted arrays

---
 .../base/fastpaths/IntersectFastPath.java     | 174 +++++++++++++-----
 1 file changed, 130 insertions(+), 44 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java
index 0089dad0f3..5d746b49b9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java
@@ -24,10 +24,13 @@ package com.oracle.truffle.r.nodes.builtin.base.fastpaths;
 
 import java.util.Arrays;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -40,76 +43,157 @@ public abstract class IntersectFastPath extends RFastPathNode {
 
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 
-    @Specialization(limit = "TYPE_LIMIT", guards = {"x.getLength() > 0", "y.getLength() > 0", "x.getClass() == xClass", "y.getClass() == yClass"})
-    protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y,
-                    @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass,
-                    @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass,
-                    @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile,
-                    @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile,
-                    @Cached("createBinaryProfile()") ConditionProfile resultLengthMatchProfile) {
-        // apply the type profiles:
-        RAbstractIntVector profiledX = xClass.cast(x);
-        RAbstractIntVector profiledY = yClass.cast(y);
+    protected static final class IntersectSortedNode extends Node {
 
-        int xLength = profiledX.getLength();
-        int yLength = profiledY.getLength();
-        RBaseNode.reportWork(this, xLength + yLength);
+        private final boolean isSorted;
 
-        int count = 0;
-        int[] result = EMPTY_INT_ARRAY;
-        int maxResultLength = Math.min(xLength, yLength);
-        if (isXSortedProfile.profile(isSorted(profiledX))) {
-            RAbstractIntVector tempY;
-            if (isYSortedProfile.profile(isSorted(profiledY))) {
-                tempY = profiledY;
-            } else {
-                int[] temp = new int[yLength];
-                for (int i = 0; i < yLength; i++) {
-                    temp[i] = profiledY.getDataAt(i);
-                }
-                sort(temp);
-                tempY = RDataFactory.createIntVector(temp, profiledY.isComplete());
-            }
+        private final ConditionProfile resizeProfile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile valueEqualsProfile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile valueSmallerProfile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile exit1Profile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile exit2Profile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile exit3Profile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile exit4Profile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile exit5Profile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile exit6Profile = ConditionProfile.createCountingProfile();
+        private final ConditionProfile resultLengthMatchProfile = ConditionProfile.createBinaryProfile();
+
+        protected IntersectSortedNode(boolean isSorted) {
+            this.isSorted = isSorted;
+        }
+
+        @Override
+        public NodeCost getCost() {
+            return NodeCost.NONE;
+        }
+
+        private int[] execute(RAbstractIntVector x, int xLength, int yLength, RAbstractIntVector y) {
+            int[] result = EMPTY_INT_ARRAY;
+            int maxResultLength = Math.min(xLength, yLength);
+            int count = 0;
             int xPos = 0;
             int yPos = 0;
-            int xValue = profiledX.getDataAt(xPos);
-            int yValue = tempY.getDataAt(yPos);
+            int xValue = x.getDataAt(xPos);
+            int yValue = y.getDataAt(yPos);
             while (true) {
-                if (xValue == yValue) {
-                    if (count >= result.length) {
+                if (valueEqualsProfile.profile(xValue == yValue)) {
+                    if (resizeProfile.profile(count >= result.length)) {
                         result = Arrays.copyOf(result, Math.min(maxResultLength, Math.max(result.length * 2, 8)));
                     }
                     result[count++] = xValue;
                     // advance over similar entries
                     while (true) {
-                        if (xPos >= xLength - 1) {
+                        if (exit1Profile.profile(xPos >= xLength - 1)) {
                             break;
                         }
-                        int nextValue = profiledX.getDataAt(xPos + 1);
-                        if (xValue != nextValue) {
+                        int nextValue = x.getDataAt(xPos + 1);
+                        if (exit2Profile.profile(xValue != nextValue)) {
                             break;
                         }
                         xPos++;
                         xValue = nextValue;
                     }
-                    if (++xPos >= xLength || ++yPos >= yLength) {
+                    if (exit3Profile.profile(++xPos >= xLength) || exit4Profile.profile(++yPos >= yLength)) {
                         break;
                     }
-                    xValue = profiledX.getDataAt(xPos);
-                    yValue = tempY.getDataAt(yPos);
-                } else if (xValue < yValue) {
-                    if (++xPos >= xLength) {
+                    xValue = getNextValue(x, xPos, xValue);
+                    yValue = getNextValue(y, yPos, yValue);
+                } else if (valueSmallerProfile.profile(xValue < yValue)) {
+                    if (exit5Profile.profile(++xPos >= xLength)) {
                         break;
                     }
-                    xValue = profiledX.getDataAt(xPos);
+                    xValue = getNextValue(x, xPos, xValue);
                 } else {
-                    if (++yPos >= yLength) {
+                    if (exit6Profile.profile(++yPos >= yLength)) {
                         break;
                     }
-                    yValue = tempY.getDataAt(yPos);
+                    yValue = getNextValue(y, yPos, yValue);
+                }
+            }
+            if (!isSorted) {
+                // check remaining array entries
+                while (++xPos < xLength) {
+                    xValue = getNextValue(x, xPos, xValue);
                 }
+                while (++yPos < yLength) {
+                    yValue = getNextValue(y, yPos, yValue);
+                }
+            }
+            return resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count);
+        }
+
+        private int getNextValue(RAbstractIntVector vector, int pos, int oldValue) {
+            int newValue = vector.getDataAt(pos);
+            if (!isSorted && newValue < oldValue) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                throw new IllegalArgumentException();
+            }
+            return newValue;
+        }
+    }
+
+    protected static int length(RAbstractIntVector v, Class<? extends RAbstractIntVector> clazz) {
+        return clazz.cast(v).getLength();
+    }
+
+    protected static IntersectSortedNode createMaybeSorted() {
+        return new IntersectSortedNode(false);
+    }
+
+    @Specialization(limit = "TYPE_LIMIT", guards = {"x.getClass() == xClass", "y.getClass() == yClass", "length(x, xClass) > 0", "length(y, yClass) > 0"}, rewriteOn = IllegalArgumentException.class)
+    protected RAbstractIntVector intersectMaybeSorted(RAbstractIntVector x, RAbstractIntVector y,
+                    @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass,
+                    @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass,
+                    @Cached("createMaybeSorted()") IntersectSortedNode intersect) {
+        // apply the type profiles:
+        RAbstractIntVector profiledX = xClass.cast(x);
+        RAbstractIntVector profiledY = yClass.cast(y);
+
+        int xLength = profiledX.getLength();
+        int yLength = profiledY.getLength();
+        RBaseNode.reportWork(this, xLength + yLength);
+
+        int[] result = intersect.execute(profiledX, xLength, yLength, profiledY);
+        return RDataFactory.createIntVector(result, profiledX.isComplete() | profiledY.isComplete());
+    }
+
+    protected static IntersectSortedNode createSorted() {
+        return new IntersectSortedNode(true);
+    }
+
+    @Specialization(limit = "TYPE_LIMIT", guards = {"x.getClass() == xClass", "y.getClass() == yClass", "length(x, xClass) > 0", "length(y, yClass) > 0"})
+    protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y,
+                    @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass,
+                    @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass,
+                    @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile resultLengthMatchProfile,
+                    @Cached("createSorted()") IntersectSortedNode intersect) {
+        // apply the type profiles:
+        RAbstractIntVector profiledX = xClass.cast(x);
+        RAbstractIntVector profiledY = yClass.cast(y);
+
+        int xLength = profiledX.getLength();
+        int yLength = profiledY.getLength();
+        RBaseNode.reportWork(this, xLength + yLength);
+
+        int[] result;
+        if (isXSortedProfile.profile(isSorted(profiledX))) {
+            RAbstractIntVector tempY;
+            if (isYSortedProfile.profile(isSorted(profiledY))) {
+                tempY = profiledY;
+            } else {
+                int[] temp = new int[yLength];
+                for (int i = 0; i < yLength; i++) {
+                    temp[i] = profiledY.getDataAt(i);
+                }
+                sort(temp);
+                tempY = RDataFactory.createIntVector(temp, profiledY.isComplete());
             }
+            result = intersect.execute(profiledX, xLength, yLength, tempY);
         } else {
+            result = EMPTY_INT_ARRAY;
+            int maxResultLength = Math.min(xLength, yLength);
             int[] temp = new int[yLength];
             boolean[] used = new boolean[yLength];
             for (int i = 0; i < yLength; i++) {
@@ -117,6 +201,7 @@ public abstract class IntersectFastPath extends RFastPathNode {
             }
             sort(temp);
 
+            int count = 0;
             for (int i = 0; i < xLength; i++) {
                 int value = profiledX.getDataAt(i);
                 int pos = Arrays.binarySearch(temp, value);
@@ -128,8 +213,9 @@ public abstract class IntersectFastPath extends RFastPathNode {
                     result[count++] = value;
                 }
             }
+            result = resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count);
         }
-        return RDataFactory.createIntVector(resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count), profiledX.isComplete() | profiledY.isComplete());
+        return RDataFactory.createIntVector(result, profiledX.isComplete() | profiledY.isComplete());
     }
 
     private static boolean isSorted(RAbstractIntVector vector) {
-- 
GitLab


From 093dbbede47761c1be264f35b9d40864dd56b038 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 6 Apr 2017 13:20:20 +0200
Subject: [PATCH 254/402] do not treat sep as regex in Scan

---
 .../truffle/r/nodes/builtin/base/Scan.java    |  9 +++--
 .../truffle/r/test/ExpectedTestOutput.test    | 34 +++++++++++++++++++
 .../r/test/builtins/TestBuiltin_scan.java     |  3 ++
 3 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 4e90a9dd39..027d3087c4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -29,6 +29,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import java.io.IOException;
 import java.util.LinkedList;
+import java.util.regex.Pattern;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -79,6 +80,7 @@ public abstract class Scan extends RBuiltinNode {
         RAbstractStringVector naStrings = null;
         boolean quiet = false;
         String sepchar = null;
+        String sepregex = null;
         char decchar = '.';
         String quoteset = null;
         int comchar = NO_COMCHAR;
@@ -150,6 +152,7 @@ public abstract class Scan extends RBuiltinNode {
 
         // TODO: some sort of character translation happens here?
         data.sepchar = sep.isEmpty() ? null : sep.substring(0, 1);
+        data.sepregex = sep.isEmpty() ? null : Pattern.quote(sep.substring(0, 1));
 
         // TODO: some sort of character translation happens here?
         data.decchar = dec.charAt(0);
@@ -248,7 +251,7 @@ public abstract class Scan extends RBuiltinNode {
                 // first iteration
                 if (quoteInd == -1) {
                     // no quotes at all
-                    return data.sepchar == null ? s.split("\\s+") : s.split(data.sepchar);
+                    return data.sepregex == null ? s.split("\\s+") : s.split(data.sepregex);
                 } else {
                     sb = new StringBuilder();
                 }
@@ -272,7 +275,7 @@ public abstract class Scan extends RBuiltinNode {
                 assert sepInd >= 0;
                 // everything from the beginning of str becomes part of this time and item
                 // processing is completed (also eat up separators)
-                String[] tuple = data.sepchar == null ? str.split("\\s+", 2) : str.split(data.sepchar, 2);
+                String[] tuple = data.sepregex == null ? str.split("\\s+", 2) : str.split(data.sepregex, 2);
                 assert tuple.length == 2;
                 sb.append(tuple[0]);
                 str = tuple[1];
@@ -295,7 +298,7 @@ public abstract class Scan extends RBuiltinNode {
                     continue;
                 } else {
                     if (data.quoteset.length() == 0) {
-                        return data.sepchar == null ? s.split("\\s+") : s.split(data.sepchar);
+                        return data.sepregex == null ? s.split("\\s+") : s.split(data.sepregex);
                     } else {
                         return getQuotedItems(data, s);
                     }
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 4a91d4b30c..53e044ed1e 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
@@ -47286,6 +47286,34 @@ attr(,"useBytes")
 #rep(x<-42)
 [1] 42
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 1)
+asdf
+   1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; names(v) <- 'asdf'; rep(v, 2)
+asdf asdf
+   1    1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; rep(v, 1)
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; class(v) <- 'asdf'; rep(v, 2)
+[1] 1 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; names(v) <- 'asdf'; rep(v, 1)
+asdf
+   1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#v <- 1; names(v) <- 'asdf'; rep(v, 2)
+asdf asdf
+   1    1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
 #{ rep("hello", 3) }
 [1] "hello" "hello" "hello"
@@ -49190,6 +49218,12 @@ Error: invalid 'what' argument
 #{ con<-textConnection(c("1.5 2.89 3", "4 5 6")); .Internal(scan(con, 1.2, 2, ' ', NULL, '"', 0, 3, "NA", F, F, F, T, T, '', '#', T, 'utf8', F)) }
 [1] 1.50 2.89
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#
+#con <- textConnection("A|B|C\n1|2|3\n4|5|6"); read.csv(con, sep="|")
+  A B C
+1 1 2 3
+2 4 5 6
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_scan.testScan#
 #{ con<-textConnection(c("'foo'")); scan(con, what=list("")) }
 Read 1 record
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
index 7f9cf822a1..fd9a88eff6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java
@@ -48,6 +48,9 @@ public class TestBuiltin_scan extends TestBase {
         assertEval("{ con<-textConnection(c(\"bar'foo'\")); scan(con, what=list(\"\")) }");
         assertEval("{ con<-textConnection(c(\"'foo'\")); scan(con, what=list(\"\")) }");
         assertEval("{ con<-textConnection(c(\"bar 'foo'\")); scan(con, what=list(\"\")) }");
+
+        // sep should not be treated as a regex:
+        assertEval("con <- textConnection(\"A|B|C\\n1|2|3\\n4|5|6\"); read.csv(con, sep=\"|\")");
     }
 
     @Test
-- 
GitLab


From b95419f8a8ee4a085756bfad52076257c954a23e Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 1 Mar 2017 14:40:58 +0100
Subject: [PATCH 255/402] =?UTF-8?q?simplifications=20in=20cast=20pipelines?=
 =?UTF-8?q?=20(don=E2=80=99t=20recreate=20cast=20builders)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../r/nodes/test/PipelineToCastNodeTests.java |  5 +-
 .../builtin/casts/PipelineToCastNode.java     |  8 ++-
 .../analysis/ForwardingAnalysisResult.java    |  4 +-
 .../casts/fluent/CoercedPhaseBuilder.java     |  3 +-
 .../casts/fluent/HeadPhaseBuilder.java        | 31 ++++++------
 .../casts/fluent/InitialPhaseBuilder.java     | 31 ++++++------
 .../builtin/casts/fluent/PipelineBuilder.java | 23 +++------
 .../casts/fluent/PreinitialPhaseBuilder.java  | 50 ++++++++++---------
 8 files changed, 75 insertions(+), 80 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
index a719c9d363..444a877bf6 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
@@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.test;
 import static junit.framework.TestCase.assertTrue;
 import static org.junit.Assert.assertEquals;
 
-import java.util.Optional;
-
 import org.junit.Test;
 
 import com.oracle.truffle.r.nodes.builtin.casts.Filter.TypeFilter;
@@ -35,6 +33,7 @@ import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.CoercionStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FilterStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineStep.FindFirstStep;
 import com.oracle.truffle.r.nodes.builtin.casts.PipelineToCastNode;
+import com.oracle.truffle.r.nodes.builtin.casts.analysis.ForwardingAnalysisResult;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder;
 import com.oracle.truffle.r.nodes.unary.CastIntegerBaseNode;
 import com.oracle.truffle.r.nodes.unary.CastLogicalBaseNode;
@@ -85,6 +84,6 @@ public class PipelineToCastNodeTests {
     private static CastNode createPipeline(PipelineStep<?, ?> lastStep) {
         PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x");
         configBuilder.setValueForwarding(false);
-        return PipelineToCastNode.convert(configBuilder.build(), lastStep, Optional.empty());
+        return PipelineToCastNode.convert(configBuilder.build(), lastStep, ForwardingAnalysisResult.INVALID);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 1a2e496913..15f80bdb96 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts;
 
-import java.util.Optional;
 import java.util.function.Supplier;
 
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
@@ -106,7 +105,7 @@ public final class PipelineToCastNode {
         // nop: static class
     }
 
-    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStepIn, Optional<ForwardingAnalysisResult> fwdAnalysisResult) {
+    public static CastNode convert(PipelineConfig config, PipelineStep<?, ?> firstStepIn, ForwardingAnalysisResult fwdAnalysisResult) {
         if (firstStepIn == null) {
             return null;
         }
@@ -122,9 +121,8 @@ public final class PipelineToCastNode {
             return originalPipelineFactory.get();
         }
 
-        ForwardingAnalysisResult fwdRes = fwdAnalysisResult.get();
-        if (fwdRes != null && fwdRes.isAnythingForwarded()) {
-            return ValueForwardingNodeGen.create(fwdRes, originalPipelineFactory);
+        if (fwdAnalysisResult.isAnythingForwarded()) {
+            return ValueForwardingNodeGen.create(fwdAnalysisResult, originalPipelineFactory);
         } else {
             return originalPipelineFactory.get();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java
index 0058644d84..c5323e2aea 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/analysis/ForwardingAnalysisResult.java
@@ -41,7 +41,7 @@ public final class ForwardingAnalysisResult {
     public final ForwardingStatus missingForwarded;
     public final boolean invalid;
 
-    static final ForwardingAnalysisResult INVALID = new ForwardingAnalysisResult(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, true);
+    public static final ForwardingAnalysisResult INVALID = new ForwardingAnalysisResult(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, true);
 
     ForwardingAnalysisResult() {
         this(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, false);
@@ -103,7 +103,7 @@ public final class ForwardingAnalysisResult {
     }
 
     public boolean isAnythingForwarded() {
-        return isNullForwarded() || isMissingForwarded() || isIntegerForwarded() || isLogicalForwarded() || isDoubleForwarded() || isComplexForwarded() || isStringForwarded();
+        return !invalid && (isNullForwarded() || isMissingForwarded() || isIntegerForwarded() || isLogicalForwarded() || isDoubleForwarded() || isComplexForwarded() || isStringForwarded());
     }
 
     ForwardingAnalysisResult setForwardedType(Class<?> tp, ForwardingStatus status) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
index b9e980973b..05384ae850 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/CoercedPhaseBuilder.java
@@ -94,7 +94,8 @@ public final class CoercedPhaseBuilder<T extends RAbstractVector, S> extends Arg
         return mustBe(argFilter, null, null, (Object[]) null);
     }
 
+    @SuppressWarnings("unchecked")
     public <R extends T> CoercedPhaseBuilder<R, S> mustBe(Class<R> cls) {
-        return new CoercedPhaseBuilder<R, S>(pipelineBuilder(), elementClass).mustBe(Predef.instanceOf(cls));
+        return (CoercedPhaseBuilder<R, S>) mustBe(Predef.instanceOf(cls));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
index 5402c62bf2..3317318400 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/HeadPhaseBuilder.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.r.runtime.RError;
  * head of a vector. This is the last phase in the pipeline building fluent API and comes after
  * {@link CoercedPhaseBuilder} phase.
  */
+@SuppressWarnings("unchecked")
 public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilder<T>> {
 
     public HeadPhaseBuilder(PipelineBuilder builder) {
@@ -42,57 +43,57 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde
     public <S> HeadPhaseBuilder<S> map(Mapper<T, S> mapFn) {
         // state().castBuilder().insert(state().index(), () -> MapNode.create(mapFn));
         pipelineBuilder().appendMap(mapFn);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<S>) this;
     }
 
     public HeadPhaseBuilder<Object> returnIf(Filter<? super T, ?> argFilter) {
         pipelineBuilder().appendMapIf(argFilter, (PipelineStep<?, ?>) null, (PipelineStep<?, ?>) null, true);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, false);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<T> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, true);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, false);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<S, R> trueBranchMapper, Mapper<T, ?> falseBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, true);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<S, ?> trueBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, false);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<S, ?> trueBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, true);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<S, R> trueBranch, PipelineStep<T, ?> falseBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, false);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> HeadPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<S, R> trueBranch, PipelineStep<T, ?> falseBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, true);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<Object>) this;
     }
 
     public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RError.Message message, Object... messageArgs) {
         pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<S>) this;
     }
 
     public <S extends T> HeadPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter) {
@@ -101,22 +102,22 @@ public final class HeadPhaseBuilder<T> extends ArgCastBuilder<T, HeadPhaseBuilde
 
     public <S extends T> HeadPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) {
         mustBe(Predef.instanceOf(cls), message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<S>) this;
     }
 
     public <S extends T> HeadPhaseBuilder<S> mustBe(Class<S> cls) {
         mustBe(Predef.instanceOf(cls));
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<S>) this;
     }
 
     public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) {
         shouldBe(Predef.instanceOf(cls), message, messageArgs);
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<S>) this;
     }
 
     public <S> HeadPhaseBuilder<S> shouldBe(Class<S> cls) {
         shouldBe(Predef.instanceOf(cls));
-        return new HeadPhaseBuilder<>(pipelineBuilder());
+        return (HeadPhaseBuilder<S>) this;
     }
 
     public HeadPhaseBuilder<T> mustNotBeNA(RError.Message message, Object... messageArgs) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
index 39790fdd69..c66079bf6e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/InitialPhaseBuilder.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  * cast to any specific type yet. Any method that represents casting of the argument to a specific
  * type returns instance of {@link CoercedPhaseBuilder} with its generic parameters set accordingly.
  */
+@SuppressWarnings("unchecked")
 public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilder<T>> {
 
     public InitialPhaseBuilder(PipelineBuilder builder) {
@@ -52,7 +53,7 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
 
     public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter, RError.Message message, Object... messageArgs) {
         pipelineBuilder().appendMustBeStep(argFilter, message, messageArgs);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<S>) this;
     }
 
     public <S extends T> InitialPhaseBuilder<S> mustBe(Filter<? super T, S> argFilter) {
@@ -61,72 +62,72 @@ public class InitialPhaseBuilder<T> extends ArgCastBuilder<T, InitialPhaseBuilde
 
     public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls, RError.Message message, Object... messageArgs) {
         mustBe(Predef.instanceOf(cls), message, messageArgs);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<S>) this;
     }
 
     public <S extends T> InitialPhaseBuilder<S> mustBe(Class<S> cls) {
         mustBe(Predef.instanceOf(cls));
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<S>) this;
     }
 
     public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls, RError.Message message, Object... messageArgs) {
         shouldBe(Predef.instanceOf(cls), message, messageArgs);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<S>) this;
     }
 
     public <S> InitialPhaseBuilder<S> shouldBe(Class<S> cls) {
         shouldBe(Predef.instanceOf(cls));
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<S>) this;
     }
 
     public <S> InitialPhaseBuilder<S> map(Mapper<T, S> mapFn) {
         pipelineBuilder().appendMap(mapFn);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<S>) this;
     }
 
     public InitialPhaseBuilder<Object> returnIf(Filter<? super T, ?> argFilter) {
         pipelineBuilder().appendMapIf(argFilter, (PipelineStep<?, ?>) null, (PipelineStep<?, ?>) null, true);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, false);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, true);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper, Mapper<? super T, ?> falseBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, false);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, Mapper<? super S, R> trueBranchMapper, Mapper<? super T, ?> falseBranchMapper) {
         pipelineBuilder().appendMapIf(argFilter, trueBranchMapper, falseBranchMapper, true);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, false);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, true);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> mapIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, false);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public <S extends T, R> InitialPhaseBuilder<Object> returnIf(Filter<? super T, S> argFilter, PipelineStep<?, ?> trueBranch, PipelineStep<?, ?> falseBranch) {
         pipelineBuilder().appendMapIf(argFilter, trueBranch, falseBranch, true);
-        return new InitialPhaseBuilder<>(pipelineBuilder());
+        return (InitialPhaseBuilder<Object>) this;
     }
 
     public InitialPhaseBuilder<T> mustNotBeNA(RError.Message message, Object... messageArgs) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
index ee2ffc3328..5637486524 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineBuilder.java
@@ -22,9 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicReference;
-
 import com.oracle.truffle.r.nodes.builtin.casts.Filter;
 import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
@@ -52,7 +49,7 @@ public final class PipelineBuilder {
 
     private final PipelineConfigBuilder pcb;
     private ChainBuilder<?> chainBuilder;
-    private final AtomicReference<Optional<ForwardingAnalysisResult>> fwdAnalysisResult = new AtomicReference<>();
+    private volatile ForwardingAnalysisResult fwdAnalysisResult;
 
     public PipelineBuilder(String argumentName) {
         this.pcb = new PipelineConfigBuilder(argumentName);
@@ -139,23 +136,19 @@ public final class PipelineBuilder {
         }
     }
 
-    public Optional<ForwardingAnalysisResult> getFwdAnalysisResult() {
-        Optional<ForwardingAnalysisResult> res = fwdAnalysisResult.get();
+    public ForwardingAnalysisResult getFwdAnalysisResult() {
+        ForwardingAnalysisResult res = fwdAnalysisResult;
         if (res == null) {
             ForwardedValuesAnalyser fwdAnalyser = new ForwardedValuesAnalyser();
             PipelineStep<?, ?> firstStep = getFirstStep();
             if (firstStep == null) {
-                res = Optional.empty();
-            } else {
-                res = Optional.of(fwdAnalyser.analyse(firstStep));
-            }
-            if (fwdAnalysisResult.compareAndSet(null, res)) {
-                return res;
+                res = ForwardingAnalysisResult.INVALID;
             } else {
-                return fwdAnalysisResult.get();
+                res = fwdAnalyser.analyse(firstStep);
             }
-        } else {
-            return res;
+            fwdAnalysisResult = res;
         }
+        assert res != null;
+        return res;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
index 598db1e749..3c959e0bb4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
@@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.casts.fluent;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 
-import java.util.function.Consumer;
-
 import com.oracle.truffle.r.nodes.builtin.casts.Mapper;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.RError;
@@ -48,45 +46,49 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> {
         super(pipelineBuilder);
     }
 
-    public PreinitialPhaseBuilder conf(Consumer<PipelineConfigBuilder> cfgLambda) {
-        cfgLambda.accept(pipelineBuilder().getPipelineConfig());
+    public PreinitialPhaseBuilder allowNull() {
+        returnIf(nullValue());
         return this;
     }
 
-    public InitialPhaseBuilder<Object> allowNull() {
-        return returnIf(nullValue());
-    }
-
-    public InitialPhaseBuilder<Object> mustNotBeNull() {
-        return mustBe(nullValue().not());
+    public PreinitialPhaseBuilder mustNotBeNull() {
+        mustBe(nullValue().not());
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> mustNotBeNull(RError.Message errorMsg, Object... msgArgs) {
-        return mustBe(nullValue().not(), errorMsg, msgArgs);
+    public PreinitialPhaseBuilder mustNotBeNull(RError.Message errorMsg, Object... msgArgs) {
+        mustBe(nullValue().not(), errorMsg, msgArgs);
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> mapNull(Mapper<RNull, ?> mapper) {
-        return mapIf(nullValue(), mapper);
+    public PreinitialPhaseBuilder mapNull(Mapper<RNull, ?> mapper) {
+        mapIf(nullValue(), mapper);
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> allowMissing() {
-        return returnIf(missingValue());
+    public PreinitialPhaseBuilder allowMissing() {
+        returnIf(missingValue());
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> mustNotBeMissing() {
-        return mustBe(missingValue().not());
+    public PreinitialPhaseBuilder mustNotBeMissing() {
+        mustBe(missingValue().not());
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> mustNotBeMissing(RError.Message errorMsg, Object... msgArgs) {
-        return mustBe(missingValue().not(), errorMsg, msgArgs);
+    public PreinitialPhaseBuilder mustNotBeMissing(RError.Message errorMsg, Object... msgArgs) {
+        mustBe(missingValue().not(), errorMsg, msgArgs);
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> mapMissing(Mapper<RMissing, ?> mapper) {
-        return mapIf(missingValue(), mapper);
+    public PreinitialPhaseBuilder mapMissing(Mapper<RMissing, ?> mapper) {
+        mapIf(missingValue(), mapper);
+        return this;
     }
 
-    public InitialPhaseBuilder<Object> allowNullAndMissing() {
-        return returnIf(nullValue().or(missingValue()));
+    public PreinitialPhaseBuilder allowNullAndMissing() {
+        returnIf(nullValue().or(missingValue()));
+        return this;
     }
 
     public PreinitialPhaseBuilder defaultError(RError.Message message, Object... args) {
-- 
GitLab


From da6333b1c9f7ddce74ee25ef6451dd67e6772f3d Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 4 Apr 2017 14:15:52 +0200
Subject: [PATCH 256/402] handle return statements in on.exit expressions

---
 .../function/FunctionDefinitionNode.java      | 17 +++++++++++-----
 .../truffle/r/test/ExpectedTestOutput.test    | 20 +++++++++++--------
 .../r/test/builtins/TestBuiltin_on_exit.java  | 19 +++++++++---------
 3 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 1ac435c5d9..984dce3f21 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -324,12 +324,19 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
                      * We do not need to preserve visibility, since visibility.executeEndOfFunction
                      * was already called.
                      */
-                    for (Object expr : current) {
-                        if (!(expr instanceof RNode)) {
-                            RInternalError.shouldNotReachHere("unexpected type for on.exit entry");
+                    try {
+                        for (Object expr : current) {
+                            if (!(expr instanceof RNode)) {
+                                RInternalError.shouldNotReachHere("unexpected type for on.exit entry");
+                            }
+                            onExitExpressionCache.execute(frame, expr);
+                        }
+                    } catch (ReturnException ex) {
+                        if (returnTopLevelProfile.profile(ex.getTarget() == RArguments.getCall(frame))) {
+                            return ex.getResult();
+                        } else {
+                            throw ex;
                         }
-                        RNode node = (RNode) expr;
-                        onExitExpressionCache.execute(frame, node);
                     }
                 }
             }
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 4a91d4b30c..a110b1a72a 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
@@ -37924,41 +37924,45 @@ NULL
  [1]  1  2  3  4  5  6  7  8  9 10
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit() }; n()
+#f <- function() { on.exit() }; f()
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test")); on.exit(); print("some") }; n()
+#f <- function() { on.exit(print('test')); on.exit(); print('some') }; f()
 [1] "some"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test")); on.exit(print("test2")); print("some") }; n()
+#f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some') }; f()
 [1] "some"
 [1] "test2"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test")); on.exit(print("test2")); print("some"); on.exit() }; n()
+#f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some'); on.exit() }; f()
 [1] "some"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test")); on.exit(print("test2", TRUE)); print("some") }; n()
+#f <- function() { on.exit(print('test')); on.exit(print('test2', TRUE)); print('some') }; f()
 [1] "some"
 [1] "test2"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test")); print("some") }; n()
+#f <- function() { on.exit(print('test')); print('some') }; f()
 [1] "some"
 [1] "test"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test", TRUE)); on.exit(print("test2")); print("some") }; n()
+#f <- function() { on.exit(print('test', TRUE)); on.exit(print('test2')); print('some') }; f()
 [1] "some"
 [1] "test2"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
-#n = function() { on.exit(print("test", TRUE)); print("some") }; n()
+#f <- function() { on.exit(print('test', TRUE)); print('some') }; f()
 [1] "some"
 [1] "test"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_on_exit.testOnExit#
+#f <- function() { on.exit(return(5)); return(1) }; f()
+[1] 5
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testBooleanOperators#
 #as.symbol('*') == '*'
 [1] TRUE
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java
index 569fe28f7c..d9cf000cb8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_on_exit.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -19,13 +19,14 @@ public class TestBuiltin_on_exit extends TestBase {
 
     @Test
     public void testOnExit() {
-        assertEval("n = function() { on.exit(print(\"test\")); print(\"some\") }; n()");
-        assertEval("n = function() { on.exit(print(\"test\", TRUE)); print(\"some\") }; n()");
-        assertEval("n = function() { on.exit(print(\"test\")); on.exit(); print(\"some\") }; n()");
-        assertEval("n = function() { on.exit(print(\"test\")); on.exit(print(\"test2\", TRUE)); print(\"some\") }; n()");
-        assertEval("n = function() { on.exit(print(\"test\")); on.exit(print(\"test2\")); print(\"some\") }; n()");
-        assertEval("n = function() { on.exit(print(\"test\", TRUE)); on.exit(print(\"test2\")); print(\"some\") }; n()");
-        assertEval("n = function() { on.exit(print(\"test\")); on.exit(print(\"test2\")); print(\"some\"); on.exit() }; n()");
-        assertEval("n = function() { on.exit() }; n()");
+        assertEval("f <- function() { on.exit(print('test')); print('some') }; f()");
+        assertEval("f <- function() { on.exit(print('test', TRUE)); print('some') }; f()");
+        assertEval("f <- function() { on.exit(print('test')); on.exit(); print('some') }; f()");
+        assertEval("f <- function() { on.exit(print('test')); on.exit(print('test2', TRUE)); print('some') }; f()");
+        assertEval("f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some') }; f()");
+        assertEval("f <- function() { on.exit(print('test', TRUE)); on.exit(print('test2')); print('some') }; f()");
+        assertEval("f <- function() { on.exit(print('test')); on.exit(print('test2')); print('some'); on.exit() }; f()");
+        assertEval("f <- function() { on.exit() }; f()");
+        assertEval("f <- function() { on.exit(return(5)); return(1) }; f()");
     }
 }
-- 
GitLab


From 15b2d796e5f5fb1fcbdd63aebf8f4e2acb4704f3 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 5 Apr 2017 15:11:22 +0200
Subject: [PATCH 257/402] FastR Grid: implement L_pretty

---
 .../fastrGrid/FastRGridExternalLookup.java    |   2 +
 .../truffle/r/library/fastrGrid/LPretty.java  |  98 +++++++++++
 .../truffle/r/nodes/builtin/base/Pretty.java  | 145 +--------------
 .../truffle/r/runtime/PrettyIntevals.java     | 166 ++++++++++++++++++
 mx.fastr/copyrights/overrides                 |   2 +
 5 files changed, 272 insertions(+), 141 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index 1292153015..daea6bc681 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -89,6 +89,8 @@ public final class FastRGridExternalLookup {
                 return LConvert.create();
             case "L_validUnits":
                 return LValidUnit.create();
+            case "L_pretty":
+                return LPretty.create();
 
             // Viewport management
             case "L_upviewport":
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java
new file mode 100644
index 0000000000..1ff6bb3f11
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java
@@ -0,0 +1,98 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (C) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.PrettyIntevals;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+
+public abstract class LPretty extends RExternalBuiltinNode.Arg1 {
+    static {
+        Casts casts = new Casts(LPretty.class);
+        casts.arg(0).mustBe(numericValue()).asDoubleVector();
+    }
+
+    public static LPretty create() {
+        return LPrettyNodeGen.create();
+    }
+
+    @Specialization
+    protected Object doPretty(RAbstractDoubleVector scale) {
+        double min = scale.getLength() > 0 ? scale.getDataAt(0) : 0;
+        double max = scale.getLength() > 1 ? scale.getDataAt(1) : 0;
+        boolean swap = max < min;
+        if (swap) {
+            min = max;
+            max = scale.getDataAt(0);
+        }
+
+        if (Double.isInfinite(min) || Double.isInfinite(max)) {
+            throw error(Message.GENERIC, String.format("infinite axis extents [GEPretty(%g,%g,5)]", min, max));
+        }
+
+        double[] ns = new double[]{min};
+        double[] nu = new double[]{max};
+        int[] ndiv = new int[]{5};
+        double unit = PrettyIntevals.pretty(getErrorContext(), ns, nu, new int[]{5}, 1, 0.25, new double[]{.8, 1.7}, 2, false);
+
+        if (nu[0] >= ns[0] + 1) {
+            if (ns[0] * unit < min - 1e-7 * unit) {
+                ns[0]++;
+            }
+            if (nu[0] > ns[0] + 1 && nu[0] * unit > max + 1e-7 * unit) {
+                nu[0]--;
+            }
+            ndiv[0] = (int) (nu[0] - ns[0]);
+        }
+        min = ns[0] * unit;
+        max = nu[0] * unit;
+
+        if (swap) {
+            double temp = min;
+            min = max;
+            max = temp;
+        }
+        return createAtVector(min, max, ndiv[0]);
+    }
+
+    private static RAbstractDoubleVector createAtVector(double axp0, double axp1, double axp2) {
+        /*
+         * Create an 'at = ...' vector for axis(.) i.e., the vector of tick mark locations, when
+         * none has been specified (= default).
+         *
+         * axp[0:2] = (x1, x2, nInt), where x1..x2 are the extreme tick marks {unless in log case,
+         * where nInt \in {1,2,3 ; -1,-2,....} and the `nint' argument is used *instead*.} The
+         * resulting REAL vector must have length >= 1, ideally >= 2
+         *
+         * FastR Notes: we only implement case where logflag == false.
+         */
+        /* --- linear axis --- Only use axp[] arg. */
+        int n = (int) (fabs(axp2) + 0.25); /* >= 0 */
+        int dn = Math.max(1, n);
+        double rng = axp1 - axp0;
+        double small = fabs(rng) / (100. * dn);
+        double[] at = new double[n + 1];
+        for (int i = 0; i <= n; i++) {
+            at[i] = axp0 + ((double) i / dn) * rng;
+            if (fabs(at[i]) < small) {
+                at[i] = 0;
+            }
+        }
+        return RDataFactory.createDoubleVector(at, RDataFactory.COMPLETE_VECTOR);
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
index 52f90c316f..01bdd569f5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
@@ -22,6 +22,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.PrettyIntevals;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -46,6 +47,8 @@ public abstract class Pretty extends RBuiltinNode {
         casts.arg("eps.correct").defaultError(RError.Message.GENERIC, "'eps.correct' must be 0, 1, or 2").asIntegerVector().findFirst().mustNotBeNA().mustBe(and(gte0(), lte(2)));
     }
 
+    public abstract RList execute(double l, double u, int n, int minN, double shrinkSml, RAbstractDoubleVector hi, int epsCorrect);
+
     @Specialization
     protected RList pretty(double l, double u, int n, int minN, double shrinkSml, RAbstractDoubleVector hi, int epsCorrect) {
         double hi0 = hi.getDataAt(0);
@@ -60,151 +63,11 @@ public abstract class Pretty extends RBuiltinNode {
         double[] lo = new double[]{l};
         double[] up = new double[]{u};
         int[] ndiv = new int[]{n};
-        rPretty(lo, up, ndiv, minN, shrinkSml, hi.materialize().getDataWithoutCopying(), epsCorrect, true);
+        PrettyIntevals.pretty(getErrorContext(), lo, up, ndiv, minN, shrinkSml, hi.materialize().getDataWithoutCopying(), epsCorrect, true);
         Object[] data = new Object[3];
         data[0] = lo[0];
         data[1] = up[0];
         data[2] = ndiv[0];
         return RDataFactory.createList(data, NAMES);
     }
-
-    double rPretty(double[] lo, double[] up, int[] ndiv, int minN,
-                    double shrinkSml, double[] highUFact,
-                    int epsCorrection, boolean returnBounds) {
-        /*
-         * From version 0.65 on, we had rounding_eps := 1e-5, before, r..eps = 0 1e-7 is consistent
-         * with seq.default()
-         */
-        double roundingEps = 1e-7;
-
-        double h = highUFact[0];
-        double h5 = highUFact[1];
-
-        double dx;
-        double cell;
-        double unit;
-        double base;
-        double uu;
-        double ns;
-        double nu;
-        int k;
-        boolean iSmall;
-
-        dx = up[0] - lo[0];
-        /* cell := "scale" here */
-        if (dx == 0 && up[0] == 0) { /* up == lo == 0 */
-            cell = 1;
-            iSmall = true;
-        } else {
-            cell = Math.max(Math.abs(lo[0]), Math.abs(up[0]));
-            /* uu = upper bound on cell/unit */
-            // uu = (1 + (h5 >= 1.5 * h + .5)) ? 1 / (1 + h) : 1.5 / (1 + h5);
-            // How can above expression ever be zero?
-            uu = 1 / (1 + h);
-            /* added times 3, as several calculations here */
-            iSmall = dx < cell * uu * Math.max(1, ndiv[0]) * RRuntime.EPSILON * 3;
-        }
-
-        /* OLD: cell = FLT_EPSILON+ dx / ndiv[0]; FLT_EPSILON = 1.192e-07 */
-        if (iSmall) {
-            if (cell > 10) {
-                cell = 9 + cell / 10;
-            }
-            cell *= shrinkSml;
-            if (minN > 1) {
-                cell /= minN;
-            }
-        } else {
-            cell = dx;
-            if (ndiv[0] > 1) {
-                cell /= ndiv[0];
-            }
-        }
-
-        if (cell < 20 * Double.MIN_VALUE) {
-            warning(RError.Message.GENERIC, "Internal(pretty()): very small range.. corrected");
-            cell = 20 * Double.MIN_VALUE;
-        } else if (cell * 10 > Double.MAX_VALUE) {
-            warning(RError.Message.GENERIC, "Internal(pretty()): very large range.. corrected");
-            cell = .1 * Double.MAX_VALUE;
-        }
-        /*
-         * NB: the power can be negative and this relies on exact calculation, which glibc's exp10
-         * does not achieve
-         */
-        base = Math.pow(10.0, Math.floor(Math.log10(cell))); /* base <= cell < 10*base */
-
-        /*
-         * unit : from { 1,2,5,10 } * base such that |u - cell| is small, favoring larger (if h > 1,
-         * else smaller) u values; favor '5' more than '2' if h5 > h (default h5 = .5 + 1.5 h)
-         */
-        unit = base;
-        if ((uu = 2 * base) - cell < h * (cell - unit)) {
-            unit = uu;
-            if ((uu = 5 * base) - cell < h5 * (cell - unit)) {
-                unit = uu;
-                if ((uu = 10 * base) - cell < h * (cell - unit)) {
-                    unit = uu;
-                }
-            }
-        }
-        /*
-         * Result: c := cell, u := unit, b := base c in [ 1, (2+ h) /(1+h) ] b ==> u= b c in ( (2+
-         * h)/(1+h), (5+2h5)/(1+h5)] b ==> u= 2b c in ( (5+2h)/(1+h), (10+5h) /(1+h) ] b ==> u= 5b c
-         * in ((10+5h)/(1+h), 10 ) b ==> u=10b
-         *
-         * ===> 2/5 *(2+h)/(1+h) <= c/u <= (2+h)/(1+h)
-         */
-
-        ns = Math.floor(lo[0] / unit + roundingEps);
-        nu = Math.ceil(up[0] / unit - roundingEps);
-        if (epsCorrection != 0 && (epsCorrection > 1 || !iSmall)) {
-            if (lo[0] != 0.) {
-                lo[0] *= (1 - RRuntime.EPSILON);
-            } else {
-                lo[0] = -Double.MIN_VALUE;
-            }
-            if (up[0] != 0.) {
-                up[0] *= (1 + RRuntime.EPSILON);
-            } else {
-                up[0] = +Double.MIN_VALUE;
-            }
-        }
-
-        while (ns * unit > lo[0] + roundingEps * unit) {
-            ns--;
-        }
-
-        while (nu * unit < up[0] - roundingEps * unit) {
-            nu++;
-        }
-
-        k = (int) (0.5 + nu - ns);
-        if (k < minN) {
-            /* ensure that nu - ns == min_n */
-            k = minN - k;
-            if (ns >= 0.) {
-                nu += k / 2;
-                ns -= k / 2 + k % 2; /* ==> nu-ns = old(nu-ns) + min_n -k = min_n */
-            } else {
-                ns -= k / 2;
-                nu += k / 2 + k % 2;
-            }
-            ndiv[0] = minN;
-        } else {
-            ndiv[0] = k;
-        }
-        if (returnBounds) { /* if()'s to ensure that result covers original range */
-            if (ns * unit < lo[0]) {
-                lo[0] = ns * unit;
-            }
-            if (nu * unit > up[0]) {
-                up[0] = nu * unit;
-            }
-        } else {
-            lo[0] = ns;
-            up[0] = nu;
-        }
-        return unit;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java
new file mode 100644
index 0000000000..9ff10b704e
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java
@@ -0,0 +1,166 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2014,  The R Core Team
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.runtime;
+
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+/**
+ * Constructs m "pretty" values which cover the given interval. This code is used in both built-in
+ * {@code pretty} and the grid package.
+ */
+public final class PrettyIntevals {
+    private PrettyIntevals() {
+        // only static members
+    }
+
+    // transcribed from pretty.c
+
+    public static double pretty(RBaseNode errorCtx, double[] lo, double[] up, int[] ndiv, int minN,
+                    double shrinkSml, double[] highUFact,
+                    int epsCorrection, boolean returnBounds) {
+        /*
+         * From version 0.65 on, we had rounding_eps := 1e-5, before, r..eps = 0 1e-7 is consistent
+         * with seq.default()
+         */
+        double roundingEps = 1e-7;
+
+        double h = highUFact[0];
+        double h5 = highUFact[1];
+
+        double dx;
+        double cell;
+        double unit;
+        double base;
+        double uu;
+        double ns;
+        double nu;
+        int k;
+        boolean iSmall;
+
+        dx = up[0] - lo[0];
+        /* cell := "scale" here */
+        if (dx == 0 && up[0] == 0) { /* up == lo == 0 */
+            cell = 1;
+            iSmall = true;
+        } else {
+            cell = Math.max(Math.abs(lo[0]), Math.abs(up[0]));
+            /* uu = upper bound on cell/unit */
+            // uu = (1 + (h5 >= 1.5 * h + .5)) ? 1 / (1 + h) : 1.5 / (1 + h5);
+            // How can above expression ever be zero?
+            uu = 1 / (1 + h);
+            /* added times 3, as several calculations here */
+            iSmall = dx < cell * uu * Math.max(1, ndiv[0]) * RRuntime.EPSILON * 3;
+        }
+
+        /* OLD: cell = FLT_EPSILON+ dx / ndiv[0]; FLT_EPSILON = 1.192e-07 */
+        if (iSmall) {
+            if (cell > 10) {
+                cell = 9 + cell / 10;
+            }
+            cell *= shrinkSml;
+            if (minN > 1) {
+                cell /= minN;
+            }
+        } else {
+            cell = dx;
+            if (ndiv[0] > 1) {
+                cell /= ndiv[0];
+            }
+        }
+
+        if (cell < 20 * Double.MIN_VALUE) {
+            RError.warning(errorCtx, RError.Message.GENERIC, "Internal(pretty()): very small range.. corrected");
+            cell = 20 * Double.MIN_VALUE;
+        } else if (cell * 10 > Double.MAX_VALUE) {
+            RError.warning(errorCtx, RError.Message.GENERIC, "Internal(pretty()): very large range.. corrected");
+            cell = .1 * Double.MAX_VALUE;
+        }
+        /*
+         * NB: the power can be negative and this relies on exact calculation, which glibc's exp10
+         * does not achieve
+         */
+        base = Math.pow(10.0, Math.floor(Math.log10(cell))); /* base <= cell < 10*base */
+
+        /*
+         * unit : from { 1,2,5,10 } * base such that |u - cell| is small, favoring larger (if h > 1,
+         * else smaller) u values; favor '5' more than '2' if h5 > h (default h5 = .5 + 1.5 h)
+         */
+        unit = base;
+        if ((uu = 2 * base) - cell < h * (cell - unit)) {
+            unit = uu;
+            if ((uu = 5 * base) - cell < h5 * (cell - unit)) {
+                unit = uu;
+                if ((uu = 10 * base) - cell < h * (cell - unit)) {
+                    unit = uu;
+                }
+            }
+        }
+        /*
+         * Result: c := cell, u := unit, b := base c in [ 1, (2+ h) /(1+h) ] b ==> u= b c in ( (2+
+         * h)/(1+h), (5+2h5)/(1+h5)] b ==> u= 2b c in ( (5+2h)/(1+h), (10+5h) /(1+h) ] b ==> u= 5b c
+         * in ((10+5h)/(1+h), 10 ) b ==> u=10b
+         *
+         * ===> 2/5 *(2+h)/(1+h) <= c/u <= (2+h)/(1+h)
+         */
+
+        ns = Math.floor(lo[0] / unit + roundingEps);
+        nu = Math.ceil(up[0] / unit - roundingEps);
+        if (epsCorrection != 0 && (epsCorrection > 1 || !iSmall)) {
+            if (lo[0] != 0.) {
+                lo[0] *= (1 - RRuntime.EPSILON);
+            } else {
+                lo[0] = -Double.MIN_VALUE;
+            }
+            if (up[0] != 0.) {
+                up[0] *= (1 + RRuntime.EPSILON);
+            } else {
+                up[0] = +Double.MIN_VALUE;
+            }
+        }
+
+        while (ns * unit > lo[0] + roundingEps * unit) {
+            ns--;
+        }
+
+        while (nu * unit < up[0] - roundingEps * unit) {
+            nu++;
+        }
+
+        k = (int) (0.5 + nu - ns);
+        if (k < minN) {
+            /* ensure that nu - ns == min_n */
+            k = minN - k;
+            if (ns >= 0.) {
+                nu += k / 2;
+                ns -= k / 2 + k % 2; /* ==> nu-ns = old(nu-ns) + min_n -k = min_n */
+            } else {
+                ns -= k / 2;
+                nu += k / 2 + k % 2;
+            }
+            ndiv[0] = minN;
+        } else {
+            ndiv[0] = k;
+        }
+        if (returnBounds) { /* if()'s to ensure that result covers original range */
+            if (ns * unit < lo[0]) {
+                lo[0] = ns * unit;
+            }
+            if (nu * unit > up[0]) {
+                up[0] = nu * unit;
+            }
+        } else {
+            lo[0] = ns;
+            up[0] = nu;
+        }
+        return unit;
+    }
+}
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index a72c103a9a..d5600cf28a 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -185,6 +185,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/L
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java,purdue.copyright
@@ -744,6 +745,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/p
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
-- 
GitLab


From 94ab3e311eb1a47fa0baabb5aac1cf812458e973 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 6 Apr 2017 15:49:40 +0200
Subject: [PATCH 258/402] use profiles in combined tests in cast pipelines

---
 .../builtin/casts/PipelineToCastNode.java     | 67 +++++++++++++++----
 1 file changed, 53 insertions(+), 14 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 1a2e496913..74231dc060 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.casts;
 import java.util.Optional;
 import java.util.function.Supplier;
 
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.builtin.ArgumentFilter;
 import com.oracle.truffle.r.nodes.builtin.ArgumentFilter.ArgumentTypeFilter;
@@ -300,15 +301,43 @@ public final class PipelineToCastNode {
         @Override
         public ArgumentFilter<?, ?> visit(RTypeFilter<?> filter, ArgumentFilter<?, ?> previous) {
             if (filter.getType() == RType.Integer) {
-                return x -> x instanceof Integer || x instanceof RAbstractIntVector;
+                return new ArgumentFilter<Object, Object>() {
+                    private final ConditionProfile profile = ConditionProfile.createBinaryProfile();
+
+                    @Override
+                    public boolean test(Object x) {
+                        return profile.profile(x instanceof Integer) || x instanceof RAbstractIntVector;
+                    }
+                };
             } else if (filter.getType() == RType.Double) {
-                return x -> x instanceof Double || x instanceof RAbstractDoubleVector;
+                return new ArgumentFilter<Object, Object>() {
+                    private final ConditionProfile profile = ConditionProfile.createBinaryProfile();
+
+                    @Override
+                    public boolean test(Object x) {
+                        return profile.profile(x instanceof Double) || x instanceof RAbstractDoubleVector;
+                    }
+                };
             } else if (filter.getType() == RType.Logical) {
-                return x -> x instanceof Byte || x instanceof RAbstractLogicalVector;
+                return new ArgumentFilter<Object, Object>() {
+                    private final ConditionProfile profile = ConditionProfile.createBinaryProfile();
+
+                    @Override
+                    public boolean test(Object x) {
+                        return profile.profile(x instanceof Byte) || x instanceof RAbstractLogicalVector;
+                    }
+                };
             } else if (filter.getType() == RType.Complex) {
                 return x -> x instanceof RAbstractComplexVector;
             } else if (filter.getType() == RType.Character) {
-                return x -> x instanceof String || x instanceof RAbstractStringVector;
+                return new ArgumentFilter<Object, Object>() {
+                    private final ConditionProfile profile = ConditionProfile.createBinaryProfile();
+
+                    @Override
+                    public boolean test(Object x) {
+                        return profile.profile(x instanceof String) || x instanceof RAbstractStringVector;
+                    }
+                };
             } else if (filter.getType() == RType.Raw) {
                 return x -> x instanceof RAbstractRawVector;
             } else {
@@ -326,11 +355,16 @@ public final class PipelineToCastNode {
         public ArgumentFilter<?, ?> visit(AndFilter<?, ?> filter, ArgumentFilter<?, ?> previous) {
             ArgumentFilter leftFilter = filter.getLeft().accept(this, previous);
             ArgumentFilter rightFilter = filter.getRight().accept(this, previous);
-            return (ArgumentTypeFilter<Object, Object>) arg -> {
-                if (!leftFilter.test(arg)) {
-                    return false;
-                } else {
-                    return rightFilter.test(arg);
+            return new ArgumentTypeFilter<Object, Object>() {
+                private final ConditionProfile profile = ConditionProfile.createBinaryProfile();
+
+                @Override
+                public boolean test(Object arg) {
+                    if (profile.profile(leftFilter.test(arg))) {
+                        return rightFilter.test(arg);
+                    } else {
+                        return false;
+                    }
                 }
             };
         }
@@ -340,11 +374,16 @@ public final class PipelineToCastNode {
         public ArgumentFilter<?, ?> visit(OrFilter<?> filter, ArgumentFilter<?, ?> previous) {
             ArgumentFilter leftFilter = filter.getLeft().accept(this, previous);
             ArgumentFilter rightFilter = filter.getRight().accept(this, previous);
-            return (ArgumentTypeFilter<Object, Object>) arg -> {
-                if (leftFilter.test(arg)) {
-                    return true;
-                } else {
-                    return rightFilter.test(arg);
+            return new ArgumentTypeFilter<Object, Object>() {
+                private final ConditionProfile profile = ConditionProfile.createBinaryProfile();
+
+                @Override
+                public boolean test(Object arg) {
+                    if (profile.profile(leftFilter.test(arg))) {
+                        return true;
+                    } else {
+                        return rightFilter.test(arg);
+                    }
                 }
             };
         }
-- 
GitLab


From 27f6a722afa8c1ff1590a511960334113658228b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 6 Apr 2017 15:05:28 +0200
Subject: [PATCH 259/402] Fixes in switch corner-cases behavior

---
 .../truffle/r/nodes/builtin/base/Switch.java  | 64 ++++++++++++-------
 .../truffle/r/test/ExpectedTestOutput.test    | 25 ++++++++
 .../r/test/builtins/TestBuiltin_switch.java   | 12 +++-
 3 files changed, 77 insertions(+), 24 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
index c3e59f1710..af0650a456 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
@@ -11,6 +11,12 @@
 
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -24,17 +30,18 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
 import com.oracle.truffle.r.nodes.function.RMissingHelper;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
-import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
-import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 /**
  * The {@code switch} builtin. When called directly, the "..." arguments are not evaluated before
@@ -47,7 +54,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 @RBuiltin(name = "switch", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"EXPR", "..."}, nonEvalArgs = 1, behavior = COMPLEX)
 public abstract class Switch extends RBuiltinNode {
 
-    @Child private CastIntegerNode castIntNode;
     @Child private PromiseCheckHelperNode promiseHelper = new PromiseCheckHelperNode();
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
@@ -60,24 +66,45 @@ public abstract class Switch extends RBuiltinNode {
     private final ConditionProfile noAlternativesProfile = ConditionProfile.createBinaryProfile();
 
     static {
-        Casts.noCasts(Switch.class);
+        // @formatter:off
+        Casts casts = new Casts(Switch.class);
+        // first argument must be list or expression or vector of size 1, if it is not String, cast it to integer
+        casts.arg("EXPR").defaultError(RError.Message.EXPR_NOT_LENGTH_ONE).
+                returnIf(atomicIntegerValue().or(instanceOf(String.class)).or(instanceOf(RExpression.class))).
+                mustBe(abstractVectorValue()).boxPrimitive().mustBe(size(1)).
+                returnIf(stringValue(), findFirst().stringElement()).
+                returnIf(instanceOf(RList.class)).
+                asIntegerVector().findFirst();
+        // @formatter:on
+    }
+
+    // Note: GnuR returns NULL for lists/expressions, even if they contain a signle number, which
+    // could be interpreted as integer
+
+    @Specialization
+    protected Object doSwitchList(VirtualFrame frame, RList list, @SuppressWarnings("unused") RArgsValuesAndNames optionalArgs) {
+        return prepareResult(frame, null);
     }
 
     @Specialization
-    protected Object doSwitch(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) {
-        if (x.getLength() != 1) {
-            throw error(RError.Message.EXPR_NOT_LENGTH_ONE);
+    protected Object doSwitchExpr(VirtualFrame frame, RExpression expr, @SuppressWarnings("unused") RArgsValuesAndNames optionalArgs) {
+        if (expr.getLength() != 1) {
+            throw error(Message.EXPR_NOT_LENGTH_ONE);
         }
+        return prepareResult(frame, null);
+    }
+
+    @Specialization
+    protected Object doSwitch(VirtualFrame frame, String x, RArgsValuesAndNames optionalArgs) {
         return prepareResult(frame, doSwitchString(frame, x, optionalArgs));
     }
 
-    private Object doSwitchString(VirtualFrame frame, RAbstractStringVector x, RArgsValuesAndNames optionalArgs) {
+    private Object doSwitchString(VirtualFrame frame, String xStr, RArgsValuesAndNames optionalArgs) {
         if (noAlternativesProfile.profile(optionalArgs.getLength() == 0)) {
             warning(RError.Message.NO_ALTERNATIVES_IN_SWITCH);
             return null;
         }
         Object[] optionalArgValues = optionalArgs.getArguments();
-        final String xStr = x.getDataAt(0);
         ArgumentsSignature signature = optionalArgs.getSignature();
         for (int i = 0; i < signature.getLength(); i++) {
             final String suppliedArgName = signature.getName(i);
@@ -141,21 +168,12 @@ public abstract class Switch extends RBuiltinNode {
 
     @Specialization
     protected Object doSwitch(VirtualFrame frame, int x, RArgsValuesAndNames optionalArgs) {
-        return prepareResult(frame, doSwitchInt(frame, x, optionalArgs));
-    }
-
-    @Specialization
-    protected Object doSwitch(VirtualFrame frame, Object x, RArgsValuesAndNames optionalArgs) {
-        if (castIntNode == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            castIntNode = insert(CastIntegerNodeGen.create(false, false, false));
-        }
-        Object objIndex = castIntNode.execute(x);
-        if (!(objIndex instanceof Integer)) {
+        if (RRuntime.isNA(x)) {
+            // cast pipeline gives us NA for non-integer value
             notIntType.enter();
-            return null;
+            return prepareResult(frame, null);
         }
-        return prepareResult(frame, doSwitchInt(frame, (int) objIndex, optionalArgs));
+        return prepareResult(frame, doSwitchInt(frame, x, optionalArgs));
     }
 
     @SuppressWarnings("unused")
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 53e044ed1e..8d8ab23053 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
@@ -68474,6 +68474,31 @@ Error: duplicate 'switch' defaults: 'v77' and 'v55'
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitch#
 #{switch(4,1,2,z)}
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr#
+#{ switch(quote(a), 1, 2, 3) }
+Error in switch(quote(a), 1, 2, 3) : EXPR must be a length 1 vector
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr#
+#{ x <- switch(NA, 1, 2, 3); x }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr#
+#{ x <- switch(expression(quote(1)), 1, 2, 3); x }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr#
+#{ x <- switch(expression(quote(1), quote(2)), 1, 2, 3); x }
+Error in switch(expression(quote(1), quote(2)), 1, 2, 3) :
+  EXPR must be a length 1 vector
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr#
+#{ x <- switch(list(1,2,3), 1, 2, 3); x }
+Error in switch(list(1, 2, 3), 1, 2, 3) : EXPR must be a length 1 vector
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testSwitchInvalidExpr#
+#{ x <- switch(list(2), 1, 2, 3); x }
+NULL
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_switch.testswitch1#
 #argv <- structure(list('forward', forward = 'posS', reverse = 'negS'),     .Names = c('', 'forward', 'reverse'));do.call('switch', argv)
 [1] "posS"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java
index ba05e9011e..823c928e5a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -50,4 +50,14 @@ public class TestBuiltin_switch extends TestBase {
         assertEval(Output.IgnoreErrorContext, "{ x <- \"!\"; v <- switch(x, v77, \"<=\" =, \"<\" =, \">\" = 99, v55)}");
         assertEval("{ x <- \"!\"; v <- switch(x, \"\"=v77, \"<=\" =, \"<\" =, \">\" = 99, v55)}");
     }
+
+    @Test
+    public void testSwitchInvalidExpr() {
+        assertEval("{ x <- switch(NA, 1, 2, 3); x }");
+        assertEval("{ switch(quote(a), 1, 2, 3) }");
+        assertEval("{ x <- switch(expression(quote(1)), 1, 2, 3); x }");
+        assertEval("{ x <- switch(expression(quote(1), quote(2)), 1, 2, 3); x }");
+        assertEval("{ x <- switch(list(2), 1, 2, 3); x }");
+        assertEval("{ x <- switch(list(1,2,3), 1, 2, 3); x }");
+    }
 }
-- 
GitLab


From 62dd4c7a55e742b4367200f60740c7a8682fabfc Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 6 Apr 2017 17:00:10 +0200
Subject: [PATCH 260/402] Implemented ToString for S4Object.

---
 .../truffle/r/nodes/unary/ToStringNode.java       | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
index c597619ecc..e32163ff72 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
@@ -27,12 +27,15 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RS4Object;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -133,6 +136,18 @@ public abstract class ToStringNode extends RBaseNode {
         return RRuntime.logicalToString(operand);
     }
 
+    @Specialization
+    protected String toString(RS4Object obj, @SuppressWarnings("unused") boolean quotes, String separator) {
+        RStringVector classHierarchy = obj.getClassHierarchy();
+        Object clazz;
+        if (classHierarchy.getLength() > 0) {
+            clazz = toString(classHierarchy.getDataAt(0), true, separator);
+        } else {
+            throw RInternalError.shouldNotReachHere("S4 object has no class");
+        }
+        return String.format("<S4 object of class %s>", clazz);
+    }
+
     @FunctionalInterface
     private interface ElementFunction {
         String apply(int index, boolean quotes, String separator);
-- 
GitLab


From a4d203981a89c99a2061d1c8b24e8601215f5d44 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 6 Apr 2017 17:00:53 +0200
Subject: [PATCH 261/402] Fix: Did not properly increase refCount when
 accessing a slot.

---
 .../src/com/oracle/truffle/r/nodes/builtin/base/Slot.java | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
index b52efc144f..f352c35e80 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.WrapArgumentNode;
+import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RSymbol;
 @RBuiltin(name = "@", kind = PRIMITIVE, parameterNames = {"", ""}, nonEvalArgs = 1, behavior = COMPLEX)
 public abstract class Slot extends RBuiltinNode {
 
+    @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create();
     @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(true);
 
     static {
@@ -69,6 +71,10 @@ public abstract class Slot extends RBuiltinNode {
                     @Cached("createClassProfile()") ValueProfile nameObjProfile) {
         String name = getName(nameObjProfile.profile(nameObj));
         assert Utils.isInterned(name);
-        return accessSlotNode.executeAccess(object, name);
+        Object result = accessSlotNode.executeAccess(object, name);
+
+        // since we give the slot away, we probably have to increase the refCount
+        sharedAttrUpdate.execute(object, result);
+        return result;
     }
 }
-- 
GitLab


From c9d3debb2c1107cc3bfcaac18179ea0f0b25002b Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 22 Feb 2017 17:06:48 +0100
Subject: [PATCH 262/402] fix unsafe child node insertions

---
 .../src/com/oracle/truffle/r/nodes/builtin/base/Args.java  | 3 +++
 .../src/com/oracle/truffle/r/nodes/builtin/base/Bind.java  | 3 +++
 .../oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java   | 3 +++
 .../com/oracle/truffle/r/nodes/objects/ExecuteMethod.java  | 3 +++
 .../com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java  | 7 ++++---
 .../com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java | 2 +-
 6 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
index 3ea1d01a8f..2d8b257bb0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
@@ -72,6 +72,9 @@ public abstract class Args extends RBuiltinNode {
         if (getNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             getNode = insert(GetNodeGen.create());
+        }
+        if (parentFrameNode == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
             parentFrameNode = insert(ParentFrameNodeGen.create());
         }
         return args((RFunction) getNode.execute(frame, funName.getDataAt(0), parentFrameNode.execute(frame, 1), RType.Function.getName(), true));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index acc4e16ed1..991678b692 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -614,6 +614,9 @@ public abstract class Bind extends RBaseNode {
                     if (lookup == null) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
                         lookup = insert(S3FunctionLookupNode.create(false, false));
+                    }
+                    if (getBaseEnv == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
                         getBaseEnv = insert(GetBaseEnvFrameNode.create());
                     }
                     Result r = lookup.execute(frame, type.toString(), clazz, null, frame.materialize(), getBaseEnv.execute());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index e719605f9e..1e7072ac50 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -75,6 +75,9 @@ public class FastRTrace {
             if (topEnv == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 topEnv = insert(TopEnvNodeGen.create());
+            }
+            if (parentFrame == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 parentFrame = insert(ParentFrameNodeGen.create());
             }
             return topEnv.executeBuiltin(frame, parentFrame.execute(frame, 1), RNull.instance);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java
index 636a8b4c95..c7403d171a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java
@@ -40,6 +40,9 @@ final class ExecuteMethod extends RBaseNode {
         if (collectArgs == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             collectArgs = insert(CollectArgumentsNodeGen.create());
+        }
+        if (callMatcher == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
             callMatcher = insert(CallMatcherNode.create(false));
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java
index 8dc96975eb..350638665a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java
@@ -6,7 +6,7 @@
  * Copyright (c) 1995, 1996, 1997  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1995-2014, The R Core Team
  * Copyright (c) 2002-2008, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -81,11 +81,12 @@ public abstract class GetS4DataSlot extends Node {
 
             if (s3Class != null) {
                 if (s3ClassAttrRemove == null) {
-                    assert castToVector == null;
                     CompilerDirectives.transferToInterpreterAndInvalidate();
                     s3ClassAttrRemove = insert(RemoveFixedAttributeNode.create(RRuntime.DOT_S3_CLASS));
+                }
+                if (castToVector == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
                     castToVector = insert(CastToVectorNode.create());
-
                 }
                 s3ClassAttrRemove.execute(obj.initAttributes());
                 setClassAttrNode.execute(obj, castToVector.execute(s3Class));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
index b7b07fc864..1848dcc302 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
@@ -630,8 +630,8 @@ public abstract class BinaryArithmetic extends Operation {
             if (mult == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 mult = insert(new Multiply());
-                cpow2 = insert(new CPow2());
             }
+            ensurePow2();
         }
 
         protected void ensurePow2() {
-- 
GitLab


From b251de1236d5e765580b6a85953c9f88b43bf33c Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 20 Sep 2016 13:05:10 +0200
Subject: [PATCH 263/402] increment/decrement refcount in do.call

---
 .../oracle/truffle/r/nodes/builtin/base/DoCall.java  | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 0c6e143e00..a9ae510c24 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctions.Get;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
 import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode;
+import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -133,7 +134,16 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode
                 }
             }
         }
-        return call.execute(frame, func, new RArgsValuesAndNames(argValues, signature));
+        for (int i = 0; i < argValues.length; i++) {
+            ShareObjectNode.share(argValues[i]);
+        }
+        try {
+            return call.execute(frame, func, new RArgsValuesAndNames(argValues, signature));
+        } finally {
+            for (int i = 0; i < argValues.length; i++) {
+                ShareObjectNode.unshare(argValues[i]);
+            }
+        }
     }
 
     @TruffleBoundary
-- 
GitLab


From 8a9238698e5b6f0c33c77f1b8c190a0bad740dcc Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 5 Apr 2017 17:40:32 +0200
Subject: [PATCH 264/402] do not use Node.clone in Deriv

---
 .../src/com/oracle/truffle/r/library/stats/deriv/Deriv.java    | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
index 36aa408315..d822fac092 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
@@ -443,7 +442,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
     }
 
     static RSyntaxNode cloneElement(RSyntaxElement element) {
-        return (RSyntaxNode) RASTUtils.cloneNode(((RBaseNode) element));
+        return RContext.getASTBuilder().process(element);
     }
 
     private static RBaseNode d(RBaseNode expr, String var) {
-- 
GitLab


From 7250d9b1ca0665d906b92506bf2b164930c8a6dc Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 6 Apr 2017 17:22:57 +0200
Subject: [PATCH 265/402] copyright

---
 .../src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index a9ae510c24..0bd6655ffc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From ad60c4aa56df259f3693a70a5e91830830fd13ae Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 6 Apr 2017 17:23:05 +0200
Subject: [PATCH 266/402] copyright

---
 .../src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 0bd6655ffc..a9ae510c24 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From 147d27444894e489ca3e8f920796dafd5161ecc0 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 8 Mar 2017 10:52:24 +0100
Subject: [PATCH 267/402] change Closures to work on concrete instead of
 abstract types, cleanups in vector hierarchy

---
 .../truffle/r/nodes/builtin/base/Format.java  |   4 -
 .../r/nodes/builtin/base/LogFunctions.java    |  10 +-
 .../truffle/r/nodes/builtin/base/MatMult.java |  14 +-
 .../truffle/r/nodes/builtin/base/Match.java   |  21 +-
 .../truffle/r/nodes/builtin/base/Order.java   |   7 +-
 .../truffle/r/nodes/builtin/base/Rank.java    |   9 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |   3 +-
 .../truffle/r/nodes/builtin/base/Unlist.java  |   4 +-
 .../vector/CachedExtractVectorNode.java       |   2 +-
 .../BinaryMapArithmeticFunctionNode.java      |   4 +-
 .../unary/UnaryArithmeticReduceNode.java      |   4 +-
 .../oracle/truffle/r/runtime/RRuntime.java    |  14 +-
 .../truffle/r/runtime/data/RComplex.java      |   8 +-
 .../r/runtime/data/RComplexVector.java        |  12 +-
 .../truffle/r/runtime/data/RDouble.java       |   8 +-
 .../r/runtime/data/RDoubleSequence.java       |  19 +-
 .../truffle/r/runtime/data/RDoubleVector.java |  18 +-
 .../truffle/r/runtime/data/RExpression.java   |   4 +-
 .../truffle/r/runtime/data/RIntSequence.java  |  15 +-
 .../truffle/r/runtime/data/RIntVector.java    |  18 +-
 .../truffle/r/runtime/data/RInteger.java      |   7 +-
 .../oracle/truffle/r/runtime/data/RList.java  |   4 +-
 .../truffle/r/runtime/data/RListBase.java     |  22 +-
 .../truffle/r/runtime/data/RLogical.java      |   7 +-
 .../r/runtime/data/RLogicalVector.java        |  20 +-
 .../oracle/truffle/r/runtime/data/RRaw.java   |   6 +-
 .../truffle/r/runtime/data/RRawVector.java    |  16 +-
 ...torToListClosure.java => RScalarList.java} |  70 ++++--
 .../truffle/r/runtime/data/RSequence.java     |   9 -
 .../truffle/r/runtime/data/RString.java       |   5 +-
 .../truffle/r/runtime/data/RStringVector.java |  10 +-
 .../truffle/r/runtime/data/RVector.java       | 132 +++-------
 .../r/runtime/data/closures/RClosures.java    | 121 +++++----
 .../closures/RComplexToIntVectorClosure.java  |  49 ----
 .../RComplexToStringVectorClosure.java        |  45 ----
 .../RDoubleToComplexVectorClosure.java        |  48 ----
 .../closures/RDoubleToIntVectorClosure.java   |  49 ----
 .../RDoubleToStringVectorClosure.java         |  45 ----
 .../RFactorToComplexVectorClosure.java        |  76 ------
 .../RFactorToDoubleVectorClosure.java         |  77 ------
 .../closures/RFactorToIntVectorClosure.java   |  78 ------
 .../RFactorToStringVectorClosure.java         |  85 -------
 .../closures/RIntToComplexVectorClosure.java  |  51 ----
 .../closures/RIntToDoubleVectorClosure.java   |  43 ----
 .../closures/RIntToStringVectorClosure.java   |  43 ----
 .../RLogicalToComplexVectorClosure.java       |  51 ----
 .../RLogicalToDoubleVectorClosure.java        |  43 ----
 .../closures/RLogicalToIntVectorClosure.java  |  43 ----
 .../RLogicalToStringVectorClosure.java        |  44 ----
 .../closures/RRawToComplexVectorClosure.java  |  43 ----
 .../closures/RRawToDoubleVectorClosure.java   |  39 ---
 .../data/closures/RRawToIntVectorClosure.java |  39 ---
 .../closures/RRawToStringVectorClosure.java   |  39 ---
 .../closures/RToComplexVectorClosure.java     | 135 +++++++++-
 .../data/closures/RToDoubleVectorClosure.java | 102 +++++++-
 .../data/closures/RToIntVectorClosure.java    | 142 ++++++++++-
 .../data/closures/RToListVectorClosure.java   | 220 +++++++++++++++++
 .../data/closures/RToStringVectorClosure.java | 230 +++++++++++++++++-
 .../data/closures/RToVectorClosure.java       |  72 +++---
 .../truffle/r/runtime/ops/na/NACheck.java     |  10 +-
 60 files changed, 1141 insertions(+), 1427 deletions(-)
 rename com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/{closures/RAbstactVectorToListClosure.java => RScalarList.java} (54%)
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index 15d6c2f6a8..d383f0330e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -21,11 +21,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.base.printer.AnyVectorToStringVectorWriter;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter;
-import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorMetrics;
 import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter;
 import com.oracle.truffle.r.nodes.builtin.base.printer.IntegerVectorPrinter;
 import com.oracle.truffle.r.nodes.builtin.base.printer.LogicalVectorPrinter;
@@ -35,7 +32,6 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 76cea754f0..3bce1da46d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -123,7 +123,7 @@ public class LogFunctions {
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NAProfile naBase) {
             if (naX.isNA(x)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             }
             return logb(RComplex.valueOf(x, 0), base, divNode, naBase);
         }
@@ -133,7 +133,7 @@ public class LogFunctions {
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NAProfile naBase) {
             if (naX.isNA(x)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             }
             return logb(RComplex.valueOf(x, 0), base, divNode, naBase);
         }
@@ -143,7 +143,7 @@ public class LogFunctions {
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NAProfile naBase) {
             if (naX.isNA(x)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             }
             return logb(RComplex.valueOf(x, 0), base, divNode, naBase);
         }
@@ -153,7 +153,7 @@ public class LogFunctions {
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NAProfile naBase) {
             if (naX.isNA(x)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             }
             return logb(x, base, divNode, naBase);
         }
@@ -352,7 +352,7 @@ public class LogFunctions {
 
         private RComplex logb(RComplex x, RComplex base, BinaryMapArithmeticFunctionNode div, NAProfile naBase) {
             if (naBase.isNA(base)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             }
             if (isNaN(base)) {
                 nanProfile.enter();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index 5630ef3dab..d6baac0ef1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -52,7 +52,6 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -604,25 +603,28 @@ public abstract class MatMult extends RBuiltinNode {
 
     @Specialization
     protected RIntVector multiply(RAbstractLogicalVector aOriginal, RAbstractLogicalVector bOriginal,
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return intMultiply(RClosures.createLogicalToIntVector(aOriginal), RClosures.createLogicalToIntVector(bOriginal), aIsMatrix, bIsMatrix);
+        return intMultiply((RAbstractIntVector) aOriginal.castSafe(RType.Integer, isNAProfile), (RAbstractIntVector) bOriginal.castSafe(RType.Integer, isNAProfile), aIsMatrix, bIsMatrix);
     }
 
     // to int
 
     @Specialization
-    protected RIntVector multiply(RAbstractLogicalVector a, RAbstractIntVector b,
+    protected RIntVector multiply(RAbstractLogicalVector aOriginal, RAbstractIntVector b,
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return intMultiply(RClosures.createLogicalToIntVector(a), b, aIsMatrix, bIsMatrix);
+        return intMultiply((RAbstractIntVector) aOriginal.castSafe(RType.Integer, isNAProfile), b, aIsMatrix, bIsMatrix);
     }
 
     @Specialization
-    protected RIntVector multiply(RAbstractIntVector a, RAbstractLogicalVector b,
+    protected RIntVector multiply(RAbstractIntVector a, RAbstractLogicalVector bOriginal,
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                     @Cached("createBinaryProfile()") ConditionProfile aIsMatrix,
                     @Cached("createBinaryProfile()") ConditionProfile bIsMatrix) {
-        return intMultiply(a, RClosures.createLogicalToIntVector(b), aIsMatrix, bIsMatrix);
+        return intMultiply(a, (RAbstractIntVector) bOriginal.castSafe(RType.Integer, isNAProfile), aIsMatrix, bIsMatrix);
     }
 
     // to double
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index e8ba5a9eed..aa14f79e59 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -418,23 +419,27 @@ public abstract class Match extends RBuiltinNode {
         }
 
         @Specialization
-        protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, int nomatch) {
-            return match(RClosures.createLogicalToStringVector(x), table, nomatch);
+        protected RIntVector match(RAbstractLogicalVector x, RAbstractStringVector table, int nomatch,
+                        @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+            return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), table, nomatch);
         }
 
         @Specialization
-        protected RIntVector match(RAbstractRawVector x, RAbstractIntVector table, int nomatch) {
-            return match(RClosures.createRawToStringVector(x), RClosures.createIntToStringVector(table), nomatch);
+        protected RIntVector match(RAbstractRawVector x, RAbstractIntVector table, int nomatch,
+                        @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+            return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), (RAbstractStringVector) table.castSafe(RType.Character, isNAProfile), nomatch);
         }
 
         @Specialization
-        protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch) {
-            return match(RClosures.createIntToStringVector(x), table, nomatch);
+        protected RIntVector match(RAbstractIntVector x, RAbstractStringVector table, int nomatch,
+                        @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+            return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), table, nomatch);
         }
 
         @Specialization
-        protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch) {
-            return match(RClosures.createDoubleToStringVector(x), table, nomatch);
+        protected RIntVector match(RAbstractDoubleVector x, RAbstractStringVector table, int nomatch,
+                        @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
+            return match((RAbstractStringVector) x.castSafe(RType.Character, isNAProfile), table, nomatch);
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index 97359fc05e..d8aebe6acb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -47,7 +48,6 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -183,9 +183,10 @@ public abstract class Order extends RPrecedenceBuiltinNode {
     }
 
     @Specialization(guards = {"oneVec(args)", "isFirstLogicalPrecedence(args)"})
-    Object orderLogical(byte naLast, boolean decreasing, RArgsValuesAndNames args) {
+    Object orderLogical(byte naLast, boolean decreasing, RArgsValuesAndNames args,
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
         Object[] vectors = args.getArguments();
-        RAbstractIntVector v = RClosures.createLogicalToIntVector((RAbstractLogicalVector) castVector(vectors[0]));
+        RAbstractIntVector v = (RAbstractIntVector) castVector(vectors[0]).castSafe(RType.Integer, isNAProfile);
         return executeOrderVector1(v, naLast, decreasing);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
index aa0fff3a30..19ba218041 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
@@ -30,17 +30,19 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.CmpNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.OrderNodeGen.OrderVector1NodeGen;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -89,7 +91,8 @@ public abstract class Rank extends RBuiltinNode {
     }
 
     @Specialization
-    protected Object rank(RAbstractVector xa, int inN, String tiesMethod) {
+    protected Object rank(RAbstractVector xa, int inN, String tiesMethod,
+                    @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
         int n = inN;
         if (n > xa.getLength()) {
             errorProfile.enter();
@@ -110,7 +113,7 @@ public abstract class Rank extends RBuiltinNode {
             indx[i] = i;
         }
         RIntVector indxVec = RDataFactory.createIntVector(indx, RDataFactory.COMPLETE_VECTOR);
-        RAbstractVector x = xa instanceof RAbstractLogicalVector ? RClosures.createLogicalToIntVector((RAbstractLogicalVector) xa) : xa;
+        RAbstractVector x = xa instanceof RAbstractLogicalVector ? xa.castSafe(RType.Integer, isNAProfile) : xa;
         initOrderVector1().execute(indxVec, x, RRuntime.LOGICAL_TRUE, false, rho);
         initOrderCmp();
         int j;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 4e90a9dd39..ec45913d6a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
+import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -521,7 +522,7 @@ public abstract class Scan extends RBuiltinNode {
                 }
             case Complex:
                 if (isNaString(buffer, 0, data)) {
-                    return RRuntime.createComplexNA();
+                    return RComplex.createNA();
                 } else {
                     return RRuntime.string2complexNoCheck(buffer);
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
index 5d2925cfbe..5bb9e1786c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
@@ -714,14 +714,14 @@ public abstract class Unlist extends RBuiltinNode {
         } else if (dataAtAsObject instanceof Double) {
             double result = unlistValueDouble(dataAtAsObject);
             if (RRuntime.isNA(result)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             } else {
                 return RDataFactory.createComplex(result, 0.0);
             }
         } else {
             int result = unlistValueInt(dataAtAsObject);
             if (RRuntime.isNA(result)) {
-                return RRuntime.createComplexNA();
+                return RComplex.createNA();
             } else {
                 return RDataFactory.createComplex(result, 0.0);
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index 3621333404..c6aca41dc8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -466,7 +466,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
         protected void setNames(RVector<?> container, RAbstractStringVector newNames) {
             RStringVector newNames1 = newNames.materialize();
             assert newNames1.getLength() <= container.getLength();
-            assert container.getInternalDimensions() == null;
+            assert container.getDimensions() == null;
             if (container.getAttributes() == null) {
                 // usual case
                 container.initAttributes(RAttributesLayout.createNames(newNames1));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
index 82f194dd2f..ab8aefdb1e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryMapArithmeticFunctionNode.java
@@ -164,7 +164,7 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo
                 // CORNER: Must throw error on modulo operation on complex numbers.
                 throw error(RError.Message.UNIMPLEMENTED_COMPLEX);
             }
-            return RRuntime.createComplexNA();
+            return RComplex.createNA();
         }
         if (rightNACheck.check(right)) {
             if (this.arithmetic instanceof BinaryArithmetic.Pow && left.isZero()) {
@@ -174,7 +174,7 @@ public final class BinaryMapArithmeticFunctionNode extends BinaryMapNAFunctionNo
                 // CORNER: Must throw error on modulo operation on complex numbers.
                 throw error(RError.Message.UNIMPLEMENTED_COMPLEX);
             }
-            return RRuntime.createComplexNA();
+            return RComplex.createNA();
         }
         try {
             RComplex value = arithmetic.op(left.getRealPart(), left.getImaginaryPart(), right.getRealPart(), right.getImaginaryPart());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
index 6b79cd9599..5b66205f4b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
@@ -170,7 +170,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
                     return operand;
                 }
             } else {
-                return na.check(operand) ? RRuntime.createComplexNA() : operand;
+                return na.check(operand) ? RComplex.createNA() : operand;
             }
         } else {
             throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
@@ -350,7 +350,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
                     if (profiledNaRm) {
                         continue;
                     } else {
-                        return RRuntime.createComplexNA();
+                        return RComplex.createNA();
                     }
                 } else {
                     result = arithmetic.op(result.getRealPart(), result.getImaginaryPart(), current.getRealPart(), current.getImaginaryPart());
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index ad2573744b..9d4b1dd7de 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -205,10 +205,6 @@ public class RRuntime {
         return frame;
     }
 
-    public static RComplex createComplexNA() {
-        return RDataFactory.createComplex(COMPLEX_NA_REAL_PART, COMPLEX_NA_IMAGINARY_PART);
-    }
-
     /**
      * Since a distinguished NaN value is used for NA, checking for {@code isNaN} suffices.
      */
@@ -306,7 +302,7 @@ public class RRuntime {
     }
 
     public static RComplex logical2complex(byte value) {
-        return isNA(value) ? createComplexNA() : logical2complexNoCheck(value);
+        return isNA(value) ? RComplex.createNA() : logical2complexNoCheck(value);
     }
 
     public static String logicalToStringNoCheck(byte operand) {
@@ -484,14 +480,14 @@ public class RRuntime {
 
                 return RDataFactory.createComplex(realPart * (negativeReal ? -1 : 1), imaginaryPart * (negativeImaginary ? -1 : 1));
             } catch (NumberFormatException ex) {
-                return createComplexNA();
+                return RComplex.createNA();
             }
         }
     }
 
     @TruffleBoundary
     public static RComplex string2complex(String v) {
-        return isNA(v) ? createComplexNA() : string2complexNoCheck(v);
+        return isNA(v) ? RComplex.createNA() : string2complexNoCheck(v);
     }
 
     @TruffleBoundary
@@ -526,7 +522,7 @@ public class RRuntime {
     }
 
     public static RComplex int2complex(int i) {
-        return isNA(i) ? createComplexNA() : int2complexNoCheck(i);
+        return isNA(i) ? RComplex.createNA() : int2complexNoCheck(i);
     }
 
     public static String intToStringNoCheck(int operand) {
@@ -585,7 +581,7 @@ public class RRuntime {
     }
 
     public static RComplex double2complex(double d) {
-        return isNAorNaN(d) ? createComplexNA() : double2complexNoCheck(d);
+        return isNAorNaN(d) ? RComplex.createNA() : double2complexNoCheck(d);
     }
 
     public static int double2rawIntValue(double operand) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
index dcbcfd1fb1..e928ee140a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -57,9 +57,9 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec
             case Complex:
                 return this;
             case Character:
-                return RClosures.createComplexToStringVector(this);
+                return RString.valueOf(RContext.getRRuntimeASTAccess().encodeComplex(this));
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RScalarList.valueOf(this);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
index 585753ac6f..c075adf537 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -71,9 +71,9 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
             case Complex:
                 return this;
             case Character:
-                return RClosures.createComplexToStringVector(this);
+                return RClosures.createToStringVector(this);
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -106,7 +106,7 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     }
 
     @Override
-    protected boolean internalVerify() {
+    public boolean verify() {
         if (isComplete()) {
             for (double d : data) {
                 if (d == RRuntime.DOUBLE_NA) {
@@ -172,9 +172,9 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
     }
 
     @Override
-    protected RComplexVector internalCopyResized(int size, boolean fillNA) {
+    protected RComplexVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
-        return RDataFactory.createComplexVector(copyResizedData(size, fillNA), isComplete);
+        return RDataFactory.createComplexVector(copyResizedData(size, fillNA), isComplete, dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
index e729e7a1e9..1a034e6bf2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -63,9 +63,9 @@ public final class RDouble extends RScalarVector implements RAbstractDoubleVecto
                 // From 3.3.0 on, only "true" NA values are converted to complex NA
                 return isNAProfile.profile(RRuntime.isNA(value)) ? RComplex.createNA() : RComplex.valueOf(value, 0.0);
             case Character:
-                return RClosures.createDoubleToStringVector(this);
+                return RString.valueOf(RContext.getRRuntimeASTAccess().encodeDouble(value));
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RScalarList.valueOf(this);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
index 71cf88bace..3c928c8607 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
@@ -73,16 +73,16 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
     public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
         // TODO might be possible to implement some of these without closures
         switch (type) {
+            case Integer:
+                return RClosures.createToIntVector(this);
             case Double:
                 return this;
-            case Integer:
-                return RClosures.createDoubleToIntVector(this);
             case Complex:
-                return RClosures.createDoubleToComplexVector(this);
+                return RClosures.createToComplexVector(this);
             case Character:
-                return RClosures.createDoubleToStringVector(this);
+                return RClosures.createToStringVector(this);
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -120,6 +120,15 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
         return RDataFactory.createDoubleVector(data, !(fillNA && size > getLength()));
     }
 
+    @Override
+    public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
+        int size = newDimensions[0] * newDimensions[1];
+        double[] data = new double[size];
+        populateVectorData(data);
+        RDoubleVector.resizeData(data, data, getLength(), fillNA);
+        return RDataFactory.createDoubleVector(data, !(fillNA && size > getLength()), newDimensions);
+    }
+
     @Override
     public RDoubleVector createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createDoubleVector(new double[newLength], newIsComplete);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
index be3aaec3c9..7023ee9876 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,16 +52,16 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     @Override
     public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
         switch (type) {
+            case Integer:
+                return RClosures.createToIntVector(this);
             case Double:
                 return this;
-            case Integer:
-                return RClosures.createDoubleToIntVector(this);
             case Complex:
-                return RClosures.createDoubleToComplexVector(this);
+                return RClosures.createToComplexVector(this);
             case Character:
-                return RClosures.createDoubleToStringVector(this);
+                return RClosures.createToStringVector(this);
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -113,7 +113,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     }
 
     @Override
-    protected boolean internalVerify() {
+    public boolean verify() {
         if (isComplete()) {
             for (double d : data) {
                 if (d == RRuntime.DOUBLE_NA) {
@@ -185,9 +185,9 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     }
 
     @Override
-    protected RDoubleVector internalCopyResized(int size, boolean fillNA) {
+    protected RDoubleVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
-        return RDataFactory.createDoubleVector(copyResizedData(size, fillNA), isComplete);
+        return RDataFactory.createDoubleVector(copyResizedData(size, fillNA), isComplete, dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index 450359f5b7..dd428cc24a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -79,8 +79,8 @@ public final class RExpression extends RListBase implements RAbstractVector {
     }
 
     @Override
-    protected RExpression internalCopyResized(int size, boolean fillNA) {
-        return RDataFactory.createExpression(copyResizedData(size, fillNA));
+    protected RExpression internalCopyResized(int size, boolean fillNA, int[] dimensions) {
+        return RDataFactory.createExpression(copyResizedData(size, fillNA), dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
index 90d5a01501..40a643c725 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
@@ -55,11 +55,11 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
             case Double:
                 return RDataFactory.createDoubleSequence(getStart(), getStride(), getLength());
             case Complex:
-                return RClosures.createIntToComplexVector(this);
+                return RClosures.createToComplexVector(this);
             case Character:
-                return RClosures.createIntToStringVector(this);
+                return RClosures.createToStringVector(this);
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -125,6 +125,15 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
         return RDataFactory.createIntVector(data, !(fillNA && size > getLength()));
     }
 
+    @Override
+    public RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
+        int size = newDimensions[0] * newDimensions[1];
+        int[] data = new int[size];
+        populateVectorData(data);
+        RIntVector.resizeData(data, data, getLength(), fillNA);
+        return RDataFactory.createIntVector(data, !(fillNA && size > getLength()), newDimensions);
+    }
+
     @Override
     public RIntVector createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createIntVector(new int[newLength], newIsComplete);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
index c1a53a35f6..3dcce42962 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,16 +52,16 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
     @Override
     public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
         switch (type) {
-            case Double:
-                return RClosures.createIntToDoubleVector(this);
             case Integer:
                 return this;
+            case Double:
+                return RClosures.createToDoubleVector(this);
             case Complex:
-                return RClosures.createIntToComplexVector(this);
+                return RClosures.createToComplexVector(this);
             case Character:
-                return RClosures.createIntToStringVector(this);
+                return RClosures.createToStringVector(this);
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -118,7 +118,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
     }
 
     @Override
-    protected boolean internalVerify() {
+    public boolean verify() {
         if (isComplete()) {
             for (int x : data) {
                 if (x == RRuntime.INT_NA) {
@@ -184,9 +184,9 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
     }
 
     @Override
-    protected RIntVector internalCopyResized(int size, boolean fillNA) {
+    protected RIntVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
-        return RDataFactory.createIntVector(copyResizedData(size, fillNA), isComplete);
+        return RDataFactory.createIntVector(copyResizedData(size, fillNA), isComplete, dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java
index 33ba1ebd83..3a618e1ff5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -72,9 +71,9 @@ public final class RInteger extends RScalarVector implements RAbstractIntVector
             case Complex:
                 return isNAProfile.profile(isNA()) ? RComplex.createNA() : RComplex.valueOf(value, 0.0);
             case Character:
-                return RClosures.createIntToStringVector(this);
+                return RString.valueOf(RRuntime.intToString(value));
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RScalarList.valueOf(this);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
index 63184283da..781e73dc4a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
@@ -79,8 +79,8 @@ public final class RList extends RListBase implements RAbstractListVector {
     }
 
     @Override
-    protected RList internalCopyResized(int size, boolean fillNA) {
-        return RDataFactory.createList(copyResizedData(size, fillNA));
+    protected RList internalCopyResized(int size, boolean fillNA, int[] dimensions) {
+        return RDataFactory.createList(copyResizedData(size, fillNA), dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
index 9ad1c7c3b1..abd4bf2d47 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.data;
 
 import java.util.Arrays;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListBaseVector;
@@ -92,7 +91,7 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
     }
 
     @Override
-    protected final boolean internalVerify() {
+    public final boolean verify() {
         for (Object item : data) {
             if (item == null) {
                 return false;
@@ -146,25 +145,6 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
         data[toIndex] = other.getDataAtAsObject(fromIndex);
     }
 
-    @TruffleBoundary
-    public final Object getNameAt(int index) {
-        RStringVector names = getNamesFromAttrs();
-        if (names != null && names != null) {
-            String name = names.getDataAt(index);
-            if (name == RRuntime.STRING_NA) {
-                return "$" + RRuntime.NA_HEADER;
-            } else if (name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)) {
-                return "[[" + Integer.toString(index + 1) + "]]";
-            } else if (name.matches("^[a-zA-Z.][a-zA-Z0-9_.]*$")) {
-                return "$" + name;
-            } else {
-                return "$`" + name + "`";
-            }
-        } else {
-            return "[[" + Integer.toString(index + 1) + "]]";
-        }
-    }
-
     /**
      * Note: elements inside lists may be in inconsistent state reference counting wise. You may
      * need to put them into consistent state depending on what you use them for, consult the
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
index 44e432804a..b0a64de5ab 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -67,9 +66,9 @@ public final class RLogical extends RScalarVector implements RAbstractLogicalVec
             case Complex:
                 return isNAProfile.profile(isNA()) ? RComplex.createNA() : RComplex.valueOf(value, 0.0);
             case Character:
-                return RClosures.createLogicalToStringVector(this);
+                return RString.valueOf(RRuntime.logicalToString(value));
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RScalarList.valueOf(this);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
index f35b7730df..fead808381 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,16 +54,16 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
         switch (type) {
             case Logical:
                 return this;
-            case Double:
-                return RClosures.createLogicalToDoubleVector(this);
             case Integer:
-                return RClosures.createLogicalToIntVector(this);
+                return RClosures.createToIntVector(this);
+            case Double:
+                return RClosures.createToDoubleVector(this);
             case Complex:
-                return RClosures.createLogicalToComplexVector(this);
+                return RClosures.createToComplexVector(this);
             case Character:
-                return RClosures.createLogicalToStringVector(this);
+                return RClosures.createToStringVector(this);
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -115,7 +115,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
     }
 
     @Override
-    protected boolean internalVerify() {
+    public boolean verify() {
         if (isComplete()) {
             for (byte b : data) {
                 if (b == RRuntime.LOGICAL_NA) {
@@ -164,9 +164,9 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
     }
 
     @Override
-    protected RLogicalVector internalCopyResized(int size, boolean fillNA) {
+    protected RLogicalVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
-        return RDataFactory.createLogicalVector(copyResizedData(size, fillNA), isComplete);
+        return RDataFactory.createLogicalVector(copyResizedData(size, fillNA), isComplete, dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
index 138c53d057..0c55726d53 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,9 @@ package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -56,7 +56,7 @@ public final class RRaw extends RScalarVector implements RAbstractRawVector {
             case Complex:
                 return RComplex.valueOf(value, 0.0);
             case Character:
-                return RClosures.createRawToStringVector(this);
+                return RString.valueOf(RRuntime.rawToString(this));
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
index 6fdbf806bf..66437ffcea 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,13 +55,13 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
             case Raw:
                 return this;
             case Integer:
-                return RClosures.createRawToIntVector(this);
+                return RClosures.createToIntVector(this);
             case Double:
-                return RClosures.createRawToDoubleVector(this);
+                return RClosures.createToDoubleVector(this);
             case Complex:
-                return RClosures.createRawToComplexVector(this);
+                return RClosures.createToComplexVector(this);
             case Character:
-                return RClosures.createRawToStringVector(this);
+                return RClosures.createToStringVector(this);
             default:
                 return null;
         }
@@ -105,7 +105,7 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
     }
 
     @Override
-    protected boolean internalVerify() {
+    public boolean verify() {
         return true;
     }
 
@@ -161,8 +161,8 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
     }
 
     @Override
-    protected RRawVector internalCopyResized(int size, boolean fillNA) {
-        return RDataFactory.createRawVector(copyResizedData(size, fillNA));
+    protected RRawVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
+        return RDataFactory.createRawVector(copyResizedData(size, fillNA), dimensions);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java
similarity index 54%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java
index ae651a3e46..48e050c17b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RAbstactVectorToListClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarList.java
@@ -20,51 +20,71 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.data.closures;
+package com.oracle.truffle.r.runtime.data;
 
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-/**
- * In converting complex numbers to integers, this closure discards the imaginary parts.
- */
-final class RAbstactVectorToListClosure extends RToVectorClosure implements RAbstractListVector {
+@ValueType
+public final class RScalarList extends RScalarVector implements RAbstractListVector {
+
+    private final Object value;
 
-    RAbstactVectorToListClosure(RAbstractVector vector) {
-        super(vector);
+    private RScalarList(Object value) {
+        this.value = value;
     }
 
-    @Override
-    public Object getDataAtAsObject(int index) {
-        return vector.getDataAtAsObject(index);
+    public static RScalarList valueOf(Object value) {
+        return new RScalarList(value);
     }
 
     @Override
     public Object getDataAt(int index) {
-        return vector.getDataAtAsObject(index);
+        assert index == 0;
+        return value;
+    }
+
+    public Object getValue() {
+        return value;
     }
 
     @Override
-    public RList materialize() {
-        int length = getLength();
-        Object[] result = new Object[length];
-        for (int i = 0; i < length; i++) {
-            Object data = getDataAtAsObject(i);
-            result[i] = data;
+    public RType getRType() {
+        return RType.List;
+    }
+
+    @Override
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+        switch (type) {
+            case List:
+                return this;
+            default:
+                return null;
         }
-        return RDataFactory.createList(result);
     }
 
     @Override
-    public RAbstractVector copyWithNewDimensions(int[] newDimensions) {
-        return materialize().copyWithNewDimensions(newDimensions);
+    public String toString() {
+        return value.toString();
+    }
+
+    @Override
+    public RList materialize() {
+        RList result = RDataFactory.createList(new Object[]{value});
+        MemoryCopyTracer.reportCopying(this, result);
+        return result;
+    }
+
+    @Override
+    public Object getDataAtAsObject(int index) {
+        return getDataAt(index);
     }
 
     @Override
-    public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
-        return RDataFactory.createList(newLength);
+    public boolean isNA() {
+        return false;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
index c8a79d94e8..9c1ca7f7d8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
@@ -182,15 +182,6 @@ public abstract class RSequence implements RAbstractVector {
         return materialize().getNonShared();
     }
 
-    @Override
-    public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
-        // TODO support for higher dimensions
-        assert newDimensions.length == 2;
-        RVector<?> result = copyResized(newDimensions[0] * newDimensions[1], fillNA);
-        result.setDimensions(newDimensions);
-        return result;
-    }
-
     @Override
     public int getTypedValueInfo() {
         return 0;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java
index af3281e0c1..98b4b5653f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@ import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.closures.RClosures;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -54,7 +53,7 @@ public final class RString extends RScalarVector implements RAbstractStringVecto
             case Character:
                 return this;
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RScalarList.valueOf(this);
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
index b4110bd81a..a327638578 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
             case Character:
                 return this;
             case List:
-                return RClosures.createAbstractVectorToListVector(this);
+                return RClosures.createToListVector(this);
             default:
                 return null;
         }
@@ -111,7 +111,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
     }
 
     @Override
-    protected boolean internalVerify() {
+    public boolean verify() {
         if (isComplete()) {
             for (String b : data) {
                 if (b == RRuntime.STRING_NA) {
@@ -166,9 +166,9 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
     }
 
     @Override
-    protected RStringVector internalCopyResized(int size, boolean fillNA) {
+    protected RStringVector internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         boolean isComplete = isComplete() && ((data.length >= size) || !fillNA);
-        return RDataFactory.createStringVector(copyResizedData(size, fillNA ? RRuntime.STRING_NA : null), isComplete);
+        return RDataFactory.createStringVector(copyResizedData(size, fillNA ? RRuntime.STRING_NA : null), isComplete, dimensions);
     }
 
     public RStringVector resizeWithEmpty(int size) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index 0b84bc51a2..5af392c085 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -96,23 +96,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         }
     }
 
-    private RList getDimNamesFromAttrs() {
-        if (attributes == null) {
-            return null;
-        } else {
-            return (RList) attributes.get(RRuntime.DIMNAMES_ATTR_KEY);
-        }
-    }
-
-    private Object getRowNamesFromAttrs() {
-        if (attributes == null) {
-            return null;
-        } else {
-            return attributes.get(RRuntime.ROWNAMES_ATTR_KEY);
-        }
-    }
-
-    protected final RStringVector getNamesFromAttrs() {
+    private RStringVector getNamesFromAttrs() {
         if (attributes == null) {
             return null;
         } else {
@@ -151,10 +135,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return isTemporary() ? getDataWithoutCopying() : getDataCopy();
     }
 
-    public final int[] getInternalDimensions() {
-        return getDimensionsFromAttrs();
-    }
-
     @Override
     public final void setComplete(boolean complete) {
         this.complete = complete;
@@ -203,37 +183,8 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return -1;
     }
 
-    /**
-     * Find the first element in the names list that {@code name} is a prefix of, and return its
-     * index. If there are no names, or none is found, or there are multiple inexact matches, return
-     * -1.
-     */
-    @TruffleBoundary
-    public final int getElementIndexByNameInexact(String name) {
-        if (getNames() == null) {
-            return -1;
-        }
-        boolean oneMatch = false;
-        int match = -1;
-        RStringVector names = getNamesFromAttrs();
-        for (int i = 0; i < names.getLength(); i++) {
-            if (names.getDataAt(i).startsWith(name)) {
-                if (oneMatch) {
-                    return -1;
-                } else {
-                    match = i;
-                    oneMatch = true;
-                }
-            }
-        }
-        return match;
-    }
-
     /**
      * Guarded method that checks whether {@code attributes} is initialized.
-     *
-     * @param attribute
-     * @param value
      */
     private void putAttribute(String attribute, Object value) {
         initAttributes().define(attribute, value);
@@ -292,20 +243,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         }
     }
 
-    /**
-     * Sets names attribute without doing any error checking - to be used sparingly.
-     *
-     * @param newNames
-     */
-    public final void setNamesNoCheck(RStringVector newNames) {
-        if (newNames == null) {
-            removeAttributeMapping(RRuntime.NAMES_ATTR_KEY);
-        } else {
-            putAttribute(RRuntime.NAMES_ATTR_KEY, newNames);
-        }
-        assert newNames != this;
-    }
-
     @Override
     public final void setNames(RStringVector newNames) {
         // TODO pass invoking Node
@@ -338,7 +275,11 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     @Override
     public final RList getDimNames() {
-        return getDimNamesFromAttrs();
+        if (attributes == null) {
+            return null;
+        } else {
+            return (RList) attributes.get(RRuntime.DIMNAMES_ATTR_KEY);
+        }
     }
 
     /**
@@ -409,8 +350,11 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     @Override
     public final Object getRowNames() {
-        Object rn = getRowNamesFromAttrs();
-        return rn == null ? RNull.instance : rn;
+        if (attributes == null) {
+            return RNull.instance;
+        } else {
+            return attributes.get(RRuntime.ROWNAMES_ATTR_KEY);
+        }
     }
 
     @Override
@@ -432,15 +376,15 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return attributes == null ? false : attributes.containsKey(RRuntime.DIM_ATTR_KEY);
     }
 
-    public final boolean hasDimNames() {
+    private boolean hasDimNames() {
         return attributes == null ? false : attributes.containsKey(RRuntime.DIMNAMES_ATTR_KEY);
     }
 
-    public final boolean hasRowNames() {
+    private boolean hasRowNames() {
         return attributes == null ? false : attributes.containsKey(RRuntime.ROWNAMES_ATTR_KEY);
     }
 
-    public final boolean hasNames() {
+    private boolean hasNames() {
         return attributes == null ? false : attributes.containsKey(RRuntime.NAMES_ATTR_KEY);
     }
 
@@ -499,10 +443,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         return setClassAttrInternal(vector, classAttr);
     }
 
-    public abstract class CNode extends RBaseNode {
-
-    }
-
     private static RAbstractContainer setClassAttrInternal(RVector<?> vector, RStringVector classAttr) {
         if (vector.attributes == null && classAttr != null && classAttr.getLength() != 0) {
             vector.initAttributes();
@@ -554,34 +494,39 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     @Override
     public final RVector<ArrayT> copyResized(int size, boolean fillNA) {
-        return internalCopyResizedAndReport(size, fillNA);
+        RVector<ArrayT> result = internalCopyResized(size, fillNA, null);
+        MemoryCopyTracer.reportCopying(this, result);
+        return result;
+    }
+
+    @Override
+    public final RVector<ArrayT> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
+        // TODO support for higher dimensions
+        assert newDimensions.length == 2;
+        RVector<ArrayT> result = internalCopyResized(newDimensions[0] * newDimensions[1], fillNA, newDimensions);
+        MemoryCopyTracer.reportCopying(this, result);
+        return result;
     }
 
     // *internalCopyAndReport* methods do just the copy and report it to MemoryTracer. These should
     // be used if additional logic in public interface *copy* method is not desired.
 
-    protected final RVector<ArrayT> internalCopyAndReport() {
+    private RVector<ArrayT> internalCopyAndReport() {
         RVector<ArrayT> result = internalCopy();
         MemoryCopyTracer.reportCopying(this, result);
         return result;
     }
 
-    protected final RVector<ArrayT> internalDeepCopyAndReport() {
+    private RVector<ArrayT> internalDeepCopyAndReport() {
         RVector<ArrayT> result = internalDeepCopy();
         MemoryCopyTracer.reportCopying(this, result);
         return result;
     }
 
-    protected final RVector<ArrayT> internalCopyResizedAndReport(int size, boolean fillNA) {
-        RVector<ArrayT> result = internalCopyResized(size, fillNA);
-        MemoryCopyTracer.reportCopying(this, result);
-        return result;
-    }
-
     // *internalCopy* methods should only be overridden, but never invoked from anywhere but
     // *internalCopyAndReport*
 
-    protected abstract RVector<ArrayT> internalCopyResized(int size, boolean fillNA);
+    protected abstract RVector<ArrayT> internalCopyResized(int size, boolean fillNA, int[] dimensions);
 
     // to be overridden by recursive structures
     protected RVector<ArrayT> internalDeepCopy() {
@@ -590,20 +535,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     protected abstract RVector<ArrayT> internalCopy();
 
-    @Override
-    public RVector<ArrayT> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
-        // TODO support for higher dimensions
-        assert newDimensions.length == 2;
-        RVector<ArrayT> result = copyResized(newDimensions[0] * newDimensions[1], fillNA);
-        result.setDimensions(newDimensions);
-        return result;
-    }
-
-    public final boolean verify() {
-        return internalVerify();
-    }
-
-    protected abstract boolean internalVerify();
+    public abstract boolean verify();
 
     /**
      * Update a data item in the vector. Possibly not as efficient as type-specific methods, but in
@@ -643,7 +575,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
      * Internal version without profiles used in a rare (and already slow) case of double-to-int
      * vector conversion when setting class attribute
      */
-    protected final RAttributable copyAttributesFromVector(RVector<?> vector) {
+    private RAttributable copyAttributesFromVector(RVector<?> vector) {
         DynamicObject vecAttributes = vector.getAttributes();
         if (vecAttributes != null) {
             initAttributes(RAttributesLayout.copy(vecAttributes));
@@ -791,7 +723,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     private static final int MAX_TOSTRING_LENGTH = 100;
 
-    protected String toString(Function<Integer, String> element) {
+    protected final String toString(Function<Integer, String> element) {
         CompilerAsserts.neverPartOfCompilation();
         StringBuilder str = new StringBuilder("[");
         for (int i = 0; i < getLength(); i++) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
index d16147af06..91dddf4b5f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java
@@ -22,14 +22,20 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
@@ -37,102 +43,135 @@ public class RClosures {
 
     // Logical to ...
 
-    public static RAbstractIntVector createLogicalToIntVector(RAbstractLogicalVector vector) {
+    public static RAbstractIntVector createToIntVector(RLogicalVector vector) {
         return new RLogicalToIntVectorClosure(vector);
     }
 
-    public static RAbstractDoubleVector createLogicalToDoubleVector(RAbstractLogicalVector vector) {
+    public static RAbstractDoubleVector createToDoubleVector(RLogicalVector vector) {
         return new RLogicalToDoubleVectorClosure(vector);
     }
 
-    public static RAbstractComplexVector createLogicalToComplexVector(RAbstractLogicalVector vector) {
+    public static RAbstractComplexVector createToComplexVector(RLogicalVector vector) {
         return new RLogicalToComplexVectorClosure(vector);
     }
 
-    public static RAbstractStringVector createLogicalToStringVector(RAbstractLogicalVector vector) {
+    public static RAbstractStringVector createToStringVector(RLogicalVector vector) {
         return new RLogicalToStringVectorClosure(vector);
     }
 
+    public static RAbstractListVector createToListVector(RLogicalVector vector) {
+        return new RLogicalToListVectorClosure(vector);
+    }
+
     // Int to ...
 
-    public static RAbstractDoubleVector createIntToDoubleVector(RAbstractIntVector vector) {
+    public static RAbstractComplexVector createToComplexVector(RIntSequence vector) {
+        return new RIntSequenceToComplexVectorClosure(vector);
+    }
+
+    public static RAbstractStringVector createToStringVector(RIntSequence vector) {
+        return new RIntSequenceToStringVectorClosure(vector);
+    }
+
+    public static RAbstractListVector createToListVector(RIntSequence vector) {
+        return new RIntSequenceToListVectorClosure(vector);
+    }
+
+    public static RAbstractDoubleVector createToDoubleVector(RIntVector vector) {
         return new RIntToDoubleVectorClosure(vector);
     }
 
-    public static RAbstractComplexVector createIntToComplexVector(RAbstractIntVector vector) {
+    public static RAbstractComplexVector createToComplexVector(RIntVector vector) {
         return new RIntToComplexVectorClosure(vector);
     }
 
-    public static RAbstractStringVector createIntToStringVector(RAbstractIntVector vector) {
+    public static RAbstractStringVector createToStringVector(RIntVector vector) {
         return new RIntToStringVectorClosure(vector);
     }
 
+    public static RAbstractListVector createToListVector(RIntVector vector) {
+        return new RIntToListVectorClosure(vector);
+    }
+
     // Double to ...
 
-    public static RAbstractComplexVector createDoubleToComplexVector(RAbstractDoubleVector vector) {
+    public static RAbstractComplexVector createToComplexVector(RDoubleSequence vector) {
+        return new RDoubleSequenceToComplexVectorClosure(vector);
+    }
+
+    public static RAbstractStringVector createToStringVector(RDoubleSequence vector) {
+        return new RDoubleSequenceToStringVectorClosure(vector);
+    }
+
+    public static RAbstractIntVector createToIntVector(RDoubleSequence vector) {
+        return new RDoubleSequenceToIntVectorClosure(vector);
+    }
+
+    public static RAbstractListVector createToListVector(RDoubleSequence vector) {
+        return new RDoubleSequenceToListVectorClosure(vector);
+    }
+
+    public static RAbstractComplexVector createToComplexVector(RDoubleVector vector) {
         return new RDoubleToComplexVectorClosure(vector);
     }
 
-    public static RAbstractStringVector createDoubleToStringVector(RAbstractDoubleVector vector) {
+    public static RAbstractStringVector createToStringVector(RDoubleVector vector) {
         return new RDoubleToStringVectorClosure(vector);
     }
 
-    public static RAbstractIntVector createDoubleToIntVector(RAbstractDoubleVector vector) {
+    public static RAbstractIntVector createToIntVector(RDoubleVector vector) {
         return new RDoubleToIntVectorClosure(vector);
     }
 
+    public static RAbstractListVector createToListVector(RDoubleVector vector) {
+        return new RDoubleToListVectorClosure(vector);
+    }
+
     // Raw to ...
 
-    public static RAbstractIntVector createRawToIntVector(RAbstractRawVector vector) {
+    public static RAbstractIntVector createToIntVector(RRawVector vector) {
         return new RRawToIntVectorClosure(vector);
     }
 
-    public static RAbstractDoubleVector createRawToDoubleVector(RAbstractRawVector vector) {
+    public static RAbstractDoubleVector createToDoubleVector(RRawVector vector) {
         return new RRawToDoubleVectorClosure(vector);
     }
 
-    public static RAbstractComplexVector createRawToComplexVector(RAbstractRawVector vector) {
+    public static RAbstractComplexVector createToComplexVector(RRawVector vector) {
         return new RRawToComplexVectorClosure(vector);
     }
 
-    public static RAbstractStringVector createRawToStringVector(RAbstractRawVector vector) {
+    public static RAbstractStringVector createToStringVector(RRawVector vector) {
         return new RRawToStringVectorClosure(vector);
     }
 
+    public static RAbstractListVector createToListVector(RRawVector vector) {
+        return new RRawToListVectorClosure(vector);
+    }
+
     // Complex to ...
 
-    public static RAbstractStringVector createComplexToStringVector(RAbstractComplexVector vector) {
+    public static RAbstractStringVector createToStringVector(RComplexVector vector) {
         return new RComplexToStringVectorClosure(vector);
     }
 
-    // Vector to list
+    public static RAbstractListVector createToListVector(RComplexVector vector) {
+        return new RComplexToListVectorClosure(vector);
+    }
+
+    // Character to ...
 
-    public static RAbstractListVector createAbstractVectorToListVector(RAbstractVector vector) {
-        return new RAbstactVectorToListClosure(vector);
+    public static RAbstractListVector createToListVector(RStringVector vector) {
+        return new RStringToListVectorClosure(vector);
     }
 
     // Factor to vector
 
-    public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RVector<?> levels) {
-        if (levels == null) {
-            return new RFactorToStringVectorClosure(factor, null, withNames);
+    public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAbstractVector levels) {
+        if (levels instanceof RAbstractStringVector) {
+            return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames);
         } else {
-            switch (levels.getRType()) {
-                case Integer:
-                    return new RFactorToIntVectorClosure(factor, (RAbstractIntVector) levels, withNames);
-                case Double:
-                    return new RFactorToDoubleVectorClosure(factor, (RAbstractDoubleVector) levels, withNames);
-                case Logical:
-                    return new RFactorToIntVectorClosure(factor, createLogicalToIntVector((RAbstractLogicalVector) levels), withNames);
-                case Complex:
-                    return new RFactorToComplexVectorClosure(factor, (RAbstractComplexVector) levels, withNames);
-                case Character:
-                    return new RFactorToStringVectorClosure(factor, (RAbstractStringVector) levels, withNames);
-                case Raw:
-                    return new RFactorToIntVectorClosure(factor, createRawToIntVector((RAbstractRawVector) levels), withNames);
-                default:
-                    throw RInternalError.shouldNotReachHere();
-            }
+            throw RError.error(RError.SHOW_CALLER, Message.MALFORMED_FACTOR);
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java
deleted file mode 100644
index 549c0338dc..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToIntVectorClosure.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-
-/**
- * In converting complex numbers to integers, this closure discards the imaginary parts.
- */
-final class RComplexToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
-
-    RComplexToIntVectorClosure(RAbstractComplexVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public int getDataAt(int index) {
-        RComplex right = ((RAbstractComplexVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(right)) {
-            return RRuntime.INT_NA;
-        }
-        RError.warning(RError.SHOW_CALLER2, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
-        return RRuntime.complex2intNoCheck(right);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java
deleted file mode 100644
index 136d4e7653..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RComplexToStringVectorClosure.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-final class RComplexToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector {
-
-    RComplexToStringVectorClosure(RAbstractComplexVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public String getDataAt(int index) {
-        RComplex data = ((RAbstractComplexVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.STRING_NA;
-        }
-        return RContext.getRRuntimeASTAccess().encodeComplex(data);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java
deleted file mode 100644
index 6b9b5018e6..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToComplexVectorClosure.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-
-final class RDoubleToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
-
-    private final RAbstractDoubleVector castVector;
-
-    RDoubleToComplexVectorClosure(RAbstractDoubleVector vector) {
-        super(vector);
-        this.castVector = vector;
-    }
-
-    @Override
-    public RComplex getDataAt(int index) {
-        double real = castVector.getDataAt(index);
-        double imaginary = 0.0;
-        if (Double.isNaN(real)) {
-            return RComplex.createNA();
-        }
-        return RDataFactory.createComplex(real, imaginary);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java
deleted file mode 100644
index c25c168ab9..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToIntVectorClosure.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-
-final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
-
-    RDoubleToIntVectorClosure(RAbstractDoubleVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public int getDataAt(int index) {
-        double value = ((RAbstractDoubleVector) vector).getDataAt(index);
-        if (Double.isNaN(value)) {
-            return RRuntime.INT_NA;
-        }
-        int result = (int) value;
-        if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
-            RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION);
-            return RRuntime.INT_NA;
-        }
-        return result;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java
deleted file mode 100644
index 6a7ce849bb..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RDoubleToStringVectorClosure.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-final class RDoubleToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector {
-
-    RDoubleToStringVectorClosure(RAbstractDoubleVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public String getDataAt(int index) {
-        double data = ((RAbstractDoubleVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.STRING_NA;
-        } else {
-            return RContext.getRRuntimeASTAccess().encodeDouble(data);
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java
deleted file mode 100644
index 5826cf4d5f..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-/*
- * This closure is meant to be used only for implementation of the binary operators.
- */
-final class RFactorToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
-
-    private final RAbstractComplexVector levels;
-    private final boolean withNames;
-
-    RFactorToComplexVectorClosure(RAbstractIntVector vector, RAbstractComplexVector levels, boolean withNames) {
-        super(vector);
-        assert levels != null;
-        this.levels = levels;
-        this.withNames = withNames;
-    }
-
-    @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
-        switch (type) {
-            case Character:
-                return new RComplexToStringVectorClosure(this);
-            case Complex:
-                return this;
-            default:
-                return null;
-        }
-    }
-
-    @Override
-    public RComplex getDataAt(int index) {
-        int val = ((RIntVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(val)) {
-            return RRuntime.createComplexNA();
-        } else {
-            return levels.getDataAt(val - 1);
-        }
-    }
-
-    @Override
-    public RStringVector getNames() {
-        return withNames ? super.getNames() : null;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java
deleted file mode 100644
index af9ed55494..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-/*
- * This closure is meant to be used only for implementation of the binary operators.
- */
-final class RFactorToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
-
-    private final RAbstractDoubleVector levels;
-    private final boolean withNames;
-
-    RFactorToDoubleVectorClosure(RAbstractIntVector vector, RAbstractDoubleVector levels, boolean withNames) {
-        super(vector);
-        assert levels != null;
-        this.levels = levels;
-        this.withNames = withNames;
-    }
-
-    @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
-        switch (type) {
-            case Double:
-                return this;
-            case Character:
-                return new RDoubleToStringVectorClosure(this);
-            case Complex:
-                return new RDoubleToComplexVectorClosure(this);
-            default:
-                return null;
-        }
-    }
-
-    @Override
-    public double getDataAt(int index) {
-        int val = ((RIntVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(val)) {
-            return RRuntime.DOUBLE_NA;
-        } else {
-            return levels.getDataAt(val - 1);
-        }
-    }
-
-    @Override
-    public RStringVector getNames() {
-        return withNames ? super.getNames() : null;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java
deleted file mode 100644
index ecec033a92..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-/*
- * This closure is meant to be used only for implementation of the binary operators.
- */
-final class RFactorToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
-
-    private final RAbstractIntVector levels;
-    private final boolean withNames;
-
-    RFactorToIntVectorClosure(RAbstractIntVector vector, RAbstractIntVector levels, boolean withNames) {
-        super(vector);
-        assert levels != null;
-        this.levels = levels;
-        this.withNames = withNames;
-    }
-
-    @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
-        switch (type) {
-            case Integer:
-                return this;
-            case Double:
-                return new RIntToDoubleVectorClosure(this);
-            case Character:
-                return new RIntToStringVectorClosure(this);
-            case Complex:
-                return new RIntToComplexVectorClosure(this);
-            default:
-                return null;
-        }
-    }
-
-    @Override
-    public int getDataAt(int index) {
-        int val = ((RIntVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(val)) {
-            return RRuntime.INT_NA;
-        } else {
-            return levels.getDataAt(val - 1);
-        }
-    }
-
-    @Override
-    public RStringVector getNames() {
-        return withNames ? super.getNames() : null;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java
deleted file mode 100644
index 91350bfa78..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-/*
- * This closure is meant to be used only for implementation of the binary operators.
- */
-public final class RFactorToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector {
-
-    private final RAbstractStringVector levels;
-    private final boolean withNames;
-
-    RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) {
-        super(vector);
-        this.levels = levels;
-        this.withNames = withNames;
-        if (this.levels == null) {
-            RError.warning(RError.SHOW_CALLER2, RError.Message.IS_NA_TO_NON_VECTOR, "NULL");
-        }
-    }
-
-    @Override
-    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
-        switch (type) {
-            case Character:
-                return this;
-            default:
-                return null;
-        }
-    }
-
-    @Override
-    public String getDataAt(int index) {
-        if (levels == null || levels.getLength() == 0) {
-            return RRuntime.STRING_NA;
-        } else {
-            int val = ((RIntVector) vector).getDataAt(index);
-            if (!vector.isComplete() && RRuntime.isNA(val)) {
-                return RRuntime.STRING_NA;
-            } else {
-                String l = levels.getDataAt(val - 1);
-                if (!levels.isComplete() && RRuntime.isNA(l)) {
-                    return "NA"; // for comparison
-                } else {
-                    return l;
-                }
-            }
-        }
-    }
-
-    @Override
-    public RStringVector getNames() {
-        return withNames ? super.getNames() : null;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java
deleted file mode 100644
index 7583e9ffc0..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToComplexVectorClosure.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-
-final class RIntToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
-
-    RIntToComplexVectorClosure(RAbstractIntVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public RComplex getDataAt(int index) {
-        int data = ((RAbstractIntVector) vector).getDataAt(index);
-        double real;
-        double imaginary;
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            real = RRuntime.COMPLEX_NA_REAL_PART;
-            imaginary = RRuntime.COMPLEX_NA_IMAGINARY_PART;
-        } else {
-            real = data;
-            imaginary = 0;
-        }
-        return RDataFactory.createComplex(real, imaginary);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java
deleted file mode 100644
index 9b1d20f62a..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToDoubleVectorClosure.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-
-final class RIntToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
-
-    RIntToDoubleVectorClosure(RAbstractIntVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public double getDataAt(int index) {
-        int data = ((RAbstractIntVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.DOUBLE_NA;
-        }
-        return RRuntime.int2doubleNoCheck(data);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java
deleted file mode 100644
index 05de4164e6..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RIntToStringVectorClosure.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-final class RIntToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector {
-
-    RIntToStringVectorClosure(RAbstractIntVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public String getDataAt(int index) {
-        int data = ((RAbstractIntVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.STRING_NA;
-        }
-        return RRuntime.intToStringNoCheck(data);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java
deleted file mode 100644
index 66fe09f3f3..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToComplexVectorClosure.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-
-final class RLogicalToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
-
-    RLogicalToComplexVectorClosure(RAbstractLogicalVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public RComplex getDataAt(int index) {
-        byte data = ((RAbstractLogicalVector) vector).getDataAt(index);
-        double real;
-        double imaginary;
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            real = RRuntime.COMPLEX_NA_REAL_PART;
-            imaginary = RRuntime.COMPLEX_NA_IMAGINARY_PART;
-        } else {
-            real = data;
-            imaginary = 0;
-        }
-        return RDataFactory.createComplex(real, imaginary);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java
deleted file mode 100644
index 4a93498bea..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToDoubleVectorClosure.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-
-final class RLogicalToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
-
-    RLogicalToDoubleVectorClosure(RAbstractLogicalVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public double getDataAt(int index) {
-        byte data = ((RAbstractLogicalVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.DOUBLE_NA;
-        }
-        return RRuntime.logical2doubleNoCheck(data);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java
deleted file mode 100644
index 12ac3e31b8..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToIntVectorClosure.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-
-final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
-
-    RLogicalToIntVectorClosure(RAbstractLogicalVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public int getDataAt(int index) {
-        byte data = ((RAbstractLogicalVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.INT_NA;
-        }
-        return data;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java
deleted file mode 100644
index 50cd40a0be..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RLogicalToStringVectorClosure.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-final class RLogicalToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector {
-
-    RLogicalToStringVectorClosure(RAbstractLogicalVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public String getDataAt(int index) {
-        byte data = ((RAbstractLogicalVector) vector).getDataAt(index);
-        if (!vector.isComplete() && RRuntime.isNA(data)) {
-            return RRuntime.STRING_NA;
-        }
-        return RRuntime.logicalToStringNoCheck(data);
-
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java
deleted file mode 100644
index b699420159..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToComplexVectorClosure.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-
-final class RRawToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
-
-    private final RAbstractRawVector logicalVector;
-
-    RRawToComplexVectorClosure(RAbstractRawVector vector) {
-        super(vector);
-        this.logicalVector = vector;
-    }
-
-    @Override
-    public RComplex getDataAt(int index) {
-        return RRuntime.raw2complex(logicalVector.getDataAt(index));
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java
deleted file mode 100644
index 6d03d530fe..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToDoubleVectorClosure.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-
-final class RRawToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
-
-    RRawToDoubleVectorClosure(RAbstractRawVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public double getDataAt(int index) {
-        return RRuntime.raw2double(((RAbstractRawVector) vector).getDataAt(index));
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java
deleted file mode 100644
index 0cc977666f..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToIntVectorClosure.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-
-final class RRawToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
-
-    RRawToIntVectorClosure(RAbstractRawVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public int getDataAt(int index) {
-        return RRuntime.raw2int(((RAbstractRawVector) vector).getDataAt(index));
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java
deleted file mode 100644
index d7352e323f..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RRawToStringVectorClosure.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.data.closures;
-
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-
-final class RRawToStringVectorClosure extends RToStringVectorClosure implements RAbstractStringVector {
-
-    RRawToStringVectorClosure(RAbstractRawVector vector) {
-        super(vector);
-    }
-
-    @Override
-    public String getDataAt(int index) {
-        return RRuntime.rawToString(((RAbstractRawVector) vector).getDataAt(index));
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java
index e469c8b0d0..5cad987444 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToComplexVectorClosure.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,19 +22,21 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbstractComplexVector {
 
-    RToComplexVectorClosure(RAbstractVector vector) {
-        super(vector);
-    }
-
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createComplexVector(new double[newLength << 1], newIsComplete);
@@ -50,7 +52,7 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst
             result[index] = data.getRealPart();
             result[index + 1] = data.getImaginaryPart();
         }
-        return RDataFactory.createComplexVector(result, vector.isComplete());
+        return RDataFactory.createComplexVector(result, getVector().isComplete());
     }
 
     @Override
@@ -58,3 +60,122 @@ abstract class RToComplexVectorClosure extends RToVectorClosure implements RAbst
         return materialize().copyWithNewDimensions(newDimensions);
     }
 }
+
+final class RLogicalToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
+
+    private final RLogicalVector vector;
+
+    RLogicalToComplexVectorClosure(RLogicalVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RLogicalVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        byte real = vector.getDataAt(index);
+        return RRuntime.isNA(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0);
+    }
+}
+
+final class RIntToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
+
+    private final RIntVector vector;
+
+    RIntToComplexVectorClosure(RIntVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        int real = vector.getDataAt(index);
+        return RRuntime.isNA(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0);
+    }
+}
+
+final class RIntSequenceToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
+
+    private final RIntSequence vector;
+
+    RIntSequenceToComplexVectorClosure(RIntSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        int real = vector.getDataAt(index);
+        return RRuntime.isNA(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0);
+    }
+}
+
+final class RDoubleToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
+
+    private final RDoubleVector vector;
+
+    RDoubleToComplexVectorClosure(RDoubleVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        double real = vector.getDataAt(index);
+        return Double.isNaN(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0);
+    }
+}
+
+final class RDoubleSequenceToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
+
+    private final RDoubleSequence vector;
+
+    RDoubleSequenceToComplexVectorClosure(RDoubleSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        double real = vector.getDataAt(index);
+        return Double.isNaN(real) ? RComplex.createNA() : RDataFactory.createComplex(real, 0.0);
+    }
+}
+
+final class RRawToComplexVectorClosure extends RToComplexVectorClosure implements RAbstractComplexVector {
+
+    private final RRawVector vector;
+
+    RRawToComplexVectorClosure(RRawVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RRawVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        return RRuntime.raw2complex(vector.getDataAt(index));
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java
index 55cc0daa12..435498a961 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToDoubleVectorClosure.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,18 +22,18 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstractDoubleVector {
 
-    RToDoubleVectorClosure(RAbstractVector vector) {
-        super(vector);
-    }
-
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createDoubleVector(new double[newLength], newIsComplete);
@@ -47,7 +47,7 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr
             double data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createDoubleVector(result, vector.isComplete());
+        return RDataFactory.createDoubleVector(result, getVector().isComplete());
     }
 
     @Override
@@ -55,3 +55,91 @@ abstract class RToDoubleVectorClosure extends RToVectorClosure implements RAbstr
         return materialize().copyWithNewDimensions(newDimensions);
     }
 }
+
+final class RLogicalToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
+
+    private final RLogicalVector vector;
+
+    RLogicalToDoubleVectorClosure(RLogicalVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RLogicalVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public double getDataAt(int index) {
+        byte data = vector.getDataAt(index);
+        if (RRuntime.isNA(data)) {
+            return RRuntime.DOUBLE_NA;
+        }
+        return RRuntime.logical2doubleNoCheck(data);
+    }
+}
+
+final class RIntToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
+
+    private final RIntVector vector;
+
+    RIntToDoubleVectorClosure(RIntVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public double getDataAt(int index) {
+        int data = vector.getDataAt(index);
+        if (RRuntime.isNA(data)) {
+            return RRuntime.DOUBLE_NA;
+        }
+        return RRuntime.int2doubleNoCheck(data);
+    }
+}
+
+final class RIntSequenceToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
+
+    private final RIntSequence vector;
+
+    RIntSequenceToDoubleVectorClosure(RIntSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public double getDataAt(int index) {
+        int data = vector.getDataAt(index);
+        if (RRuntime.isNA(data)) {
+            return RRuntime.DOUBLE_NA;
+        }
+        return RRuntime.int2doubleNoCheck(data);
+    }
+}
+
+final class RRawToDoubleVectorClosure extends RToDoubleVectorClosure implements RAbstractDoubleVector {
+
+    private final RRawVector vector;
+
+    RRawToDoubleVectorClosure(RRawVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RRawVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public double getDataAt(int index) {
+        return RRuntime.raw2double(vector.getDataAt(index));
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java
index 132946950c..187b1260e7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToIntVectorClosure.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,18 +22,21 @@
  */
 package com.oracle.truffle.r.runtime.data.closures;
 
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstractIntVector {
 
-    RToIntVectorClosure(RAbstractVector vector) {
-        super(vector);
-    }
-
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createIntVector(new int[newLength], newIsComplete);
@@ -47,7 +50,7 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract
             int data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createIntVector(result, vector.isComplete());
+        return RDataFactory.createIntVector(result, getVector().isComplete());
     }
 
     @Override
@@ -55,3 +58,128 @@ abstract class RToIntVectorClosure extends RToVectorClosure implements RAbstract
         return materialize().copyWithNewDimensions(newDimensions);
     }
 }
+
+final class RLogicalToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
+
+    private final RLogicalVector vector;
+
+    RLogicalToIntVectorClosure(RLogicalVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RLogicalVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public int getDataAt(int index) {
+        byte data = vector.getDataAt(index);
+        if (RRuntime.isNA(data)) {
+            return RRuntime.INT_NA;
+        }
+        return data;
+    }
+}
+
+final class RDoubleToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
+
+    private final RDoubleVector vector;
+
+    RDoubleToIntVectorClosure(RDoubleVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public int getDataAt(int index) {
+        double value = vector.getDataAt(index);
+        if (Double.isNaN(value)) {
+            return RRuntime.INT_NA;
+        }
+        int result = (int) value;
+        if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
+            RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION);
+            return RRuntime.INT_NA;
+        }
+        return result;
+    }
+}
+
+final class RDoubleSequenceToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
+
+    private final RDoubleSequence vector;
+
+    RDoubleSequenceToIntVectorClosure(RDoubleSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public int getDataAt(int index) {
+        double value = vector.getDataAt(index);
+        if (Double.isNaN(value)) {
+            return RRuntime.INT_NA;
+        }
+        int result = (int) value;
+        if (result == Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
+            RError.warning(RError.SHOW_CALLER2, RError.Message.NA_INTRODUCED_COERCION);
+            return RRuntime.INT_NA;
+        }
+        return result;
+    }
+}
+
+/**
+ * In converting complex numbers to integers, this closure discards the imaginary parts.
+ */
+final class RComplexToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
+
+    private final RComplexVector vector;
+
+    RComplexToIntVectorClosure(RComplexVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RComplexVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public int getDataAt(int index) {
+        RComplex right = vector.getDataAt(index);
+        if (RRuntime.isNA(right)) {
+            return RRuntime.INT_NA;
+        }
+        RError.warning(RError.SHOW_CALLER2, RError.Message.IMAGINARY_PARTS_DISCARDED_IN_COERCION);
+        return RRuntime.complex2intNoCheck(right);
+    }
+}
+
+final class RRawToIntVectorClosure extends RToIntVectorClosure implements RAbstractIntVector {
+
+    private final RRawVector vector;
+
+    RRawToIntVectorClosure(RRawVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RRawVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public int getDataAt(int index) {
+        return RRuntime.raw2int(vector.getDataAt(index));
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java
new file mode 100644
index 0000000000..8a03a34c89
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToListVectorClosure.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.data.closures;
+
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RRawVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+abstract class RToListVectorClosure extends RToVectorClosure implements RAbstractListVector {
+
+    @Override
+    public Object getDataAtAsObject(int index) {
+        return getDataAt(index);
+    }
+
+    @Override
+    public RList materialize() {
+        int length = getLength();
+        Object[] result = new Object[length];
+        for (int i = 0; i < length; i++) {
+            Object data = getDataAt(i);
+            result[i] = data;
+        }
+        return RDataFactory.createList(result);
+    }
+
+    @Override
+    public RAbstractVector copyWithNewDimensions(int[] newDimensions) {
+        return materialize().copyWithNewDimensions(newDimensions);
+    }
+
+    @Override
+    public RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
+        return RDataFactory.createList(new Object[newLength]);
+    }
+}
+
+final class RLogicalToListVectorClosure extends RToListVectorClosure {
+
+    private final RLogicalVector vector;
+
+    RLogicalToListVectorClosure(RLogicalVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RLogicalVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public Byte getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RIntToListVectorClosure extends RToListVectorClosure {
+
+    private final RIntVector vector;
+
+    RIntToListVectorClosure(RIntVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public Integer getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RIntSequenceToListVectorClosure extends RToListVectorClosure {
+
+    private final RIntSequence vector;
+
+    RIntSequenceToListVectorClosure(RIntSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public Integer getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RDoubleToListVectorClosure extends RToListVectorClosure {
+
+    private final RDoubleVector vector;
+
+    RDoubleToListVectorClosure(RDoubleVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public Double getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RDoubleSequenceToListVectorClosure extends RToListVectorClosure {
+
+    private final RDoubleSequence vector;
+
+    RDoubleSequenceToListVectorClosure(RDoubleSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public Double getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RComplexToListVectorClosure extends RToListVectorClosure {
+
+    private final RComplexVector vector;
+
+    RComplexToListVectorClosure(RComplexVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RComplexVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RComplex getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RStringToListVectorClosure extends RToListVectorClosure {
+
+    private final RStringVector vector;
+
+    RStringToListVectorClosure(RStringVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RStringVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
+
+final class RRawToListVectorClosure extends RToListVectorClosure {
+
+    private final RRawVector vector;
+
+    RRawToListVectorClosure(RRawVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RRawVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RRaw getDataAt(int index) {
+        return vector.getDataAt(index);
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
index 6db80a38ca..e9a127adbd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToStringVectorClosure.java
@@ -23,18 +23,27 @@
 package com.oracle.truffle.r.runtime.data.closures;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleSequence;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntSequence;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstractStringVector {
 
-    RToStringVectorClosure(RAbstractVector vector) {
-        super(vector);
-    }
-
     @Override
     public final RVector<?> createEmptySameType(int newLength, boolean newIsComplete) {
         return RDataFactory.createStringVector(new String[newLength], newIsComplete);
@@ -48,7 +57,7 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr
             String data = getDataAt(i);
             result[i] = data;
         }
-        return RDataFactory.createStringVector(result, vector.isComplete(), getDimensionsMaterialized(), getNamesMaterialized());
+        return RDataFactory.createStringVector(result, getVector().isComplete(), getDimensionsMaterialized(), getNamesMaterialized());
     }
 
     @TruffleBoundary
@@ -66,3 +75,214 @@ abstract class RToStringVectorClosure extends RToVectorClosure implements RAbstr
         return materialize().copyWithNewDimensions(newDimensions);
     }
 }
+
+final class RLogicalToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RLogicalVector vector;
+
+    RLogicalToStringVectorClosure(RLogicalVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RLogicalVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        byte data = vector.getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(data)) {
+            return RRuntime.STRING_NA;
+        }
+        return RRuntime.logicalToStringNoCheck(data);
+
+    }
+}
+
+final class RIntToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RIntVector vector;
+
+    RIntToStringVectorClosure(RIntVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        int data = vector.getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(data)) {
+            return RRuntime.STRING_NA;
+        }
+        return RRuntime.intToStringNoCheck(data);
+    }
+}
+
+final class RIntSequenceToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RIntSequence vector;
+
+    RIntSequenceToStringVectorClosure(RIntSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RIntSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        int data = vector.getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(data)) {
+            return RRuntime.STRING_NA;
+        }
+        return RRuntime.intToStringNoCheck(data);
+    }
+}
+
+final class RDoubleToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RDoubleVector vector;
+
+    RDoubleToStringVectorClosure(RDoubleVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        double data = vector.getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(data)) {
+            return RRuntime.STRING_NA;
+        } else {
+            return RContext.getRRuntimeASTAccess().encodeDouble(data);
+        }
+    }
+}
+
+final class RDoubleSequenceToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RDoubleSequence vector;
+
+    RDoubleSequenceToStringVectorClosure(RDoubleSequence vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RDoubleSequence getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        double data = vector.getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(data)) {
+            return RRuntime.STRING_NA;
+        } else {
+            return RContext.getRRuntimeASTAccess().encodeDouble(data);
+        }
+    }
+}
+
+final class RComplexToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RComplexVector vector;
+
+    RComplexToStringVectorClosure(RComplexVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RComplexVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        RComplex data = vector.getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(data)) {
+            return RRuntime.STRING_NA;
+        }
+        return RContext.getRRuntimeASTAccess().encodeComplex(data);
+    }
+}
+
+final class RRawToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RRawVector vector;
+
+    RRawToStringVectorClosure(RRawVector vector) {
+        this.vector = vector;
+    }
+
+    @Override
+    public RRawVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        return RRuntime.rawToString(vector.getDataAt(index));
+    }
+}
+
+/*
+ * This closure is meant to be used only for implementation of the binary operators.
+ */
+final class RFactorToStringVectorClosure extends RToStringVectorClosure {
+
+    private final RAbstractIntVector vector;
+    private final RAbstractStringVector levels;
+    private final boolean withNames;
+
+    RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) {
+        this.vector = vector;
+        this.levels = levels;
+        this.withNames = withNames;
+    }
+
+    @Override
+    public RAbstractIntVector getVector() {
+        return vector;
+    }
+
+    @Override
+    public RAbstractVector castSafe(RType type, ConditionProfile isNAProfile) {
+        switch (type) {
+            case Character:
+                return this;
+            default:
+                return null;
+        }
+    }
+
+    @Override
+    public String getDataAt(int index) {
+        int val = ((RIntVector) vector).getDataAt(index);
+        if (!vector.isComplete() && RRuntime.isNA(val)) {
+            return RRuntime.STRING_NA;
+        } else {
+            String l = levels.getDataAt(val - 1);
+            if (!levels.isComplete() && RRuntime.isNA(l)) {
+                return "NA"; // for comparison
+            } else {
+                return l;
+            }
+        }
+    }
+
+    @Override
+    public RStringVector getNames() {
+        return withNames ? super.getNames() : null;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
index 9b78aed76e..aa70a23503 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
@@ -23,7 +23,7 @@
 package com.oracle.truffle.r.runtime.data.closures;
 
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.r.runtime.data.MemoryCopyTracer;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
@@ -33,15 +33,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 abstract class RToVectorClosure implements RAbstractVector {
 
-    protected final RAbstractVector vector;
-
-    RToVectorClosure(RAbstractVector vector) {
-        this.vector = vector;
-    }
+    public abstract RAbstractVector getVector();
 
     @Override
     public int getLength() {
-        return vector.getLength();
+        return getVector().getLength();
     }
 
     @Override
@@ -51,142 +47,132 @@ abstract class RToVectorClosure implements RAbstractVector {
 
     @Override
     public final RAbstractContainer resize(int size) {
-        return vector.resize(size);
+        return getVector().resize(size);
     }
 
     @Override
     public final void setComplete(boolean complete) {
-        this.vector.setComplete(complete);
+        this.getVector().setComplete(complete);
     }
 
     @Override
     public final boolean isComplete() {
-        return vector.isComplete();
+        return getVector().isComplete();
     }
 
     @Override
     public final boolean hasDimensions() {
-        return vector.hasDimensions();
+        return getVector().hasDimensions();
     }
 
     @Override
     public final int[] getDimensions() {
-        return vector.getDimensions();
+        return getVector().getDimensions();
     }
 
     @Override
     public final void setDimensions(int[] newDimensions) {
-        vector.setDimensions(newDimensions);
+        getVector().setDimensions(newDimensions);
     }
 
     @Override
     public RStringVector getNames() {
-        return vector.getNames();
+        return getVector().getNames();
     }
 
     @Override
     public final void setNames(RStringVector newNames) {
-        vector.setNames(newNames);
+        getVector().setNames(newNames);
     }
 
     @Override
     public final RList getDimNames() {
-        return vector.getDimNames();
+        return getVector().getDimNames();
     }
 
     @Override
     public final void setDimNames(RList newDimNames) {
-        vector.setDimNames(newDimNames);
+        getVector().setDimNames(newDimNames);
     }
 
     @Override
     public final Object getRowNames() {
-        return vector.getRowNames();
+        return getVector().getRowNames();
     }
 
     @Override
     public final void setRowNames(RAbstractVector rowNames) {
-        vector.setRowNames(rowNames);
+        getVector().setRowNames(rowNames);
     }
 
     @Override
     public final DynamicObject initAttributes() {
-        return vector.initAttributes();
+        return getVector().initAttributes();
     }
 
     @Override
     public final void initAttributes(DynamicObject newAttributes) {
-        vector.initAttributes(newAttributes);
+        getVector().initAttributes(newAttributes);
     }
 
     @Override
     public final DynamicObject getAttributes() {
-        return vector.getAttributes();
+        return getVector().getAttributes();
     }
 
     @Override
     public final RAbstractVector copy() {
-        RAbstractVector result = vector.copy();
-        MemoryCopyTracer.reportCopying(this, result);
-        return result;
+        throw RInternalError.shouldNotReachHere();
     }
 
     @Override
     public final RVector<?> copyResized(int size, boolean fillNA) {
-        RVector<?> result = vector.copyResized(size, fillNA);
-        MemoryCopyTracer.reportCopying(this, result);
-        return result;
+        throw RInternalError.shouldNotReachHere();
     }
 
     @Override
     public final RVector<?> copyResizedWithDimensions(int[] newDimensions, boolean fillNA) {
-        // TODO support for higher dimensions
-        assert newDimensions.length == 2;
-        RVector<?> result = copyResized(newDimensions[0] * newDimensions[1], fillNA);
-        result.setDimensions(newDimensions);
-        return result;
+        throw RInternalError.shouldNotReachHere();
     }
 
     @Override
     public final RAbstractVector copyDropAttributes() {
-        RAbstractVector result = vector.copyDropAttributes();
-        MemoryCopyTracer.reportCopying(this, result);
-        return result;
+        throw RInternalError.shouldNotReachHere();
     }
 
     @Override
     public final boolean isMatrix() {
-        return vector.isMatrix();
+        return getVector().isMatrix();
     }
 
     @Override
     public final boolean isArray() {
-        return vector.isArray();
+        return getVector().isArray();
     }
 
     @Override
     public final RStringVector getClassHierarchy() {
-        return vector.getClassHierarchy();
+        return getVector().getClassHierarchy();
     }
 
     @Override
     public RStringVector getImplicitClass() {
-        return vector.getImplicitClass();
+        return getVector().getImplicitClass();
     }
 
     @Override
     public final RTypedValue getNonShared() {
-        return vector.getNonShared();
+        return getVector().getNonShared();
     }
 
     @Override
     public int getTypedValueInfo() {
-        return vector.getTypedValueInfo();
+        return getVector().getTypedValueInfo();
     }
 
     @Override
     public void setTypedValueInfo(int value) {
-        vector.setTypedValueInfo(value);
+        getVector().setTypedValueInfo(value);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java
index 6b2bbd3a2e..cbf0f6f606 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -180,7 +180,7 @@ public final class NACheck {
 
     public RComplex convertLogicalToComplex(byte value) {
         if (check(value)) {
-            return RRuntime.createComplexNA();
+            return RComplex.createNA();
         }
         return RDataFactory.createComplex(value, 0);
     }
@@ -194,14 +194,14 @@ public final class NACheck {
 
     public RComplex convertDoubleToComplex(double value) {
         if (check(value)) {
-            return RRuntime.createComplexNA();
+            return RComplex.createNA();
         }
         return RDataFactory.createComplex(value, 0);
     }
 
     public RComplex convertIntToComplex(int value) {
         if (check(value)) {
-            return RRuntime.createComplexNA();
+            return RComplex.createNA();
         }
         return RDataFactory.createComplex(value, 0);
     }
@@ -252,7 +252,7 @@ public final class NACheck {
 
     public RComplex convertStringToComplex(String value) {
         if (check(value)) {
-            return RRuntime.createComplexNA();
+            return RComplex.createNA();
         }
         RComplex result = RRuntime.string2complexNoCheck(value);
         check(result); // can be NA
-- 
GitLab


From d8badc35f3d18e7c952f5187d6c6765abd357ed1 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 7 Apr 2017 10:25:46 +0200
Subject: [PATCH 268/402] FastR Grid: implement few more point types in LPoints

---
 .../truffle/r/library/fastrGrid/LPoints.java  | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index 02d7c1b47f..c8fa2b5c39 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -88,6 +88,14 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
                 return drawDot(drawingCtx, dev, cex, x, y);
             case 1:
                 return drawOctahedron(drawingCtx, dev, GridColor.TRANSPARENT, size, x, y);
+            case 19: /* R filled circle */
+                return drawFilledCircle(drawingCtx, dev, RADIUS * size, x, y);
+            case 20: /* R `Dot' (small circle) */
+                return drawFilledCircle(drawingCtx, dev, SMALL * size, x, y);
+            case 21: /* circles */
+                return drawCircle(drawingCtx, dev, size, x, y);
+            case 22: /* squares */
+                return drawSquare(drawingCtx, dev, size, x, y);
             case 16:
                 return drawOctahedron(drawingCtx, dev, drawingCtx.getWrapped().getColor(), size, x, y);
             default:
@@ -95,6 +103,25 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
         }
     }
 
+    private PointDrawingContext drawFilledCircle(PointDrawingContext drawingCtxIn, GridDevice dev, double radius, double x, double y) {
+        PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), drawingCtxIn.getWrapped().getColor());
+        dev.drawCircle(drawingCtx, x, y, radius);
+        return drawingCtx;
+    }
+
+    private PointDrawingContext drawCircle(PointDrawingContext drawingCtx, GridDevice dev, double size, double x, double y) {
+        double xc = RADIUS * size;
+        dev.drawCircle(drawingCtx, x, y, xc);
+        return drawingCtx;
+    }
+
+    private PointDrawingContext drawSquare(PointDrawingContext drawingCtx, GridDevice dev, double size, double x, double y) {
+        double xc = RADIUS * SQRC * size;
+        double yc = RADIUS * SQRC * size;
+        dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc, 0);
+        return drawingCtx;
+    }
+
     private static PointDrawingContext drawOctahedron(PointDrawingContext drawingCtxIn, GridDevice dev, GridColor fill, double size, double x, double y) {
         PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), fill);
         dev.drawCircle(drawingCtx, x, y, RADIUS * size);
-- 
GitLab


From e69f1f20e0d278bd2fc4da6abcc9779be847ccfa Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 7 Apr 2017 10:26:14 +0200
Subject: [PATCH 269/402] FastR Grid: fix L_downviewport

---
 .../oracle/truffle/r/library/fastrGrid/fastrGrid.R    | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index 70cf79d4d7..d799ca533c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -25,14 +25,14 @@ chullWrapper <- function(x, y) {
 }
 
 # Returns list with elements [[1]] - depth, zero if not found, [[2]] - the viewport, NULL if not found
-# We are searching for child "name" in "pvp", if the "path" is not missing,
+# We are searching for child "name" in "pvp", if the "path" is not integer value 0,
 # then also pathMatch(path, currPath) must hold.
 find.viewport <- function(path, name, strict, currPath, pvp, depth) {
     if (length(ls(env=pvp$children)) == 0) {
         return(list(FALSE, NULL))
-    } else if (exists(name, env=pvp$children, inherits=FALSE) && (missing(path) || grid:::pathMatch(path, currPath, strict))) {
+    } else if (exists(name, env=pvp$children, inherits=FALSE) && (path == 0L || grid:::pathMatch(path, currPath, strict))) {
         return(list(depth, get(name, env=pvp$children, inherits=FALSE)))
-    } else if (strict && missing(path)) {
+    } else if (strict && path == 0L) {
         return(list(FALSE, NULL))
     } else {
         return(find.in.children(path, name, strict, currPath, pvp$children, depth + 1L))
@@ -46,7 +46,7 @@ find.in.children <- function(path, name, strict, currPath, children, depth) {
   found <- FALSE
   while (count < ncpvp && !found) {
     child <- get(cpvps[count + 1L], env=children)
-    nextCurrPath <- if (missing(path)) NULL else grid:::growPath(currPath, child$name)
+    nextCurrPath <- if (path == 0L) NULL else grid:::growPath(currPath, child$name)
     result <- find.viewport(path, name, strict, nextCurrPath, child, depth)
     if (result[[1L]]) {
         return(result);
@@ -70,8 +70,7 @@ L_downvppath <- function(path, name, strict) {
 }
 
 L_downviewport <- function(name, strict) {
-    # note: first argument is "missing"
-    L_downvppath(, name, strict)
+    L_downvppath(0L, name, strict)
 }
 
 L_setviewport <- function(vp, hasParent) {
-- 
GitLab


From 2264c8f776511f49abf002d4d1b9785c2600d594 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 7 Apr 2017 10:27:58 +0200
Subject: [PATCH 270/402] FastR Grid: support plotting to user given Graphics2D
 instance

---
 .../device/awt/Graphics2DDevice.java          |  2 +-
 .../grDevices/InitWindowedDevice.java         | 26 ++++++++++++++++++-
 .../fastrGrid/grDevices/R/fastrGridDevices.R  |  4 +--
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
index 877ad16225..a99d30e2d1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
@@ -76,7 +76,7 @@ public class Graphics2DDevice implements GridDevice {
      * @param graphicsIsExclusive If the graphics object is exclusively used for drawing only by
      *            this class, then it can optimize some things.
      */
-    Graphics2DDevice(Graphics2D graphics, int width, int height, boolean graphicsIsExclusive) {
+    public Graphics2DDevice(Graphics2D graphics, int width, int height, boolean graphicsIsExclusive) {
         initStrokes();
         setGraphics2D(graphics);
         this.width = width;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 40ceb214b5..52fe6b7900 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -22,18 +22,24 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
+import java.awt.Graphics2D;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.Graphics2DDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 
 /**
  * Node that handles the {@code C_X11} external calls. Those calls may be initiated from either the
@@ -51,6 +57,7 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
     protected Object call(RArgsValuesAndNames args) {
         int width = getIntOrDefault(args, 1, GridDevice.DEFAULT_WIDTH);
         int height = getIntOrDefault(args, 2, GridDevice.DEFAULT_HEIGHT);
+
         // if the first argument is a String, then it may describes the image format and filename to
         // use, the format is e.g. "jpeg::quality:filename"
         if (args.getLength() >= 1) {
@@ -59,9 +66,26 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
                 return openImageDevice(name, width, height);
             }
         }
+
         // otherwise the windowed device
+        // check if we got custom Graphics2D object as 3rd parameter
+        boolean isFastRDevice = args.getArgument(0).equals(".FASTR.AWT");
+        if (isFastRDevice && args.getLength() > 3) {
+            Object arg3 = args.getArgument(3);
+            boolean isTruffleObj = arg3 instanceof TruffleObject && !(arg3 instanceof RTypedValue);
+            if (isTruffleObj && JavaInterop.isJavaObject(Graphics2D.class, (TruffleObject) arg3)) {
+                Graphics2D graphics = JavaInterop.asJavaObject(Graphics2D.class, (TruffleObject) arg3);
+                Graphics2DDevice device = new Graphics2DDevice(graphics, width, height, false);
+                GridContext.getContext().setCurrentDevice("awt", device);
+                return RNull.instance;
+            } else if (isTruffleObj) {
+                warning(Message.GENERIC, "3rd argument is foreign object, but not of type Graphics2D.");
+            }
+        }
+
+        // otherwise create the window ourselves
         BufferedJFrameDevice device = new BufferedJFrameDevice(JFrameDevice.create(width, height));
-        String name = args.getArgument(0).equals(".FASTR.AWT") ? "awt" : "X11cairo";
+        String name = isFastRDevice ? "awt" : "X11cairo";
         GridContext.getContext().setCurrentDevice(name, device);
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
index a1bc97886a..2e551b4a1a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
@@ -24,8 +24,8 @@ eval(expression({
     # For compatibility reasons, both X11 and awt end up calling C_X11.
     # In the future, this function may support extra parameters like a
     # reference to java 2D graphics object, which will be used for the drawing.
-    awt <- function(width = NULL, height = NULL) {
-        .External2(grDevices:::C_X11, ".FASTR.AWT", width, height)
+    awt <- function(width = NULL, height = NULL, graphicsObj = NULL) {
+        .External2(grDevices:::C_X11, ".FASTR.AWT", width, height, graphicsObj)
     }
     # GnuR version only works with "X11cairo" device. Our version of savePlot
     # works with "awt" device and "X11cairo", which is for us only alias for
-- 
GitLab


From 512234e0abd67257c5c639927369859693d72f11 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 7 Apr 2017 10:47:04 +0200
Subject: [PATCH 271/402] Enable FastR grid emulation by default.

---
 .../src/com/oracle/truffle/r/runtime/FastROptions.java          | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 24f998565a..636cfb2009 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -51,7 +51,7 @@ public enum FastROptions {
     FullPrecisionSum("Use 128 bit arithmetic in sum builtin", false),
     InvisibleArgs("Argument writes do not trigger state transitions", true),
     RefCountIncrementOnly("Disable reference count decrements for experimental state transition implementation", false),
-    UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", false),
+    UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", true),
     UseSpecials("Whether the fast-path special call nodes should be created for simple enough arguments.", true),
     ForceSources("Generate source sections for unserialized code", false),
 
-- 
GitLab


From 0f3dcb7aa4624b86bfc1928f0e8d1cbb13eb2db6 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 23 Feb 2017 13:16:12 +0100
Subject: [PATCH 272/402] move execute function out of UnaryNode

---
 .../com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java | 1 -
 .../src/com/oracle/truffle/r/nodes/unary/CastNode.java          | 2 ++
 .../src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java      | 1 -
 .../src/com/oracle/truffle/r/nodes/unary/TypeofNode.java        | 1 -
 .../com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java   | 2 ++
 .../src/com/oracle/truffle/r/nodes/unary/UnaryNode.java         | 1 -
 6 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index b11b3c9f7f..d13dd5cb8e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -78,7 +78,6 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return ClassHierarchyNodeGen.create(false, false);
     }
 
-    @Override
     public abstract RStringVector execute(Object arg);
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
index c252dcce4c..a6475c8759 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
@@ -42,6 +42,8 @@ public abstract class CastNode extends UnaryNode {
         isTesting = true;
     }
 
+    public abstract Object execute(Object value);
+
     /**
      * For testing purposes only, returns the last warning message (only when {@link #testingMode()}
      * was invoked before).
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java
index 7d3f63198c..5cf4bb815a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java
@@ -39,7 +39,6 @@ public final class IsFactorNode extends UnaryNode {
         return inheritsCheck.execute(x);
     }
 
-    @Override
     public Object execute(Object value) {
         return executeIsFactor(value);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
index 33fa857d3b..ff0bab5975 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
@@ -34,7 +34,6 @@ public abstract class TypeofNode extends UnaryNode {
 
     protected static final int NUMBER_OF_CACHED_CLASSES = 5;
 
-    @Override
     public abstract RType execute(Object x);
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
index eb8d1d0725..2e4061d8fe 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
@@ -65,6 +65,8 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
         this(factory, error, RType.Integer);
     }
 
+    public abstract Object execute(Object value);
+
     @Specialization(guards = {"cachedNode != null", "cachedNode.isSupported(operand)"})
     protected Object doCached(Object operand,
                     @Cached("createCachedFast(operand)") UnaryMapNode cachedNode) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
index 7101b81414..8f0de5aaee 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
@@ -29,5 +29,4 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 @TypeSystemReference(RTypes.class)
 public abstract class UnaryNode extends RBaseNode {
 
-    public abstract Object execute(Object value);
 }
-- 
GitLab


From 11e0d111c84c7b863e1b0840b155e0df7b7a4525 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 2 Mar 2017 10:16:47 +0100
Subject: [PATCH 273/402] remove getClassHierarchy and getImplicitClass from
 RAttributable

---
 .../r/engine/RRuntimeASTAccessImpl.java       |   7 +
 .../r/nodes/builtin/base/EnvFunctions.java    |  29 ++--
 .../r/nodes/builtin/base/GetOldClass.java     |   7 +-
 .../truffle/r/nodes/builtin/base/IsATTY.java  |   3 +-
 .../builtin/base/S3DispatchFunctions.java     |   8 +-
 .../truffle/r/nodes/builtin/base/Unique.java  |  12 +-
 .../builtin/base/foreign/WriteTable.java      |  10 +-
 .../base/printer/AttributesPrinter.java       |   3 +-
 .../base/printer/ValuePrinterNode.java        |  35 -----
 .../builtin/base/printer/ValuePrinters.java   |   3 +-
 .../r/nodes/access/AccessSlotNode.java        |   3 +-
 .../vector/CachedExtractVectorNode.java       |   2 +-
 .../SpecialAttributesFunctions.java           |   6 -
 .../truffle/r/nodes/builtin/CastBuilder.java  |   4 +-
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  24 +---
 .../r/nodes/function/ClassHierarchyNode.java  |  66 +++++++--
 .../function/ClassHierarchyScalarNode.java    |   2 +-
 .../function/ImplicitClassHierarchyNode.java  | 136 ++++++++++++++++++
 .../truffle/r/nodes/unary/IsFactorNode.java   |   2 +-
 .../truffle/r/nodes/unary/ToStringNode.java   |   7 +-
 .../truffle/r/nodes/unary/UnaryNode.java      |   2 +-
 .../truffle/r/runtime/RErrorHandling.java     |   2 +-
 .../oracle/truffle/r/runtime/RRuntime.java    |  10 --
 .../truffle/r/runtime/RRuntimeASTAccess.java  |   5 +-
 .../com/oracle/truffle/r/runtime/RType.java   |  10 +-
 .../truffle/r/runtime/data/RAttributable.java |  29 ----
 .../r/runtime/data/RAttributeStorage.java     |   5 +-
 .../r/runtime/data/RComplexVector.java        |   7 -
 .../r/runtime/data/RDoubleSequence.java       |   5 -
 .../truffle/r/runtime/data/RDoubleVector.java |   7 -
 .../truffle/r/runtime/data/RExpression.java   |   6 -
 .../truffle/r/runtime/data/RExternalPtr.java  |   8 +-
 .../truffle/r/runtime/data/RFunction.java     |   7 -
 .../truffle/r/runtime/data/RIntSequence.java  |   5 -
 .../truffle/r/runtime/data/RIntVector.java    |   7 -
 .../truffle/r/runtime/data/RLanguage.java     |   5 -
 .../oracle/truffle/r/runtime/data/RList.java  |   7 -
 .../r/runtime/data/RLogicalVector.java        |   6 -
 .../oracle/truffle/r/runtime/data/RNull.java  |   4 +-
 .../truffle/r/runtime/data/RPairList.java     |   5 -
 .../truffle/r/runtime/data/RRawVector.java    |   7 -
 .../truffle/r/runtime/data/RS4Object.java     |   7 -
 .../truffle/r/runtime/data/RScalarVector.java |  10 --
 .../truffle/r/runtime/data/RSequence.java     |   5 -
 .../truffle/r/runtime/data/RStringVector.java |   7 -
 .../truffle/r/runtime/data/RSymbol.java       |  10 +-
 .../data/closures/RToVectorClosure.java       |  10 --
 .../truffle/r/runtime/env/REnvironment.java   |   7 -
 .../truffle/r/runtime/nodes/RBaseNode.java    |  16 +--
 49 files changed, 277 insertions(+), 313 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index 0c7606c8f3..ad2140fbde 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -56,6 +56,7 @@ import com.oracle.truffle.r.nodes.control.AbstractLoopNode;
 import com.oracle.truffle.r.nodes.control.BlockNode;
 import com.oracle.truffle.r.nodes.control.IfNode;
 import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
@@ -85,6 +86,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
@@ -716,4 +718,9 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     public Class<? extends TruffleLanguage<?>> getTruffleRLanguage() {
         return TruffleRLanguage.class;
     }
+
+    @Override
+    public RAbstractStringVector getClassHierarchy(RAttributable value) {
+        return ClassHierarchyNode.getClassHierarchy(value);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index c2b77e78ef..c3e0789b43 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -56,6 +56,7 @@ import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RList2EnvNode;
 import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode;
@@ -371,25 +372,29 @@ public class EnvFunctions {
             return env;
         }
 
-        @Specialization(guards = "isRFormula(formula)")
-        protected Object environment(RLanguage formula) {
-            if (getEnvAttrNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT));
+        @Specialization
+        @TruffleBoundary
+        protected Object environmentLanguage(RLanguage value) {
+            if (ClassHierarchyNode.hasClass(value, RRuntime.FORMULA_CLASS)) {
+                if (getEnvAttrNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT));
+                }
+                Object result = getEnvAttrNode.execute(value);
+                return result == null ? RNull.instance : result;
+            } else {
+                return environment(value);
             }
-
-            Object result = getEnvAttrNode.execute(formula);
-            return result == null ? RNull.instance : result;
         }
 
-        @Specialization(guards = {"!isRNull(fun)", "!isRFunction(fun)", "!isRFormula(fun)"})
-        protected Object environment(Object fun) {
-            if (attributable.profile(fun instanceof RAttributable)) {
+        @Specialization(guards = {"!isRNull(value)", "!isRFunction(value)", "!isRLanguage(value)"})
+        protected Object environment(Object value) {
+            if (attributable.profile(value instanceof RAttributable)) {
                 if (getEnvAttrNode == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
                     getEnvAttrNode = insert(GetFixedAttributeNode.create(RRuntime.DOT_ENVIRONMENT));
                 }
-                Object attr = getEnvAttrNode.execute(fun);
+                Object attr = getEnvAttrNode.execute(value);
                 return attr == null ? RNull.instance : attr;
             } else {
                 // Not an error according to GnuR
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
index 374a9e866f..44d7c6121b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
@@ -25,10 +25,12 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -45,9 +47,10 @@ public abstract class GetOldClass extends RBuiltinNode {
     }
 
     @Specialization
-    protected Object getOldClass(RAbstractContainer arg) {
+    protected Object getOldClass(RAbstractContainer arg,
+                    @Cached("createWithImplicit()") ClassHierarchyNode hierarchy) {
         if (isObjectProfile.profile(getClassNode.isObject(arg))) {
-            return arg.getClassHierarchy();
+            return hierarchy.execute(arg);
         } else {
             return RNull.instance;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java
index 32fe999436..4666c8694d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.conn.RConnection;
@@ -48,7 +49,7 @@ public abstract class IsATTY extends RBuiltinNode {
     @TruffleBoundary
     protected byte isATTYNonConnection(RAbstractIntVector con) {
         if (con.getLength() == 1) {
-            RStringVector clazz = con.getClassHierarchy();
+            RStringVector clazz = ClassHierarchyNode.getClassHierarchy(con);
             for (int i = 0; i < clazz.getLength(); i++) {
                 if ("connection".equals(clazz.getDataAt(i))) {
                     RConnection connection = RContext.getInstance().stateRConnection.getConnection(con.getDataAt(0), false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
index 7465e31dfb..867f378c97 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
@@ -185,6 +185,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
         @Child private CollectArgumentsNode collectArguments = CollectArgumentsNodeGen.create();
 
         @Child private PromiseHelperNode promiseHelper;
+        @Child private ClassHierarchyNode hierarchy;
 
         private final ConditionProfile emptyArgsProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile genericCallFrameNullProfile = ConditionProfile.createBinaryProfile();
@@ -292,8 +293,11 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
             if (arg instanceof RPromise) {
                 arg = promiseHelper.evaluate(frame, (RPromise) arg);
             }
-            RAbstractContainer enclosingArg = (RAbstractContainer) arg;
-            return enclosingArg.getClassHierarchy();
+            if (hierarchy == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                hierarchy = insert(ClassHierarchyNode.createWithImplicit());
+            }
+            return hierarchy.execute(arg);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
index 32488e0035..8898ee1611 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
@@ -33,6 +33,7 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -240,8 +241,10 @@ public abstract class Unique extends RBuiltinNode {
     }
 
     @SuppressWarnings("unused")
-    @Specialization
-    protected RIntVector doUnique(RAbstractIntVector vec, byte incomparables, byte fromLast, int nmax) {
+    @Specialization(guards = "vecIn.getClass() == vecClass")
+    protected RIntVector doUniqueCached(RAbstractIntVector vecIn, byte incomparables, byte fromLast, int nmax,
+                    @Cached("vecIn.getClass()") Class<? extends RAbstractIntVector> vecClass) {
+        RAbstractIntVector vec = vecClass.cast(vecIn);
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSetInt set = new NonRecursiveHashSetInt();
             int[] data = new int[16];
@@ -268,6 +271,11 @@ public abstract class Unique extends RBuiltinNode {
         }
     }
 
+    @Specialization(replaces = "doUniqueCached")
+    protected RIntVector doUnique(RAbstractIntVector vec, byte incomparables, byte fromLast, int nmax) {
+        return doUniqueCached(vec, incomparables, fromLast, nmax, RAbstractIntVector.class);
+    }
+
     @SuppressWarnings("unused")
     @Specialization(guards = "lengthOne(list)")
     protected RList doUniqueL1(RList list, byte incomparables, byte fromLast, int nmax) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
index f03b6574e7..6c3e454a25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java
@@ -23,11 +23,13 @@ import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter;
 import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.conn.RConnection;
+import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -93,7 +95,7 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         }
         try (RConnection con = RConnection.fromIndex(file).forceOpen("wt")) {
             String tmp = null;
-            if (RRuntime.hasRClass(xx, RRuntime.CLASS_DATA_FRAME)) {
+            if (xx instanceof RAttributable && ClassHierarchyNode.hasClass((RAttributable) xx, RRuntime.CLASS_DATA_FRAME)) {
                 executeDataFrame(con, (RVector<?>) xx, nr, nc, rnames, csep, ceol, cna, cdec, qmethod, quoteCol, quoteRn);
             } else { /* A matrix */
 
@@ -284,9 +286,11 @@ public abstract class WriteTable extends RExternalBuiltinNode.Arg11 {
         throw RInternalError.unimplemented();
     }
 
+    @TruffleBoundary
     private static boolean isFactor(RAbstractContainer v) {
-        for (int i = 0; i < v.getClassHierarchy().getLength(); i++) {
-            if (v.getClassHierarchy().getDataAt(i).equals("factor")) {
+        RStringVector hierarchy = ClassHierarchyNode.getClassHierarchy(v);
+        for (int i = 0; i < hierarchy.getLength(); i++) {
+            if (hierarchy.getDataAt(i).equals("factor")) {
                 return true;
             }
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java
index 785cf3c273..0f7201f09f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java
@@ -17,6 +17,7 @@ import java.io.PrintWriter;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -62,7 +63,7 @@ final class AttributesPrinter implements ValuePrinter<RAttributable> {
                     continue;
                 }
             }
-            if (value.hasClass(RRuntime.CLASS_DATA_FRAME)) {
+            if (ClassHierarchyNode.hasClass(value, RRuntime.CLASS_DATA_FRAME)) {
                 if (RRuntime.ROWNAMES_ATTR_KEY.equals(a.getName())) {
                     continue;
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index f1212c7fd3..e1824bbccb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -132,11 +132,6 @@ public final class ValuePrinterNode extends RBaseNode {
                     return (String) value;
                 }
 
-                @Override
-                public RStringVector getImplicitClass() {
-                    return RStringVector.implicitClassHeader;
-                }
-
                 @Override
                 public RStringVector materialize() {
                     throw RInternalError.shouldNotReachHere();
@@ -185,11 +180,6 @@ public final class ValuePrinterNode extends RBaseNode {
                                 return RRuntime.asLogical((Boolean) value);
                             }
 
-                            @Override
-                            public RStringVector getImplicitClass() {
-                                return RIntVector.implicitClassHeader;
-                            }
-
                             @Override
                             public RLogicalVector materialize() {
                                 throw RInternalError.shouldNotReachHere();
@@ -222,11 +212,6 @@ public final class ValuePrinterNode extends RBaseNode {
                                 return (Integer) value;
                             }
 
-                            @Override
-                            public RStringVector getImplicitClass() {
-                                return RIntVector.implicitClassHeader;
-                            }
-
                             @Override
                             public RIntVector materialize() {
                                 throw RInternalError.shouldNotReachHere();
@@ -259,11 +244,6 @@ public final class ValuePrinterNode extends RBaseNode {
                                 return ((Number) value).doubleValue();
                             }
 
-                            @Override
-                            public RStringVector getImplicitClass() {
-                                return RDoubleVector.implicitClassHeader;
-                            }
-
                             @Override
                             public RDoubleVector materialize() {
                                 throw RInternalError.shouldNotReachHere();
@@ -298,11 +278,6 @@ public final class ValuePrinterNode extends RBaseNode {
                                 return value;
                             }
 
-                            @Override
-                            public RStringVector getImplicitClass() {
-                                return RList.implicitClassHeader;
-                            }
-
                             @Override
                             public RList materialize() {
                                 throw RInternalError.shouldNotReachHere();
@@ -348,11 +323,6 @@ public final class ValuePrinterNode extends RBaseNode {
                             return value;
                         }
 
-                        @Override
-                        public RStringVector getImplicitClass() {
-                            return RList.implicitClassHeader;
-                        }
-
                         @Override
                         public RStringVector getNames() {
                             return names;
@@ -549,11 +519,6 @@ public final class ValuePrinterNode extends RBaseNode {
             throw RInternalError.shouldNotReachHere();
         }
 
-        @Override
-        public RStringVector getImplicitClass() {
-            return null;
-        }
-
         @Override
         public RType getRType() {
             return RType.Integer;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index dfa54ca791..4104af4f43 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -28,6 +28,7 @@ import java.util.Map;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -118,7 +119,7 @@ final class ValuePrinters implements ValuePrinter<Object> {
 
     @TruffleBoundary
     private static boolean hasClass(Object x) {
-        return ((RAttributable) x).hasClass(RRuntime.CLASS_FACTOR);
+        return ClassHierarchyNode.hasClass((RAttributable) x, RRuntime.CLASS_FACTOR);
     }
 
     public static void printNewLine(PrintContext printCtx) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
index dd7b46a4b9..d5d8e0ad91 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
@@ -23,6 +23,7 @@ import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
+import com.oracle.truffle.r.nodes.function.ImplicitClassHierarchyNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
@@ -135,7 +136,7 @@ public abstract class AccessSlotNode extends RBaseNode {
                     @Cached("create()") GetClassAttributeNode getClassNode) {
         RStringVector classAttr = getClassNode.getClassAttr(object);
         if (classAttr == null) {
-            RStringVector implicitClassVec = object.getImplicitClass();
+            RStringVector implicitClassVec = ImplicitClassHierarchyNode.getImplicitClass(object);
             assert implicitClassVec.getLength() > 0;
             throw RError.error(this, RError.Message.SLOT_BASIC_CLASS, name, implicitClassVec.getDataAt(0));
         } else {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index c6aca41dc8..6a51aee479 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -466,7 +466,7 @@ final class CachedExtractVectorNode extends CachedVectorNode {
         protected void setNames(RVector<?> container, RAbstractStringVector newNames) {
             RStringVector newNames1 = newNames.materialize();
             assert newNames1.getLength() <= container.getLength();
-            assert container.getDimensions() == null;
+            assert container.getAttr(RRuntime.DIM_ATTR_KEY) == null;
             if (container.getAttributes() == null) {
                 // usual case
                 container.initAttributes(RAttributesLayout.createNames(newNames1));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
index 0cdf97146b..4ad3dfb761 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
@@ -1116,11 +1116,5 @@ public final class SpecialAttributesFunctions {
         public final boolean isObject(Object x) {
             return getClassAttr(x) != null ? true : false;
         }
-
-        public final RStringVector getClassHierarchy(RAttributable x) {
-            Object v = execute(x);
-            RStringVector result = v instanceof RStringVector ? (RStringVector) v : x.getImplicitClass();
-            return result != null ? result : RDataFactory.createEmptyStringVector();
-        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 61b20ae0af..e5c570b5d0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.builtin;
 
 import java.util.Arrays;
-import java.util.function.Consumer;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerAsserts;
@@ -157,8 +156,7 @@ public final class CastBuilder {
      *
      * In the pre-initial phase one can configure the overall behavior of the pipeline. Currently,
      * only the default handling of {@code RNull} and {@code RMissing} values can be overridden (the
-     * default behavior is explained below). The pipeline can be configured using
-     * {@link PreinitialPhaseBuilder#conf(Consumer)} or any other method of the
+     * default behavior is explained below). The pipeline can be configured using any method of the
      * {@link PreinitialPhaseBuilder} class, e.g. {@link PreinitialPhaseBuilder#allowNull()}.
      * </p>
      * <p>
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 2bb4cee421..c98d7398d3 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
@@ -41,6 +41,7 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.ffi.ParseResult.ParseStatus;
+import com.oracle.truffle.r.nodes.function.ImplicitClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RCleanUp;
@@ -62,8 +63,6 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleSequence;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -299,26 +298,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     public static RStringVector getClassHr(Object v) {
-        RStringVector result;
-        if (v instanceof RAttributable) {
-            result = ((RAttributable) v).getClassHierarchy();
-        } else if (v instanceof Byte) {
-            result = RLogicalVector.implicitClassHeader;
-        } else if (v instanceof String) {
-            result = RStringVector.implicitClassHeader;
-        } else if (v instanceof Integer) {
-            result = RIntVector.implicitClassHeader;
-        } else if (v instanceof Double) {
-            result = RDoubleVector.implicitClassHeader;
-        } else if (v instanceof RComplex) {
-            result = RComplexVector.implicitClassHeader;
-        } else if (v instanceof RRaw) {
-            result = RRawVector.implicitClassHeader;
-        } else {
-            guaranteeInstanceOf(v, RNull.class);
-            result = RNull.implicitClassHeader;
-        }
-        return result;
+        return ImplicitClassHierarchyNode.getImplicitClass(v);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index d13dd5cb8e..8988230c91 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -38,19 +38,18 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.nodes.unary.UnaryNode;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -58,10 +57,36 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class ClassHierarchyNode extends UnaryNode {
 
+    /**
+     * Returns the value of the {@code class} attribute or empty {@link RStringVector} if class
+     * attribute is not set.
+     */
+    @TruffleBoundary
+    public static RStringVector getClassHierarchy(RAttributable value) {
+        Object v = value.getAttr(RRuntime.CLASS_ATTR_KEY);
+        RStringVector result = v instanceof RStringVector ? (RStringVector) v : ImplicitClassHierarchyNode.getImplicitClass(value);
+        return result != null ? result : RDataFactory.createEmptyStringVector();
+    }
+
+    /**
+     * Returns {@code true} if the {@code class} attribute is set to {@link RStringVector} whose
+     * first element equals to the given className.
+     */
+    public static boolean hasClass(RAttributable value, String className) {
+        RStringVector v = getClassHierarchy(value);
+        for (int i = 0; i < v.getLength(); ++i) {
+            if (v.getDataAt(i).equals(className)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private static final RStringVector truffleObjectClassHeader = RDataFactory.createStringVectorFromScalar("truffle.object");
 
     @Child private GetFixedAttributeNode access;
     @Child private S4Class s4Class;
+    @Child private ImplicitClassHierarchyNode implicit;
 
     private final boolean withImplicitTypes;
     private final boolean withS4;
@@ -78,41 +103,50 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return ClassHierarchyNodeGen.create(false, false);
     }
 
+    public static ClassHierarchyNode createWithImplicit() {
+        return ClassHierarchyNodeGen.create(true, false);
+    }
+
     public abstract RStringVector execute(Object arg);
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") byte arg) {
-        return withImplicitTypes ? RLogicalVector.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Logical) : null;
     }
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") String arg) {
-        return withImplicitTypes ? RStringVector.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Character) : null;
     }
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") int arg) {
-        return withImplicitTypes ? RIntVector.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Integer) : null;
     }
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") double arg) {
-        return withImplicitTypes ? RDoubleVector.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Double) : null;
     }
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") RComplex arg) {
-        return withImplicitTypes ? RComplexVector.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Complex) : null;
+    }
+
+    @Specialization
+    protected RStringVector getClassHr(@SuppressWarnings("unused") RRaw arg) {
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Raw) : null;
     }
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") RNull arg) {
-        return withImplicitTypes ? RNull.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null;
     }
 
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") REmpty arg) {
-        return withImplicitTypes ? RNull.implicitClassHeader : null;
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null;
     }
 
     @Specialization
@@ -147,7 +181,15 @@ public abstract class ClassHierarchyNode extends UnaryNode {
                 return classHierarchy;
             }
         }
-        return withImplicitTypes ? argProfile.profile(arg).getImplicitClass() : null;
+        if (withImplicitTypes) {
+            if (implicit == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                implicit = insert(ImplicitClassHierarchyNodeGen.create());
+            }
+            return implicit.execute(arg);
+        } else {
+            return null;
+        }
     }
 
     protected static boolean isRTypedValue(Object obj) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java
index 8f47695a8a..53096fef44 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java
@@ -47,7 +47,7 @@ public abstract class ClassHierarchyScalarNode extends UnaryNode {
 
         Object v = RRuntime.asAbstractVector(arg);
         if (v instanceof RAttributable) {
-            RStringVector classHierarchy = ((RAttributable) v).getClassHierarchy();
+            RStringVector classHierarchy = ClassHierarchyNode.getClassHierarchy((RAttributable) v);
             return classHierarchy.getLength() == 0 ? "" : classHierarchy.getDataAt(0);
         } else if (arg == RNull.instance) {
             return "NULL";
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java
new file mode 100644
index 0000000000..88e4949d7d
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ImplicitClassHierarchyNode.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.function;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
+import com.oracle.truffle.r.nodes.unary.UnaryNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
+
+public abstract class ImplicitClassHierarchyNode extends UnaryNode {
+
+    private static final RStringVector implicitArrayClass = ShareObjectNode.sharePermanent(RDataFactory.createStringVector("array"));
+    private static final RStringVector implicitMatrixClass = ShareObjectNode.sharePermanent(RDataFactory.createStringVector("matrix"));
+    @CompilationFinal(dimensions = 1) private static final RStringVector[] implicitClasses = new RStringVector[RType.values().length];
+
+    public static RStringVector getImplicitClass(RType type) {
+        RStringVector result = implicitClasses[type.ordinal()];
+        if (result == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            implicitClasses[type.ordinal()] = result = ShareObjectNode.sharePermanent(RDataFactory.createStringVector(type.getClazz()));
+        }
+        return result;
+    }
+
+    public abstract RStringVector execute(Object arg);
+
+    @Specialization
+    protected static RStringVector get(@SuppressWarnings("unused") int value) {
+        return getImplicitClass(RType.Integer);
+    }
+
+    @Specialization
+    protected static RStringVector get(@SuppressWarnings("unused") double value) {
+        return getImplicitClass(RType.Double);
+    }
+
+    @Specialization
+    protected static RStringVector get(@SuppressWarnings("unused") String value) {
+        return getImplicitClass(RType.Character);
+    }
+
+    @Specialization
+    protected static RStringVector get(@SuppressWarnings("unused") byte value) {
+        return getImplicitClass(RType.Logical);
+    }
+
+    @Specialization(limit = "5", guards = "value.getClass() == valueClass")
+    protected static RStringVector getCachedClass(RTypedValue value,
+                    @Cached("value.getClass()") Class<? extends RTypedValue> valueClass,
+                    @Cached("createBinaryProfile()") ConditionProfile isArray,
+                    @Cached("createBinaryProfile()") ConditionProfile isMatrix,
+                    @Cached("create()") GetDimAttributeNode getDim) {
+        return getCachedType(value, valueClass.cast(value).getRType(), isArray, isMatrix, getDim);
+    }
+
+    @Specialization(replaces = "getCachedClass", limit = "5", guards = "value.getRType() == type")
+    protected static RStringVector getCachedType(RTypedValue value,
+                    @Cached("value.getRType()") RType type,
+                    @Cached("createBinaryProfile()") ConditionProfile isArray,
+                    @Cached("createBinaryProfile()") ConditionProfile isMatrix,
+                    @Cached("create()") GetDimAttributeNode getDim) {
+        int[] dimensions = getDim.getDimensions(value);
+        if (isMatrix.profile(GetDimAttributeNode.isMatrix(dimensions))) {
+            return implicitMatrixClass;
+        } else if (isArray.profile(GetDimAttributeNode.isArray(dimensions))) {
+            return implicitArrayClass;
+        } else {
+            return getImplicitClass(type);
+        }
+    }
+
+    @Specialization(replaces = {"getCachedClass", "getCachedType"})
+    protected static RStringVector get(RTypedValue value,
+                    @Cached("createBinaryProfile()") ConditionProfile isArray,
+                    @Cached("createBinaryProfile()") ConditionProfile isMatrix,
+                    @Cached("create()") GetDimAttributeNode getDim) {
+        return getCachedType(value, value.getRType(), isArray, isMatrix, getDim);
+    }
+
+    public static RStringVector getImplicitClass(Object value) {
+        CompilerAsserts.neverPartOfCompilation();
+        if (value instanceof Integer) {
+            return getImplicitClass(RType.Integer);
+        } else if (value instanceof Double) {
+            return getImplicitClass(RType.Double);
+        } else if (value instanceof String) {
+            return getImplicitClass(RType.Character);
+        } else if (value instanceof Byte) {
+            return getImplicitClass(RType.Logical);
+        } else if (value instanceof RAttributable) {
+            RAttributable attributable = (RAttributable) value;
+            RIntVector dim = (RIntVector) attributable.getAttr(RRuntime.DIM_ATTR_KEY);
+            if (dim != null) {
+                int[] dimArray = dim.getInternalStore();
+                if (GetDimAttributeNode.isMatrix(dimArray)) {
+                    return implicitMatrixClass;
+                } else if (GetDimAttributeNode.isArray(dimArray)) {
+                    return implicitArrayClass;
+                }
+            }
+        }
+        return getImplicitClass(((RTypedValue) value).getRType());
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java
index 5cf4bb815a..2c8de03f94 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
index e32163ff72..e4e82a96e6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
@@ -24,9 +24,11 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -137,8 +139,9 @@ public abstract class ToStringNode extends RBaseNode {
     }
 
     @Specialization
-    protected String toString(RS4Object obj, @SuppressWarnings("unused") boolean quotes, String separator) {
-        RStringVector classHierarchy = obj.getClassHierarchy();
+    protected String toString(RS4Object obj, @SuppressWarnings("unused") boolean quotes, String separator,
+                    @Cached(value = "createWithImplicit()") ClassHierarchyNode hierarchy) {
+        RStringVector classHierarchy = hierarchy.execute(obj);
         Object clazz;
         if (classHierarchy.getLength() > 0) {
             clazz = toString(classHierarchy.getDataAt(0), true, separator);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
index 8f0de5aaee..534423533d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 9b2ea12cf9..412cd0b07e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -425,7 +425,7 @@ public class RErrorHandling {
 
     private static RPairList findConditionHandler(RList cond) {
         // GnuR checks whether this is a string vector - in FastR it's statically typed to be
-        RStringVector classes = cond.getClassHierarchy();
+        RAbstractStringVector classes = RContext.getRRuntimeASTAccess().getClassHierarchy(cond);
         Object list = getHandlerStack();
         while (list != RNull.instance) {
             RPairList pList = (RPairList) list;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 9d4b1dd7de..8104d4e5a0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,7 +21,6 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
@@ -821,15 +820,6 @@ public class RRuntime {
         }
     }
 
-    /**
-     * Returns {@code true} if the given object is R object and its class attribute contains given
-     * class.
-     */
-    @TruffleBoundary
-    public static boolean hasRClass(Object obj, String rclassName) {
-        return obj instanceof RAttributable && ((RAttributable) obj).hasClass(rclassName);
-    }
-
     public static boolean checkType(Object obj, RType type) {
         if (type == RType.Any) {
             return true;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
index 835b3d36e2..15c84e15e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -201,4 +203,5 @@ public interface RRuntimeASTAccess {
 
     void checkDebugRequest(RFunction func);
 
+    RAbstractStringVector getClassHierarchy(RAttributable value);
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
index 9487504ff9..4c08a3aae0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
@@ -33,13 +33,13 @@ public enum RType {
     Function("function", -1),
     Matrix("matrix", -1),
     Array("array", -1),
-    Closure("closure", -1),
-    Builtin("builtin", -1),
-    Special("special", -1),
-    Symbol("symbol", -1),
+    Closure("closure", "function", -1),
+    Builtin("builtin", "function", -1),
+    Special("special", "function", -1),
+    Symbol("symbol", "name", -1),
     Environment("environment", -1),
     PairList("pairlist", -1),
-    Language("language", -1),
+    Language("language", "call", -1),
     Promise("promise", -1),
     DefunctReal("real", -1),
     DefunctSingle("single", -1),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java
index 661b24b02d..dd34471c65 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.data;
 import java.util.Iterator;
 
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -53,33 +52,6 @@ public interface RAttributable extends RTypedValue {
      */
     DynamicObject getAttributes();
 
-    /**
-     * Returns the value of the {@code class} attribute or empty {@link RStringVector} if class
-     * attribute is not set.
-     */
-    @TruffleBoundary
-    default RStringVector getClassHierarchy() {
-        Object v = getAttr(RRuntime.CLASS_ATTR_KEY);
-        RStringVector result = v instanceof RStringVector ? (RStringVector) v : getImplicitClass();
-        return result != null ? result : RDataFactory.createEmptyStringVector();
-    }
-
-    /**
-     * Returns {@code true} if the {@code class} attribute is set to {@link RStringVector} whose
-     * first element equals to the given className.
-     */
-    default boolean hasClass(String className) {
-        RStringVector v = getClassHierarchy();
-        for (int i = 0; i < v.getLength(); ++i) {
-            if (v.getDataAt(i).equals(className)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    RStringVector getImplicitClass();
-
     /**
      * Get the value of an attribute. Returns {@code null} if not set.
      */
@@ -152,7 +124,6 @@ public interface RAttributable extends RTypedValue {
 
     /**
      * Returns {@code true} if and only if the value has a {@code class} attribute added explicitly.
-     * When {@code true}, it is possible to call {@link RAttributable#getClassHierarchy()}.
      */
     default boolean isObject() {
         return getClassAttr() != null ? true : false;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
index 0c8cd8620d..b02f1044bc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,4 @@ public abstract class RAttributeStorage extends RBaseObject implements RAttribut
     public final void initAttributes(DynamicObject newAttributes) {
         this.attributes = newAttributes;
     }
-
-    @Override
-    public abstract RStringVector getImplicitClass();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
index c075adf537..5e7b39ec45 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
@@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RComplexVector extends RVector<double[]> implements RAbstractComplexVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Complex.getClazz());
-
     private final double[] data;
 
     RComplexVector(double[] data, boolean complete, int[] dims, RStringVector names) {
@@ -195,9 +193,4 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
         data[toIndex2] = value.getRealPart();
         data[toIndex2 + 1] = value.getImaginaryPart();
     }
-
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
index 3c928c8607..2cf039de07 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
@@ -107,11 +107,6 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
         return this.internalCreateVector();
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return RDoubleVector.implicitClassHeader;
-    }
-
     @Override
     public RDoubleVector copyResized(int size, boolean fillNA) {
         double[] data = new double[size];
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
index 7023ee9876..e4eace8649 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
@@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RDoubleVector extends RVector<double[]> implements RAbstractDoubleVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Double.getClazz());
-
     private final double[] data;
 
     RDoubleVector(double[] data, boolean complete, int[] dims, RStringVector names) {
@@ -210,9 +208,4 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
     public Object getDataAtAsObject(int index) {
         return getDataAt(index);
     }
-
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index dd428cc24a..4c064cf3cb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -30,8 +30,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class RExpression extends RListBase implements RAbstractVector {
 
-    private static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Expression.getClazz());
-
     RExpression(Object[] data, int[] dims, RStringVector names) {
         super(data, dims, names);
     }
@@ -83,8 +81,4 @@ public final class RExpression extends RListBase implements RAbstractVector {
         return RDataFactory.createExpression(copyResizedData(size, fillNA), dimensions);
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
index eddf195c7b..639450e744 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -92,10 +92,4 @@ public class RExternalPtr extends RAttributeStorage implements RTypedValue {
         return RType.ExternalPtr;
     }
 
-    private static final RStringVector implicitClass = RDataFactory.createStringVector(RType.ExternalPtr.getName());
-
-    @Override
-    public final RStringVector getImplicitClass() {
-        return implicitClass;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
index 463191fceb..6aa8daa0c0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
@@ -102,13 +102,6 @@ public final class RFunction extends RSharingAttributeStorage implements RTypedV
         return enclosingFrame;
     }
 
-    private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RType.Function.getName());
-
-    @Override
-    public RStringVector getImplicitClass() {
-        return implicitClass;
-    }
-
     @Override
     public String toString() {
         return target.toString();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
index 40a643c725..a5aea4b6f6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
@@ -112,11 +112,6 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
         return this.internalCreateVector();
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return RIntVector.implicitClassHeader;
-    }
-
     @Override
     public RIntVector copyResized(int size, boolean fillNA) {
         int[] data = new int[size];
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
index 3dcce42962..8fa15af2a3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
@@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RIntVector extends RVector<int[]> implements RAbstractIntVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Integer.getClazz());
-
     private final int[] data;
 
     RIntVector(int[] data, boolean complete, int[] dims, RStringVector names) {
@@ -210,11 +208,6 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
         return getDataAt(index);
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
-
     @Override
     public void setElement(int i, Object value) {
         data[i] = (int) value;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index d58525dcf8..ed06179415 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -225,11 +225,6 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         attr.setAttr(RRuntime.ROWNAMES_ATTR_KEY, rowNames);
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return RDataFactory.createStringVector(RRuntime.CLASS_LANGUAGE);
-    }
-
     @Override
     public RLanguage copy() {
         RLanguage l = new RLanguage(getRep(), this.length);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
index 781e73dc4a..e0dea79dbd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
@@ -25,13 +25,10 @@ package com.oracle.truffle.r.runtime.data;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 
 public final class RList extends RListBase implements RAbstractListVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.List.getClazz());
-
     public String elementNamePrefix;
 
     RList(Object[] data, int[] dims, RStringVector names) {
@@ -83,8 +80,4 @@ public final class RList extends RListBase implements RAbstractListVector {
         return RDataFactory.createList(copyResizedData(size, fillNA), dimensions);
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
index fead808381..ed3fc3d959 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
@@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RLogicalVector extends RVector<byte[]> implements RAbstractLogicalVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Logical.getClazz());
-
     private final byte[] data;
 
     RLogicalVector(byte[] data, boolean complete, int[] dims, RStringVector names) {
@@ -209,8 +207,4 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
         return getDataAt(index);
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java
index 744db91b57..c006c4d9ef 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,6 @@ import com.oracle.truffle.r.runtime.RType;
 
 public final class RNull extends RScalar {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Null.getName());
-
     public static final RNull instance = new RNull();
 
     private RNull() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index 35f18166cb..18c853f56a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -351,11 +351,6 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         throw RInternalError.unimplemented();
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return RDataFactory.createStringVector(RType.PairList.getName());
-    }
-
     @Override
     public boolean isObject() {
         return false;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
index 66437ffcea..85c9947b3c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
@@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RRawVector extends RVector<byte[]> implements RAbstractRawVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Raw.getClazz());
-
     private final byte[] data;
 
     RRawVector(byte[] data, int[] dims, RStringVector names) {
@@ -181,9 +179,4 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
     public Object getDataAtAsObject(int index) {
         return getDataAt(index);
     }
-
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java
index 9fca460896..1f706daf9e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RS4Object.java
@@ -30,17 +30,10 @@ import com.oracle.truffle.r.runtime.RType;
  */
 public final class RS4Object extends RSharingAttributeStorage {
 
-    private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar("S4");
-
     public RS4Object() {
         setS4();
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return implicitClass;
-    }
-
     @Override
     public RType getRType() {
         return RType.S4Object;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
index f7e89244ce..80f1da3147 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java
@@ -31,16 +31,6 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector {
 
     public abstract boolean isNA();
 
-    @Override
-    public final RStringVector getClassHierarchy() {
-        return RDataFactory.createStringVector(getRType().getName());
-    }
-
-    @Override
-    public final RStringVector getImplicitClass() {
-        return RDataFactory.createStringVector(getRType().getName());
-    }
-
     @Override
     public final RScalarVector copy() {
         return this;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
index 9c1ca7f7d8..d9aa895489 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java
@@ -172,11 +172,6 @@ public abstract class RSequence implements RAbstractVector {
         return false;
     }
 
-    @Override
-    public final RStringVector getClassHierarchy() {
-        return getImplicitClass();
-    }
-
     @Override
     public final RTypedValue getNonShared() {
         return materialize().getNonShared();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
index a327638578..32e0a2c866 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
@@ -36,8 +36,6 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public final class RStringVector extends RVector<String[]> implements RAbstractStringVector {
 
-    public static final RStringVector implicitClassHeader = RDataFactory.createStringVectorFromScalar(RType.Character.getClazz());
-
     private final String[] data;
 
     RStringVector(String[] data, boolean complete, int[] dims, RStringVector names) {
@@ -201,11 +199,6 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
         return getDataAt(index);
     }
 
-    @Override
-    public RStringVector getImplicitClass() {
-        return getClassHierarchyHelper(implicitClassHeader);
-    }
-
     @Override
     public void setElement(int i, Object value) {
         data[i] = (String) value;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
index 378b61fb82..ad8f31449e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 
 /**
@@ -55,13 +54,6 @@ public final class RSymbol extends RAttributeStorage {
         return name;
     }
 
-    private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RRuntime.CLASS_SYMBOL);
-
-    @Override
-    public RStringVector getImplicitClass() {
-        return implicitClass;
-    }
-
     public boolean isMissing() {
         return name.isEmpty();
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
index aa70a23503..9d00bf9472 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java
@@ -150,16 +150,6 @@ abstract class RToVectorClosure implements RAbstractVector {
         return getVector().isArray();
     }
 
-    @Override
-    public final RStringVector getClassHierarchy() {
-        return getVector().getClassHierarchy();
-    }
-
-    @Override
-    public RStringVector getImplicitClass() {
-        return getVector().getImplicitClass();
-    }
-
     @Override
     public final RTypedValue getNonShared() {
         return getVector().getNonShared();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index 4cf0176368..56100651dd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -105,13 +105,6 @@ import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess;
  */
 public abstract class REnvironment extends RAttributeStorage {
 
-    private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RType.Environment.getName());
-
-    @Override
-    public final RStringVector getImplicitClass() {
-        return implicitClass;
-    }
-
     public static final class ContextStateImpl implements RContext.ContextState {
         private final MaterializedFrame globalFrame;
         @CompilationFinal private Base baseEnv;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index b369e512dc..6650047ef0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -24,17 +24,15 @@ package com.oracle.truffle.r.runtime.nodes;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.LoopNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeVisitor;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RError.RErrorException;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -257,18 +255,6 @@ public abstract class RBaseNode extends Node {
         return value instanceof RLanguage;
     }
 
-    protected static boolean isRFormula(Object value) {
-        if (value instanceof RLanguage) {
-            return hasFormulaClass(value);
-        }
-        return false;
-    }
-
-    @TruffleBoundary
-    private static boolean hasFormulaClass(Object value) {
-        return ((RAttributable) value).hasClass(RRuntime.FORMULA_CLASS);
-    }
-
     protected static boolean isRExpression(Object value) {
         return value instanceof RExpression;
     }
-- 
GitLab


From 00e73fcb778f13ce22ed33ba0f792434c7bc9ccb Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Feb 2017 18:29:02 +0100
Subject: [PATCH 274/402] =?UTF-8?q?don=E2=80=99t=20call=20RBuiltinNode.exe?=
 =?UTF-8?q?cuteBuiltin=20from=20other=20nodes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../truffle/r/nodes/builtin/base/Assign.java  |  3 ++
 .../r/nodes/builtin/base/EnvFunctions.java    |  5 +-
 .../truffle/r/nodes/builtin/base/Gc.java      | 11 ++--
 .../r/nodes/builtin/base/GetFunctions.java    |  3 +-
 .../truffle/r/nodes/builtin/base/Mapply.java  | 53 +++++--------------
 .../r/nodes/builtin/base/TraceFunctions.java  |  6 +++
 .../base/fastpaths/AssignFastPath.java        |  8 +--
 .../system/ContextSystemFunctionFactory.java  |  2 +-
 .../r/nodes/builtin/fastr/FastRContext.java   |  3 ++
 .../r/nodes/builtin/fastr/FastRTrace.java     |  8 +--
 .../nodes/test/BinaryArithmeticNodeTest.java  |  2 +-
 .../r/nodes/binary/BinaryArithmeticNode.java  | 12 +++--
 12 files changed, 51 insertions(+), 65 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
index 7daef2edc8..fd5c01570f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
@@ -30,6 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.LoopNode;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -65,6 +66,8 @@ public abstract class Assign extends RBuiltinNode {
         this.direct = direct;
     }
 
+    public abstract Object execute(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, byte inherits);
+
     @Override
     public RBaseNode getErrorContext() {
         return direct ? this : super.getErrorContext();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index c3e0789b43..1883d63bc9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -238,6 +238,8 @@ public class EnvFunctions {
 
         @Child private FrameFunctions.ParentFrame parentFrameNode;
 
+        public abstract Object execute(VirtualFrame frame, Object execute, Object instance);
+
         @Specialization
         protected REnvironment topEnv(REnvironment env, REnvironment matchThisEnv) {
             return doTopEnv(matchThisEnv, env);
@@ -270,7 +272,7 @@ public class EnvFunctions {
         }
 
         @TruffleBoundary
-        private static REnvironment doTopEnv(REnvironment target, final REnvironment envArg) {
+        private static REnvironment doTopEnv(REnvironment target, REnvironment envArg) {
             REnvironment env = envArg;
             while (env != REnvironment.emptyEnv()) {
                 if (env == target || env == REnvironment.globalEnv() || env == REnvironment.baseEnv() || env == REnvironment.baseNamespaceEnv() || env.isPackageEnv() != null || env.isNamespaceEnv() ||
@@ -281,6 +283,7 @@ public class EnvFunctions {
             }
             return REnvironment.globalEnv();
         }
+
     }
 
     @RBuiltin(name = "parent.env", kind = INTERNAL, parameterNames = {"env"}, behavior = READS_FRAME)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
index ad8d21132c..f2dd9f3eb1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import java.util.Arrays;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -48,15 +47,13 @@ public abstract class Gc extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization
     protected RDoubleVector gc(boolean verbose, boolean reset) {
-        doGc();
+        /*
+         * It is rarely advisable to actually force a gc in Java, therefore we simply ignore this
+         * builtin.
+         */
         // TODO: somehow produce the (semi?) correct values
         double[] data = new double[14];
         Arrays.fill(data, RRuntime.DOUBLE_NA);
         return RDataFactory.createDoubleVector(data, RDataFactory.INCOMPLETE_VECTOR);
     }
-
-    @TruffleBoundary
-    private static void doGc() {
-        System.gc();
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index 42030e3dde..1293084d77 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -164,7 +164,7 @@ public class GetFunctions {
 
         private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile();
 
-        public abstract Object execute(VirtualFrame frame, String x, REnvironment environment, String mode, boolean inherits);
+        public abstract Object execute(VirtualFrame frame, Object what, Object where, String name, boolean inherits);
 
         static {
             Casts casts = new Casts(Get.class);
@@ -196,6 +196,7 @@ public class GetFunctions {
         protected Object get(VirtualFrame frame, String x, int envir, String mode, boolean inherits) {
             throw RInternalError.unimplemented();
         }
+
     }
 
     @RBuiltin(name = "get0", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits", "ifnotfound"}, behavior = COMPLEX)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
index f51a45e0d9..4a40c0ac4d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
@@ -35,25 +35,23 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
+import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.MapplyNodeGen.MapplyInternalNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.Subscript;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SubscriptNodeGen;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode;
 import com.oracle.truffle.r.runtime.AnonymousFrameVariable;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -78,7 +76,7 @@ public abstract class Mapply extends RBuiltinNode {
 
     protected static final class ElementNode extends Node {
         @Child private Length lengthNode;
-        @Child private Subscript indexedLoadNode;
+        @Child private ExtractVectorNode extractNode;
         @Child private WriteVariableNode writeVectorElementNode;
         private final String vectorElementName;
         private final String argName;
@@ -87,7 +85,7 @@ public abstract class Mapply extends RBuiltinNode {
             // the name is a hack to treat ReadVariableNode-s as syntax nodes
             this.vectorElementName = "*" + AnonymousFrameVariable.create(vectorElementName);
             this.lengthNode = insert(LengthNodeGen.create());
-            this.indexedLoadNode = insert(SubscriptNodeGen.create());
+            this.extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false));
             this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, Mode.REGULAR, null));
             this.argName = argName;
         }
@@ -110,8 +108,6 @@ public abstract class Mapply extends RBuiltinNode {
     public abstract static class MapplyInternalNode extends Node implements InternalRSyntaxNodeChildren {
 
         private static final String VECTOR_ELEMENT_PREFIX = "MAPPLY_VEC_ELEM_";
-        private static final RLogicalVector DROP = RDataFactory.createLogicalVectorFromScalar(true);
-        private static final RLogicalVector EXACT = RDataFactory.createLogicalVectorFromScalar(true);
         private static final ArgumentsSignature I_INDEX = ArgumentsSignature.get("i");
         private static final RArgsValuesAndNames[] INDEX_CACHE = new RArgsValuesAndNames[32];
 
@@ -125,33 +121,8 @@ public abstract class Mapply extends RBuiltinNode {
 
         public abstract Object[] execute(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector additionalArguments);
 
-        private static Object getVecElement(VirtualFrame frame, RAbstractListVector dots, int i, int listIndex, int[] lengths, Subscript indexedLoadNode) {
-            Object listElem = dots.getDataAt(listIndex);
-            RAbstractContainer vec = null;
-            if (listElem instanceof RAbstractContainer) {
-                vec = (RAbstractContainer) listElem;
-            } else {
-                // TODO scalar types are a nuisance!
-                if (listElem instanceof String) {
-                    vec = RDataFactory.createStringVectorFromScalar((String) listElem);
-                } else if (listElem instanceof Integer) {
-                    vec = RDataFactory.createIntVectorFromScalar((int) listElem);
-                } else if (listElem instanceof Double) {
-                    vec = RDataFactory.createDoubleVectorFromScalar((double) listElem);
-                } else {
-                    throw RInternalError.unimplemented();
-                }
-            }
-
-            int adjIndex = i % lengths[listIndex];
-            RArgsValuesAndNames indexArg;
-            if (adjIndex < INDEX_CACHE.length) {
-                indexArg = INDEX_CACHE[adjIndex];
-            } else {
-                indexArg = new RArgsValuesAndNames(new Object[]{adjIndex + 1}, I_INDEX);
-            }
-            return indexedLoadNode.executeBuiltin(frame, vec, indexArg, EXACT, DROP);
-
+        private static Object getVecElement(VirtualFrame frame, RAbstractListVector dots, int i, int listIndex, int[] lengths, ExtractVectorNode extractNode) {
+            return extractNode.apply(frame, dots.getDataAt(listIndex), new Object[]{i % lengths[listIndex] + 1}, RLogical.TRUE, RLogical.TRUE);
         }
 
         @SuppressWarnings("unused")
@@ -183,7 +154,7 @@ public abstract class Mapply extends RBuiltinNode {
             for (int i = 0; i < maxLength; i++) {
                 /* Evaluate and store the arguments */
                 for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
-                    Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].indexedLoadNode);
+                    Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].extractNode);
                     cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement);
                 }
                 /* Now call the function */
@@ -195,7 +166,7 @@ public abstract class Mapply extends RBuiltinNode {
         @Specialization(replaces = "cachedMApply")
         protected Object[] mApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs,
                         @Cached("create()") RLengthNode lengthNode,
-                        @Cached("createIndexedLoadNode()") Subscript indexedLoadNode,
+                        @Cached("createExtractNode()") ExtractVectorNode extractNode,
                         @Cached("create()") RExplicitCallNode callNode) {
             int dotsLength = dots.getLength();
             int moreArgsLength = moreArgs.getLength();
@@ -226,7 +197,7 @@ public abstract class Mapply extends RBuiltinNode {
             for (int i = 0; i < maxLength; i++) {
                 /* Evaluate and store the arguments */
                 for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
-                    Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, indexedLoadNode);
+                    Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, extractNode);
                     values[listIndex] = vecElement;
                 }
                 /* Now call the function */
@@ -265,8 +236,8 @@ public abstract class Mapply extends RBuiltinNode {
             return elementNodes;
         }
 
-        protected Subscript createIndexedLoadNode() {
-            return SubscriptNodeGen.create();
+        protected ExtractVectorNode createExtractNode() {
+            return ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
         }
 
         protected boolean sameNames(RAbstractListVector list, RAbstractListVector cachedList) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
index c5d7ba1322..13ee96c682 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
@@ -91,6 +91,8 @@ public class TraceFunctions {
             createCasts(PrimTrace.class);
         }
 
+        public abstract Object execute(VirtualFrame frame, RFunction func);
+
         @Specialization
         protected RNull primTrace(VirtualFrame frame, RAbstractStringVector funcName) {
             return primTrace((RFunction) getFunction(frame, funcName.getDataAt(0)));
@@ -106,6 +108,7 @@ public class TraceFunctions {
             }
             return RNull.instance;
         }
+
     }
 
     @RBuiltin(name = ".primUntrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX)
@@ -115,6 +118,8 @@ public class TraceFunctions {
             createCasts(PrimUnTrace.class);
         }
 
+        public abstract void execute(VirtualFrame frame, RFunction func);
+
         @Specialization
         protected RNull primUnTrace(VirtualFrame frame, RAbstractStringVector funcName) {
             return primUnTrace((RFunction) getFunction(frame, funcName.getDataAt(0)));
@@ -128,6 +133,7 @@ public class TraceFunctions {
             }
             return RNull.instance;
         }
+
     }
 
     @RBuiltin(name = "traceOnOff", kind = INTERNAL, parameterNames = "state", behavior = COMPLEX)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java
index 377add3724..7912423f9b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java
@@ -40,25 +40,25 @@ public abstract class AssignFastPath extends RFastPathNode {
     @Specialization
     @SuppressWarnings("unused")
     protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, RMissing pos, REnvironment envir, byte inherits, Object immediate) {
-        return assign.executeBuiltin(frame, x, value, envir, inherits);
+        return assign.execute(frame, x, value, envir, inherits);
     }
 
     @Specialization
     @SuppressWarnings("unused")
     protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, RMissing pos, REnvironment envir, RMissing inherits, Object immediate) {
-        return assign.executeBuiltin(frame, x, value, envir, RRuntime.LOGICAL_FALSE);
+        return assign.execute(frame, x, value, envir, RRuntime.LOGICAL_FALSE);
     }
 
     @Specialization
     @SuppressWarnings("unused")
     protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, RMissing envir, byte inherits, Object immediate) {
-        return assign.executeBuiltin(frame, x, value, pos, inherits);
+        return assign.execute(frame, x, value, pos, inherits);
     }
 
     @Specialization
     @SuppressWarnings("unused")
     protected Object assign(VirtualFrame frame, RAbstractStringVector x, Object value, REnvironment pos, RMissing envir, RMissing inherits, Object immediate) {
-        return assign.executeBuiltin(frame, x, value, pos, RRuntime.LOGICAL_FALSE);
+        return assign.execute(frame, x, value, pos, RRuntime.LOGICAL_FALSE);
     }
 
     @Fallback
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java
index a65602428e..cfb7d5c70a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/ContextSystemFunctionFactory.java
@@ -59,7 +59,7 @@ public class ContextSystemFunctionFactory extends SystemFunctionFactory {
         @Specialization
         protected Object systemFunction(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern) {
             initContextRNode();
-            Object result = contextRNode.executeBuiltin(frame, args, env, intern);
+            Object result = contextRNode.execute(frame, args, env, intern);
             return result;
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 58ec42838e..097b1660ef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -36,6 +36,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
@@ -237,6 +238,8 @@ public class FastRContext {
             casts.arg("intern").asLogicalVector().findFirst().map(toBoolean());
         }
 
+        public abstract Object execute(VirtualFrame frame, RAbstractStringVector args, RAbstractStringVector env, boolean intern);
+
         @Specialization
         @TruffleBoundary
         protected Object r(RAbstractStringVector args, RAbstractStringVector env, boolean intern) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index e719605f9e..240f7c85d2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -77,7 +77,7 @@ public class FastRTrace {
                 topEnv = insert(TopEnvNodeGen.create());
                 parentFrame = insert(ParentFrameNodeGen.create());
             }
-            return topEnv.executeBuiltin(frame, parentFrame.execute(frame, 1), RNull.instance);
+            return topEnv.execute(frame, parentFrame.execute(frame, 1), RNull.instance);
         }
 
         protected Object getFunction(VirtualFrame frame, Object what, Object where) {
@@ -85,7 +85,7 @@ public class FastRTrace {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 getNode = insert(GetNodeGen.create());
             }
-            return getNode.executeBuiltin(frame, what, where, RType.Function.getName(), true);
+            return getNode.execute(frame, what, where, RType.Function.getName(), true);
         }
 
         protected void checkWhat(Object what) {
@@ -140,7 +140,7 @@ public class FastRTrace {
                     primTrace = insert(PrimTraceNodeGen.create());
                 }
 
-                Object result = primTrace.executeBuiltin(frame, func);
+                Object result = primTrace.execute(frame, func);
                 visibility.execute(frame, false);
                 return result;
             }
@@ -204,7 +204,7 @@ public class FastRTrace {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
                     primUnTrace = insert(PrimUnTraceNodeGen.create());
                 }
-                primUnTrace.executeBuiltin(frame, func);
+                primUnTrace.execute(frame, func);
             } else {
                 throw RError.nyi(this, "method tracing");
             }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java
index 7ba9410133..2b5c1143dd 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java
@@ -387,6 +387,6 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     private static NodeHandle<BinaryArithmeticNode> create(BinaryArithmeticFactory factory) {
         return createHandle(BinaryArithmeticNode.create(factory, null),
-                        (node, args) -> node.executeBuiltin(null, args[0], args[1]));
+                        (node, args) -> node.execute(args[0], args[1]));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index 96aa278a5a..20656b1d9d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -62,17 +62,19 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
     protected final BinaryArithmeticFactory binary;
     private final UnaryArithmeticFactory unary;
 
-    public BinaryArithmeticNode(BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
-        this.binary = binaryFactory;
-        this.unary = unaryFactory;
-    }
-
     static {
         Casts casts = new Casts(BinaryArithmeticNode.class);
         casts.arg(0).boxPrimitive();
         casts.arg(1).boxPrimitive();
     }
 
+    public BinaryArithmeticNode(BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
+        this.binary = binaryFactory;
+        this.unary = unaryFactory;
+    }
+
+    public abstract Object execute(Object left, Object right);
+
     @Override
     public RBaseNode getErrorContext() {
         return this;
-- 
GitLab


From 2825f2a0b2aff745f1ad1d43351399ae6391d0d9 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 28 Feb 2017 19:43:19 +0100
Subject: [PATCH 275/402] split RBuiltinNode into separate subclasses for
 different arities

---
 .../ffi/nfi/TruffleNFI_NativeArray.java       |   1 -
 .../interop/ffi/nfi/TruffleNFI_PkgInit.java   |   1 -
 .../fastrGrid/DoSetViewPortBuiltin.java       |   2 +-
 .../r/nodes/builtin/RBuiltinPackages.java     |  10 +-
 .../truffle/r/nodes/builtin/base/APerm.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Abbrev.java  |   2 +-
 .../r/nodes/builtin/base/AllNames.java        |   2 +-
 .../truffle/r/nodes/builtin/base/AnyNA.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Args.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Array.java   |   2 +-
 .../truffle/r/nodes/builtin/base/AsCall.java  |   2 +-
 .../r/nodes/builtin/base/AsCharacter.java     |   2 +-
 .../nodes/builtin/base/AsCharacterFactor.java |   2 +-
 .../r/nodes/builtin/base/AsComplex.java       |   2 +-
 .../r/nodes/builtin/base/AsDouble.java        |   2 +-
 .../r/nodes/builtin/base/AsFunction.java      |   2 +-
 .../r/nodes/builtin/base/AsInteger.java       |   2 +-
 .../r/nodes/builtin/base/AsLogical.java       |   2 +-
 .../truffle/r/nodes/builtin/base/AsRaw.java   |   2 +-
 .../r/nodes/builtin/base/AsVector.java        |   2 +-
 .../truffle/r/nodes/builtin/base/Assign.java  |   2 +-
 .../r/nodes/builtin/base/AttachFunctions.java |   4 +-
 .../truffle/r/nodes/builtin/base/Attr.java    |   2 +-
 .../r/nodes/builtin/base/Attributes.java      |   2 +-
 .../builtin/base/BaseGammaFunctions.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Bincode.java |   2 +-
 .../truffle/r/nodes/builtin/base/Bind.java    |   2 +-
 .../nodes/builtin/base/BitwiseFunctions.java  |  56 ++---
 .../truffle/r/nodes/builtin/base/Body.java    |   2 +-
 .../nodes/builtin/base/BrowserFunctions.java  |  34 ++-
 .../truffle/r/nodes/builtin/base/CRC64.java   |   2 +-
 .../r/nodes/builtin/base/CacheClass.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Call.java    |   2 +-
 .../r/nodes/builtin/base/Capabilities.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Cat.java     |   2 +-
 .../r/nodes/builtin/base/CharMatch.java       |   2 +-
 .../r/nodes/builtin/base/ChooseBuiltin.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Col.java     |   2 +-
 .../r/nodes/builtin/base/ColSumsBase.java     |   2 +-
 .../truffle/r/nodes/builtin/base/Colon.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Combine.java |   2 +-
 .../r/nodes/builtin/base/CommandArgs.java     |   2 +-
 .../nodes/builtin/base/CompileFunctions.java  |   4 +-
 .../truffle/r/nodes/builtin/base/Complex.java |   2 +-
 .../builtin/base/ConditionFunctions.java      |  59 ++---
 .../builtin/base/ConnectionFunctions.java     |  68 +++---
 .../r/nodes/builtin/base/Contributors.java    |   2 +-
 .../r/nodes/builtin/base/CopyDFAttr.java      |   2 +-
 .../r/nodes/builtin/base/Crossprod.java       |   2 +-
 .../truffle/r/nodes/builtin/base/CumMax.java  |   2 +-
 .../truffle/r/nodes/builtin/base/CumMin.java  |   2 +-
 .../truffle/r/nodes/builtin/base/CumProd.java |   2 +-
 .../truffle/r/nodes/builtin/base/CumSum.java  |   2 +-
 .../truffle/r/nodes/builtin/base/DPut.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Date.java    |   2 +-
 .../builtin/base/DatePOSIXFunctions.java      |  12 +-
 .../r/nodes/builtin/base/DebugFunctions.java  |  39 ++--
 .../r/nodes/builtin/base/DelayedAssign.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Deparse.java |   2 +-
 .../truffle/r/nodes/builtin/base/Diag.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Dim.java     |   2 +-
 .../r/nodes/builtin/base/DimNames.java        |   2 +-
 .../truffle/r/nodes/builtin/base/DoCall.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Drop.java    |   2 +-
 .../builtin/base/DuplicatedFunctions.java     | 112 ++++-----
 .../nodes/builtin/base/DynLoadFunctions.java  |  10 +-
 .../r/nodes/builtin/base/EncodeString.java    |   2 +-
 .../nodes/builtin/base/EncodingFunctions.java |   4 +-
 .../r/nodes/builtin/base/EnvFunctions.java    |  46 ++--
 .../truffle/r/nodes/builtin/base/Eval.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Exists.java  |   2 +-
 .../r/nodes/builtin/base/Expression.java      |   2 +-
 .../r/nodes/builtin/base/FileFunctions.java   |  36 +--
 .../r/nodes/builtin/base/ForceAndCall.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Formals.java |   5 +-
 .../truffle/r/nodes/builtin/base/Format.java  |   2 +-
 .../truffle/r/nodes/builtin/base/FormatC.java |   2 +-
 .../r/nodes/builtin/base/FrameFunctions.java  |  98 +++-----
 .../truffle/r/nodes/builtin/base/Gc.java      |   2 +-
 .../r/nodes/builtin/base/GetClass.java        |   2 +-
 .../r/nodes/builtin/base/GetFunctions.java    |  37 +--
 .../r/nodes/builtin/base/GetOldClass.java     |   2 +-
 .../truffle/r/nodes/builtin/base/GetText.java |   2 +-
 .../truffle/r/nodes/builtin/base/Getwd.java   |   2 +-
 .../r/nodes/builtin/base/GrepFunctions.java   | 214 ++++++++++--------
 .../builtin/base/HiddenInternalFunctions.java |  14 +-
 .../truffle/r/nodes/builtin/base/IConv.java   |   2 +-
 .../r/nodes/builtin/base/Identical.java       |   2 +-
 .../r/nodes/builtin/base/InheritsBuiltin.java |   2 +-
 .../r/nodes/builtin/base/IntToBits.java       |   2 +-
 .../r/nodes/builtin/base/IntToUtf8.java       |   2 +-
 .../r/nodes/builtin/base/Interactive.java     |   2 +-
 .../r/nodes/builtin/base/Internal.java        |   2 +-
 .../r/nodes/builtin/base/Invisible.java       |   2 +-
 .../truffle/r/nodes/builtin/base/IsATTY.java  |   2 +-
 .../nodes/builtin/base/IsFiniteFunctions.java |   2 +-
 .../r/nodes/builtin/base/IsListFactor.java    |   2 +-
 .../builtin/base/IsMethodsDispatchOn.java     |   2 +-
 .../truffle/r/nodes/builtin/base/IsNA.java    |   2 +-
 .../truffle/r/nodes/builtin/base/IsS4.java    |   2 +-
 .../r/nodes/builtin/base/IsSingle.java        |   2 +-
 .../r/nodes/builtin/base/IsTypeFunctions.java |   4 +-
 .../r/nodes/builtin/base/IsUnsorted.java      |   4 +-
 .../r/nodes/builtin/base/LaFunctions.java     |  38 ++--
 .../truffle/r/nodes/builtin/base/Lapply.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Length.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Lengths.java |   2 +-
 .../truffle/r/nodes/builtin/base/License.java |   2 +-
 .../r/nodes/builtin/base/List2Env.java        |   2 +-
 .../r/nodes/builtin/base/ListBuiltin.java     |   2 +-
 .../nodes/builtin/base/LoadSaveFunctions.java |   7 +-
 .../r/nodes/builtin/base/LocaleFunctions.java |  14 +-
 .../r/nodes/builtin/base/LogFunctions.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Ls.java      |   2 +-
 .../r/nodes/builtin/base/MakeNames.java       |   2 +-
 .../r/nodes/builtin/base/MakeUnique.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Mapply.java  |   2 +-
 .../truffle/r/nodes/builtin/base/MatMult.java |   2 +-
 .../truffle/r/nodes/builtin/base/Match.java   |   2 +-
 .../r/nodes/builtin/base/MatchArg.java        |   2 +-
 .../r/nodes/builtin/base/MatchFun.java        |   2 +-
 .../truffle/r/nodes/builtin/base/Matrix.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Max.java     |   2 +-
 .../truffle/r/nodes/builtin/base/Mean.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Merge.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Min.java     |   2 +-
 .../truffle/r/nodes/builtin/base/Missing.java |   2 +-
 .../truffle/r/nodes/builtin/base/NArgs.java   |   2 +-
 .../truffle/r/nodes/builtin/base/NChar.java   |   2 +-
 .../r/nodes/builtin/base/NGetText.java        |   2 +-
 .../truffle/r/nodes/builtin/base/NZChar.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Names.java   |   2 +-
 .../builtin/base/NamespaceFunctions.java      |  12 +-
 .../r/nodes/builtin/base/NormalizePath.java   |   2 +-
 .../builtin/base/NumericalFunctions.java      |   2 +-
 .../truffle/r/nodes/builtin/base/OnExit.java  |   2 +-
 .../nodes/builtin/base/OptionsFunctions.java  |   4 +-
 .../truffle/r/nodes/builtin/base/PMatch.java  |   2 +-
 .../truffle/r/nodes/builtin/base/PMinMax.java |   2 +-
 .../truffle/r/nodes/builtin/base/Parse.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Paste.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Paste0.java  |   2 +-
 .../r/nodes/builtin/base/PathExpand.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Pretty.java  |   2 +-
 .../r/nodes/builtin/base/Primitive.java       |   2 +-
 .../r/nodes/builtin/base/PrintFunctions.java  |   4 +-
 .../r/nodes/builtin/base/ProcTime.java        |   2 +-
 .../truffle/r/nodes/builtin/base/Prod.java    |   2 +-
 .../r/nodes/builtin/base/Quantifier.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Quit.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Quote.java   |   2 +-
 .../r/nodes/builtin/base/RNGFunctions.java    |   4 +-
 .../r/nodes/builtin/base/RVersion.java        |   2 +-
 .../truffle/r/nodes/builtin/base/Range.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Rank.java    |   2 +-
 .../r/nodes/builtin/base/RawFunctions.java    |   6 +-
 .../r/nodes/builtin/base/RawToBits.java       |   2 +-
 .../truffle/r/nodes/builtin/base/ReadDCF.java |   2 +-
 .../r/nodes/builtin/base/ReadREnviron.java    |   2 +-
 .../r/nodes/builtin/base/Readline.java        |   2 +-
 .../truffle/r/nodes/builtin/base/Recall.java  |   2 +-
 .../r/nodes/builtin/base/RecordGraphics.java  |   2 +-
 .../r/nodes/builtin/base/RegFinalizer.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Repeat.java  |   2 +-
 .../r/nodes/builtin/base/RepeatInternal.java  |   2 +-
 .../r/nodes/builtin/base/RepeatLength.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Return.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Rhome.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Rm.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Round.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Row.java     |   2 +-
 .../r/nodes/builtin/base/RowsumFunctions.java |   2 +-
 .../builtin/base/S3DispatchFunctions.java     |  69 +++---
 .../truffle/r/nodes/builtin/base/Sample.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Sample2.java |   2 +-
 .../truffle/r/nodes/builtin/base/Scan.java    |   2 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |  12 +-
 .../builtin/base/SerializeFunctions.java      |  88 +++----
 .../r/nodes/builtin/base/SetS4Object.java     |   2 +-
 .../r/nodes/builtin/base/SetTimeLimit.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Setwd.java   |   2 +-
 .../r/nodes/builtin/base/ShortRowNames.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Signif.java  |   2 +-
 .../r/nodes/builtin/base/SinkFunctions.java   |   4 +-
 .../truffle/r/nodes/builtin/base/Slot.java    |   2 +-
 .../r/nodes/builtin/base/SortFunctions.java   | 153 +++++++------
 .../truffle/r/nodes/builtin/base/Split.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Sprintf.java |   2 +-
 .../r/nodes/builtin/base/StandardGeneric.java |   2 +-
 .../builtin/base/StartsEndsWithFunctions.java |   2 +-
 .../truffle/r/nodes/builtin/base/Stop.java    |   2 +-
 .../truffle/r/nodes/builtin/base/Strrep.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Strtoi.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Strtrim.java |   2 +-
 .../r/nodes/builtin/base/Substitute.java      |   2 +-
 .../truffle/r/nodes/builtin/base/Substr.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Sum.java     |   2 +-
 .../truffle/r/nodes/builtin/base/Switch.java  |   2 +-
 .../r/nodes/builtin/base/SysFunctions.java    |  58 +++--
 .../r/nodes/builtin/base/Tabulate.java        |   2 +-
 .../truffle/r/nodes/builtin/base/TempDir.java |   2 +-
 .../r/nodes/builtin/base/TempFile.java        |   2 +-
 .../r/nodes/builtin/base/ToLowerOrUpper.java  |   4 +-
 .../r/nodes/builtin/base/TraceFunctions.java  | 131 ++++++-----
 .../r/nodes/builtin/base/Traceback.java       |   2 +-
 .../r/nodes/builtin/base/Transpose.java       |   2 +-
 .../nodes/builtin/base/TrigExpFunctions.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Trunc.java   |   2 +-
 .../truffle/r/nodes/builtin/base/Typeof.java  |   2 +-
 .../truffle/r/nodes/builtin/base/UnClass.java |   2 +-
 .../truffle/r/nodes/builtin/base/Unique.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Unlist.java  |   2 +-
 .../r/nodes/builtin/base/UpdateAttr.java      |   2 +-
 .../nodes/builtin/base/UpdateAttributes.java  |   2 +-
 .../r/nodes/builtin/base/UpdateClass.java     |   4 +-
 .../r/nodes/builtin/base/UpdateDim.java       |   2 +-
 .../r/nodes/builtin/base/UpdateDimNames.java  |   2 +-
 .../r/nodes/builtin/base/UpdateLength.java    |   2 +-
 .../r/nodes/builtin/base/UpdateLevels.java    |   2 +-
 .../r/nodes/builtin/base/UpdateNames.java     |   2 +-
 .../r/nodes/builtin/base/UpdateOldClass.java  |   2 +-
 .../r/nodes/builtin/base/UpdateSlot.java      |   2 +-
 .../nodes/builtin/base/UpdateStorageMode.java |   4 +-
 .../r/nodes/builtin/base/UpdateSubstr.java    |   2 +-
 .../r/nodes/builtin/base/Utf8ToInt.java       |   2 +-
 .../truffle/r/nodes/builtin/base/VApply.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Vector.java  |   2 +-
 .../truffle/r/nodes/builtin/base/Warning.java |   2 +-
 .../r/nodes/builtin/base/WhichFunctions.java  |   4 +-
 .../r/nodes/builtin/base/WithVisible.java     |   2 +-
 .../truffle/r/nodes/builtin/base/Xtfrm.java   |   2 +-
 .../foreign/CallAndExternalFunctions.java     |  56 +++--
 .../base/foreign/FortranAndCFunctions.java    |  26 +--
 .../builtin/base/foreign/LookupAdapter.java   |  37 ++-
 .../nodes/builtin/base/infix/AccessField.java |   2 +-
 .../builtin/base/infix/AssignBuiltin.java     |   2 +-
 .../builtin/base/infix/AssignBuiltinEq.java   |   2 +-
 .../base/infix/AssignOuterBuiltin.java        |   2 +-
 .../builtin/base/infix/BraceBuiltin.java      |   2 +-
 .../builtin/base/infix/BreakBuiltin.java      |   3 +-
 .../nodes/builtin/base/infix/ForBuiltin.java  |   2 +-
 .../builtin/base/infix/FunctionBuiltin.java   |   2 +-
 .../r/nodes/builtin/base/infix/IfBuiltin.java |   2 +-
 .../nodes/builtin/base/infix/NextBuiltin.java |   2 +-
 .../builtin/base/infix/ParenBuiltin.java      |   6 +-
 .../builtin/base/infix/RepeatBuiltin.java     |   2 +-
 .../r/nodes/builtin/base/infix/Subscript.java |   2 +-
 .../r/nodes/builtin/base/infix/Subset.java    |   2 +-
 .../r/nodes/builtin/base/infix/Tilde.java     |   2 +-
 .../nodes/builtin/base/infix/UpdateField.java |   2 +-
 .../builtin/base/infix/UpdateSubscript.java   |   2 +-
 .../builtin/base/infix/UpdateSubset.java      |   2 +-
 .../builtin/base/infix/WhileBuiltin.java      |   2 +-
 .../builtin/base/system/SystemFunction.java   |   2 +-
 .../r/nodes/builtin/fastr/FastRContext.java   |  26 +--
 .../r/nodes/builtin/fastr/FastRDebug.java     |   2 +-
 .../r/nodes/builtin/fastr/FastRIdentity.java  |   2 +-
 .../r/nodes/builtin/fastr/FastRInspect.java   |   2 +-
 .../r/nodes/builtin/fastr/FastRInterop.java   |  20 +-
 .../r/nodes/builtin/fastr/FastRPkgSource.java |   2 +-
 .../builtin/fastr/FastRRefCountInfo.java      |   2 +-
 .../nodes/builtin/fastr/FastRSlotAssign.java  |   2 +-
 .../nodes/builtin/fastr/FastRStackTrace.java  |   2 +-
 .../r/nodes/builtin/fastr/FastRStats.java     |   6 +-
 .../nodes/builtin/fastr/FastRSyntaxTree.java  |   2 +-
 .../r/nodes/builtin/fastr/FastRThrowIt.java   |   2 +-
 .../r/nodes/builtin/fastr/FastRTrace.java     |  25 +-
 .../r/nodes/builtin/fastr/FastRTree.java      |   2 +-
 .../r/nodes/builtin/fastr/FastRTreeStats.java |   2 +-
 .../r/nodes/builtin/fastr/FastRTry.java       |   2 +-
 .../r/nodes/builtin/fastr/FastrDqrls.java     |   2 +-
 .../com/oracle/truffle/r/nodes/RRootNode.java |  30 +--
 .../r/nodes/binary/BinaryArithmeticNode.java  |   2 +-
 .../r/nodes/binary/BinaryBooleanNode.java     |   3 +-
 .../nodes/binary/BinaryBooleanScalarNode.java |   2 +-
 .../truffle/r/nodes/binary/BinaryNode.java    |  36 ---
 .../truffle/r/nodes/binary/CastTypeNode.java  |   8 +-
 .../truffle/r/nodes/builtin/InternalNode.java |  26 +--
 .../nodes/builtin/NodeWithArgumentCasts.java  |   2 +-
 .../truffle/r/nodes/builtin/RBuiltinNode.java | 213 ++++++++++++++++-
 .../r/nodes/builtin/RBuiltinRootNode.java     |  53 +++--
 .../nodes/builtin/RInvisibleBuiltinNode.java  |  27 ---
 .../nodes/builtin/RPrecedenceBuiltinNode.java |   2 +-
 .../r/nodes/function/CallMatcherNode.java     |  17 +-
 .../function/FunctionDefinitionNode.java      |  18 +-
 .../truffle/r/nodes/function/RCallNode.java   |  18 +-
 .../truffle/r/nodes/unary/TypeofNode.java     |   4 +
 .../unary/UnaryArithmeticBuiltinNode.java     |   2 +-
 .../truffle/r/nodes/unary/UnaryNotNode.java   |   2 +-
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |   1 -
 .../test/tools/RFFIUpCallMethodGenerate.java  |   1 -
 291 files changed, 1352 insertions(+), 1252 deletions(-)
 delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
 delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
index 39eeb2a3ea..8a69a8d47b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 /**
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
index 0ec6f4d2ef..2621894a90 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 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.java.JavaInterop;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
index 60ce02957f..a254e1c670 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
  * of the grid code in R.
  */
 @RBuiltin(name = ".fastr.grid.doSetViewPort", parameterNames = {"vp", "hasParent", "pushing"}, kind = RBuiltinKind.INTERNAL, behavior = RBehavior.COMPLEX)
-public abstract class DoSetViewPortBuiltin extends RBuiltinNode {
+public abstract class DoSetViewPortBuiltin extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(DoSetViewPortBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
index 13a04235fc..68b4977bee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
@@ -37,7 +37,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
 import com.oracle.truffle.r.nodes.builtin.base.BaseVariables;
-import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -159,15 +158,8 @@ public final class RBuiltinPackages implements RBuiltinLookup {
     private static RootCallTarget createArgumentsCallTarget(RBuiltinFactory builtin) {
         CompilerAsserts.neverPartOfCompilation();
 
-        RBuiltinNode node = builtin.getConstructor().get();
-        FormalArguments formals = FormalArguments.createForBuiltin(node.getDefaultParameterValues(), builtin.getSignature());
-        if (builtin.getKind() == RBuiltinKind.INTERNAL) {
-            assert node.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values";
-            assert builtin.getSignature().getVarArgCount() == 0 || builtin.getSignature().getVarArgIndex() == builtin.getSignature().getLength() - 1 : "only last argument can be vararg";
-        }
-
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        RBuiltinRootNode root = new RBuiltinRootNode(builtin, node, formals, frameDescriptor, null);
+        RBuiltinRootNode root = new RBuiltinRootNode(builtin, frameDescriptor, null);
         FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor);
         return Truffle.getRuntime().createCallTarget(root);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
index 4a4a475317..5930d40906 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 // TODO: add (permuted) dimnames to the result
 @RBuiltin(name = "aperm", kind = INTERNAL, parameterNames = {"a", "perm", "resize"}, behavior = PURE)
-public abstract class APerm extends RBuiltinNode {
+public abstract class APerm extends RBuiltinNode.Arg3 {
 
     private final BranchProfile emptyPermVector = BranchProfile.create();
     private final ConditionProfile mustResize = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
index a1c904169a..d12d0d3961 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "abbreviate", kind = INTERNAL, parameterNames = {"x", "minlength", "use.classes"}, behavior = PURE)
-public abstract class Abbrev extends RBuiltinNode {
+public abstract class Abbrev extends RBuiltinNode.Arg3 {
     private final NACheck naCheck = NACheck.create();
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
index 0feeb054e6..7a73125009 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AllNames.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
 
 @RBuiltin(name = "all.names", kind = INTERNAL, parameterNames = {"expr", "functions", "max.names", "unique"}, behavior = PURE)
-public abstract class AllNames extends RBuiltinNode {
+public abstract class AllNames extends RBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(AllNames.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
index 99ae59e013..217ee20c8e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "anyNA", kind = PRIMITIVE, parameterNames = {"x", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class AnyNA extends RBuiltinNode {
+public abstract class AnyNA extends RBuiltinNode.Arg2 {
 
     private final NACheck naCheck = NACheck.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
index 3ea1d01a8f..299462dbf2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
@@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  *
  */
 @RBuiltin(name = "args", kind = INTERNAL, parameterNames = {"name"}, behavior = COMPLEX)
-public abstract class Args extends RBuiltinNode {
+public abstract class Args extends RBuiltinNode.Arg1 {
 
     @Child private GetFunctions.Get getNode;
     @Child private FrameFunctions.ParentFrame parentFrameNode;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
index 9778fe9c13..9c16badfdc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
@@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  * TODO complete. This is sufficient for the b25 benchmark use.
  */
 @RBuiltin(name = "array", kind = INTERNAL, parameterNames = {"data", "dim", "dimnames"}, behavior = PURE)
-public abstract class Array extends RBuiltinNode {
+public abstract class Array extends RBuiltinNode.Arg3 {
 
     @Child private UpdateDimNames updateDimNames;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index c374db6cb7..436d647e5b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "as.call", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class AsCall extends RBuiltinNode {
+public abstract class AsCall extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile nullNamesProfile = ConditionProfile.createBinaryProfile();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index 9059814482..f76be77734 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "as.character", kind = PRIMITIVE, parameterNames = {"x", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class AsCharacter extends RBuiltinNode {
+public abstract class AsCharacter extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
index cb0d77ec54..d68ee44432 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "asCharacterFactor", kind = INTERNAL, parameterNames = "x", behavior = PURE)
-public abstract class AsCharacterFactor extends RBuiltinNode {
+public abstract class AsCharacterFactor extends RBuiltinNode.Arg1 {
     private static final RStringVector CLASS_FACTOR_VEC = RDataFactory.createStringVectorFromScalar(RRuntime.CLASS_FACTOR);
 
     @Child private InheritsNode inheritsNode = InheritsNodeGen.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
index 1ac005ce1b..6ca5279ac6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsComplex.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 
 @RBuiltin(name = "as.complex", kind = PRIMITIVE, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "..."}, behavior = PURE)
-public abstract class AsComplex extends RBuiltinNode {
+public abstract class AsComplex extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
index a8e7d27ae6..fc78a33800 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 @RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
-public abstract class AsDouble extends RBuiltinNode {
+public abstract class AsDouble extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
index d3f2d8b12a..d465f8dea5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
@@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "as.function.default", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE)
-public abstract class AsFunction extends RBuiltinNode {
+public abstract class AsFunction extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(AsFunction.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
index 79e6144769..35f09fb010 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "as.integer", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
-public abstract class AsInteger extends RBuiltinNode {
+public abstract class AsInteger extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
index e9eb0ca41e..3bdca002de 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
 @RBuiltin(name = "as.logical", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
-public abstract class AsLogical extends RBuiltinNode {
+public abstract class AsLogical extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
index ef2911acc2..de58fbb3b7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 
 @RBuiltin(name = "as.raw", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class AsRaw extends RBuiltinNode {
+public abstract class AsRaw extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index 7a32d4cc10..b54c737925 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -73,7 +73,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
-public abstract class AsVector extends RBuiltinNode {
+public abstract class AsVector extends RBuiltinNode.Arg2 {
 
     @Child private AsVectorInternal internal = AsVectorInternalNodeGen.create();
     @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
index fd5c01570f..316c04031c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Assign.java
@@ -54,7 +54,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  *
  */
 @RBuiltin(name = "assign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "envir", "inherits"}, behavior = COMPLEX)
-public abstract class Assign extends RBuiltinNode {
+public abstract class Assign extends RBuiltinNode.Arg4 {
 
     private final boolean direct;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
index b490525f18..82defa7b42 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AttachFunctions.java
@@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.DetachException;
 
 public class AttachFunctions {
     @RBuiltin(name = "attach", visibility = OFF, kind = INTERNAL, parameterNames = {"what", "pos", "name"}, behavior = COMPLEX)
-    public abstract static class Attach extends RBuiltinNode {
+    public abstract static class Attach extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(Attach.class);
@@ -103,7 +103,7 @@ public class AttachFunctions {
     }
 
     @RBuiltin(name = "detach", visibility = OFF, kind = INTERNAL, parameterNames = {"pos"}, behavior = COMPLEX)
-    public abstract static class Detach extends RBuiltinNode {
+    public abstract static class Detach extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Detach.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
index 4583b8b627..e746de2a76 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
@@ -54,7 +54,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "attr", kind = PRIMITIVE, parameterNames = {"x", "which", "exact"}, behavior = PURE)
-public abstract class Attr extends RBuiltinNode {
+public abstract class Attr extends RBuiltinNode.Arg3 {
 
     private final ConditionProfile searchPartialProfile = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
index 3c751dc990..c2e894809c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "attributes", kind = PRIMITIVE, parameterNames = {"obj"}, behavior = PURE)
-public abstract class Attributes extends RBuiltinNode {
+public abstract class Attributes extends RBuiltinNode.Arg1 {
 
     private final BranchProfile rownamesBranch = BranchProfile.create();
     @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index ff6d99d9c5..4ee6d5194c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class BaseGammaFunctions {
 
-    public abstract static class GammaBase extends RBuiltinNode {
+    public abstract static class GammaBase extends RBuiltinNode.Arg1 {
 
         private final NACheck naValCheck = NACheck.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
index 32498303a1..332f4021fd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bincode.java
@@ -27,7 +27,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "bincode", kind = INTERNAL, parameterNames = {"x", "breaks", "right", "include.lowest"}, behavior = PURE)
-public abstract class Bincode extends RBuiltinNode {
+public abstract class Bincode extends RBuiltinNode.Arg4 {
 
     private final NACheck naCheck = NACheck.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index acc4e16ed1..5a783d9fc9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -547,7 +547,7 @@ public abstract class Bind extends RBaseNode {
         }
     }
 
-    protected abstract static class AbstractBind extends RBuiltinNode {
+    protected abstract static class AbstractBind extends RBuiltinNode.Arg2 {
         @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
         private final ConditionProfile hasClassProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile hasDispatchFunction = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
index f90deab4bf..5d5314d20b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
@@ -43,7 +43,22 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class BitwiseFunctions {
 
-    public abstract static class BasicBitwise extends RBuiltinNode {
+    protected enum Operation {
+        AND("bitwAnd"),
+        OR("bitwOr"),
+        XOR("bitwXor"),
+        NOT("bitNot"),
+        SHIFTR("bitShiftR"),
+        SHIFTL("bitShiftL");
+
+        private final String name;
+
+        Operation(String name) {
+            this.name = name;
+        }
+    }
+
+    public abstract static class BasicBitwise extends RBuiltinNode.Arg2 {
 
         private final NACheck naCheckA = NACheck.create();
         private final NACheck naCheckB = NACheck.create();
@@ -52,21 +67,6 @@ public class BitwiseFunctions {
         @Child private TypeofNode typeofA = TypeofNodeGen.create();
         @Child private TypeofNode typeofB = TypeofNodeGen.create();
 
-        protected enum Operation {
-            AND("bitwAnd"),
-            OR("bitwOr"),
-            XOR("bitwXor"),
-            NOT("bitNot"),
-            SHIFTR("bitShiftR"),
-            SHIFTL("bitShiftL");
-
-            private final String name;
-
-            Operation(String name) {
-                this.name = name;
-            }
-        }
-
         protected Object basicBit(RAbstractIntVector aVec, RAbstractIntVector bVec, Operation op) {
             naCheckA.enable(aVec);
             naCheckB.enable(bVec);
@@ -121,14 +121,6 @@ public class BitwiseFunctions {
             return RDataFactory.createIntVector(ans, completeVector);
         }
 
-        protected Object bitNot(RAbstractIntVector aVec) {
-            int[] ans = new int[aVec.getLength()];
-            for (int i = 0; i < aVec.getLength(); i++) {
-                ans[i] = ~aVec.getDataAt(i);
-            }
-            return RDataFactory.createIntVector(ans, RDataFactory.COMPLETE_VECTOR);
-        }
-
         protected Object makeNA(int length) {
             int[] na = new int[length];
             for (int i = 0; i < length; i++) {
@@ -259,18 +251,20 @@ public class BitwiseFunctions {
     }
 
     @RBuiltin(name = "bitwiseNot", kind = INTERNAL, parameterNames = {"a"}, behavior = PURE)
-    public abstract static class BitwiseNot extends BasicBitwise {
+    public abstract static class BitwiseNot extends RBuiltinNode.Arg1 {
 
-        // @formatter:off
-    static {
-        Casts casts = new Casts(BitwiseNot.class);
+        static {
+            Casts casts = new Casts(BitwiseNot.class);
             casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.NOT.name).mustBe(doubleValue().or(integerValue())).asIntegerVector();
-    }
-        //@formatter:on
+        }
 
         @Specialization
         protected Object bitwNot(RAbstractIntVector a) {
-            return bitNot(a);
+            int[] ans = new int[a.getLength()];
+            for (int i = 0; i < a.getLength(); i++) {
+                ans[i] = ~a.getDataAt(i);
+            }
+            return RDataFactory.createIntVector(ans, RDataFactory.COMPLETE_VECTOR);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
index 47bfc87caf..f481242580 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Body.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "body", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
-public abstract class Body extends RBuiltinNode {
+public abstract class Body extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(Body.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
index 063f35a81e..8f0f513b5c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
@@ -22,8 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNodeGen;
@@ -51,7 +52,7 @@ import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState
 public class BrowserFunctions {
 
     @RBuiltin(name = "browser", visibility = OFF, kind = PRIMITIVE, parameterNames = {"text", "condition", "expr", "skipCalls"}, behavior = COMPLEX)
-    public abstract static class BrowserNode extends RBuiltinNode {
+    public abstract static class BrowserNode extends RBuiltinNode.Arg4 {
 
         @Child private BrowserInteractNode browserInteractNode = BrowserInteractNodeGen.create();
 
@@ -99,24 +100,21 @@ public class BrowserFunctions {
         }
     }
 
-    private abstract static class RetrieveAdapter extends RBuiltinNode {
-
-        protected static void casts(Class<? extends RetrieveAdapter> builtinClass) {
-            Casts casts = new Casts(builtinClass);
-            casts.arg("n").asIntegerVector().findFirst(0).mustBe(gt(0), Message.POSITIVE_CONTEXTS);
-        }
+    protected static void casts(Class<? extends RBuiltinNode> builtinClass) {
+        Casts casts = new Casts(builtinClass);
+        casts.arg("n").asIntegerVector().findFirst(0).mustBe(gt(0), Message.POSITIVE_CONTEXTS);
+    }
 
-        /**
-         * GnuR objects to indices <= 0 but allows positive indices that are out of range.
-         */
-        protected HelperState getHelperState(int n) {
-            BrowserState helperState = RContext.getInstance().stateInstrumentation.getBrowserState();
-            return helperState.get(n);
-        }
+    /**
+     * GnuR objects to indices <= 0 but allows positive indices that are out of range.
+     */
+    protected static HelperState getHelperState(int n) {
+        BrowserState helperState = RContext.getInstance().stateInstrumentation.getBrowserState();
+        return helperState.get(n);
     }
 
     @RBuiltin(name = "browserText", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
-    public abstract static class BrowserText extends RetrieveAdapter {
+    public abstract static class BrowserText extends RBuiltinNode.Arg1 {
 
         static {
             casts(BrowserText.class);
@@ -130,7 +128,7 @@ public class BrowserFunctions {
     }
 
     @RBuiltin(name = "browserCondition", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
-    public abstract static class BrowserCondition extends RetrieveAdapter {
+    public abstract static class BrowserCondition extends RBuiltinNode.Arg1 {
 
         static {
             casts(BrowserCondition.class);
@@ -144,7 +142,7 @@ public class BrowserFunctions {
     }
 
     @RBuiltin(name = "browserSetDebug", visibility = OFF, kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
-    public abstract static class BrowserSetDebug extends RetrieveAdapter {
+    public abstract static class BrowserSetDebug extends RBuiltinNode.Arg1 {
 
         static {
             casts(BrowserSetDebug.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
index 1cb9a96123..a8223eb1e1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CRC64.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "crc64", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class CRC64 extends RBuiltinNode {
+public abstract class CRC64 extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(CRC64.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java
index d95ff7128f..53ac34d5a9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CacheClass.java
@@ -25,7 +25,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = ".cache_class", kind = PRIMITIVE, parameterNames = {"class", "extends"}, behavior = COMPLEX)
-public abstract class CacheClass extends RBuiltinNode {
+public abstract class CacheClass extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(CacheClass.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index 5f04839d3b..20b0d7b466 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
@@ -57,7 +57,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * Does not perform argument matching for first parameter "name".
  */
 @RBuiltin(name = "call", kind = PRIMITIVE, parameterNames = {"", "..."}, behavior = PURE)
-public abstract class Call extends RBuiltinNode {
+public abstract class Call extends RBuiltinNode.Arg2 {
 
     @Override
     public Object[] getDefaultParameterValues() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
index b63bb9fb4e..8a80bf7e43 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 
 @RBuiltin(name = "capabilities", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-public abstract class Capabilities extends RBuiltinNode {
+public abstract class Capabilities extends RBuiltinNode.Arg0 {
     private enum Capability {
         jpeg(false, null),
         png(false, null),
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
index 4abee5300e..a4b42e74a1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Cat.java
@@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  * The {@code cat .Internal}.
  */
 @RBuiltin(name = "cat", visibility = OFF, kind = INTERNAL, parameterNames = {"arglist", "file", "sep", "fill", "labels", "append"}, behavior = IO)
-public abstract class Cat extends RBuiltinNode {
+public abstract class Cat extends RBuiltinNode.Arg6 {
 
     @Child private ToStringNode toString;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
index c371f39b79..166b7545ea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
@@ -24,7 +24,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "charmatch", kind = INTERNAL, parameterNames = {"x", "table", "noMatch"}, behavior = PURE)
-public abstract class CharMatch extends RBuiltinNode {
+public abstract class CharMatch extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(CharMatch.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
index d74f7d1718..ce33027399 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ChooseBuiltin.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * Binomial coefficients (n, k) for real n and integral k (rounded with warning).
  */
 @RBuiltin(name = "choose", kind = INTERNAL, parameterNames = {"n", "k"}, behavior = PURE)
-public abstract class ChooseBuiltin extends RBuiltinNode {
+public abstract class ChooseBuiltin extends RBuiltinNode.Arg2 {
 
     private final NACheck na = NACheck.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
index 6ceabd9a8f..c331492d3e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Col.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "col", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE)
-public abstract class Col extends RBuiltinNode {
+public abstract class Col extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Col.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
index 7b3b0aa1ac..b97bdbc8ff 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSumsBase.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * specializations shared between {@link RowSums}, {@link RowMeans}, {@link ColMeans},
  * {@link RowSums}.
  */
-public abstract class ColSumsBase extends RBuiltinNode {
+public abstract class ColSumsBase extends RBuiltinNode.Arg4 {
 
     protected final NACheck na = NACheck.create();
     private final ConditionProfile vectorLengthProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index c6eedfe836..4d4a9b0993 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -70,7 +70,7 @@ abstract class ColonSpecial extends RNode {
 
 // javac fails without fully qualified name
 @com.oracle.truffle.r.runtime.builtins.RBuiltin(name = ":", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE)
-public abstract class Colon extends RBuiltinNode {
+public abstract class Colon extends RBuiltinNode.Arg2 {
 
     public static RNode special(ArgumentsSignature signature, RNode[] arguments, boolean inReplacement) {
         if (signature.getNonNullCount() == 0 && arguments.length == 2 && !inReplacement) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 54e0f519e7..8e38c82231 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -79,7 +79,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "c", kind = PRIMITIVE, parameterNames = {"...", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class Combine extends RBuiltinNode {
+public abstract class Combine extends RBuiltinNode.Arg2 {
 
     public static Combine create() {
         return CombineNodeGen.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
index f2ad7c85cf..5ff3ba65a5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 
 @RBuiltin(name = "commandArgs", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-public abstract class CommandArgs extends RBuiltinNode {
+public abstract class CommandArgs extends RBuiltinNode.Arg0 {
 
     @Specialization
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java
index 7fb2b3ce4d..515a446f10 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CompileFunctions.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 public class CompileFunctions {
     @RBuiltin(name = "compilePKGS", kind = INTERNAL, parameterNames = "enable", behavior = PURE)
-    public abstract static class CompilePKGS extends RBuiltinNode {
+    public abstract static class CompilePKGS extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(CompilePKGS.class);
@@ -49,7 +49,7 @@ public class CompileFunctions {
     }
 
     @RBuiltin(name = "enableJIT", kind = INTERNAL, parameterNames = "level", behavior = PURE)
-    public abstract static class EnableJIT extends RBuiltinNode {
+    public abstract static class EnableJIT extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(EnableJIT.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
index d79675c636..2034744f3a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Complex.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "complex", kind = INTERNAL, parameterNames = {"length.out", "real", "imaginary"}, behavior = PURE)
-public abstract class Complex extends RBuiltinNode {
+public abstract class Complex extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(Complex.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
index 1c65b8139a..12fffb616a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
-import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -43,20 +42,8 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  */
 public class ConditionFunctions {
 
-    public abstract static class EvalAdapter extends RBuiltinNode {
-        @Child private PromiseHelperNode promiseHelper;
-
-        protected PromiseHelperNode initPromiseHelper() {
-            if (promiseHelper == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                promiseHelper = insert(new PromiseHelperNode());
-            }
-            return promiseHelper;
-        }
-    }
-
     @RBuiltin(name = ".addCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"classes", "handlers", "parentenv", "target", "calling"}, behavior = COMPLEX)
-    public abstract static class AddCondHands extends RBuiltinNode {
+    public abstract static class AddCondHands extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(AddCondHands.class);
@@ -100,7 +87,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = ".resetCondHands", visibility = OFF, kind = INTERNAL, parameterNames = {"stack"}, behavior = COMPLEX)
-    public abstract static class ResetCondHands extends RBuiltinNode {
+    public abstract static class ResetCondHands extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(ResetCondHands.class);
@@ -114,24 +101,12 @@ public class ConditionFunctions {
         }
     }
 
-    public abstract static class RestartAdapter extends RBuiltinNode {
-        protected void checkLength(RList restart) {
-            if (restart.getLength() < 2) {
-                throw error(RError.Message.BAD_RESTART);
-            }
-        }
-
-        protected static void restart(Casts casts) {
-            casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART);
-        }
-    }
-
     @RBuiltin(name = ".addRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX)
-    public abstract static class AddRestart extends RestartAdapter {
+    public abstract static class AddRestart extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(AddRestart.class);
-            restart(casts);
+            casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART);
         }
 
         protected FrameSlot createRestartFrameSlot(VirtualFrame frame) {
@@ -141,7 +116,9 @@ public class ConditionFunctions {
         @Specialization
         protected Object addRestart(VirtualFrame frame, RList restart,
                         @Cached("createRestartFrameSlot(frame)") FrameSlot restartFrameSlot) {
-            checkLength(restart);
+            if (restart.getLength() < 2) {
+                throw error(RError.Message.BAD_RESTART);
+            }
             try {
                 if (!frame.isObject(restartFrameSlot) || frame.getObject(restartFrameSlot) == null) {
                     frame.setObject(restartFrameSlot, RErrorHandling.getRestartStack());
@@ -155,7 +132,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = ".getRestart", kind = INTERNAL, parameterNames = "restart", behavior = COMPLEX)
-    public abstract static class GetRestart extends RBuiltinNode {
+    public abstract static class GetRestart extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(GetRestart.class);
@@ -170,17 +147,19 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = ".invokeRestart", kind = INTERNAL, parameterNames = {"restart", "args"}, behavior = COMPLEX)
-    public abstract static class InvokeRestart extends RestartAdapter {
+    public abstract static class InvokeRestart extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(InvokeRestart.class);
-            restart(casts);
+            casts.arg("restart").mustBe(instanceOf(RList.class), RError.Message.BAD_RESTART);
         }
 
         @Specialization
         @TruffleBoundary
         protected RNull invokeRestart(RList restart, Object args) {
-            checkLength(restart);
+            if (restart.getLength() < 2) {
+                throw error(RError.Message.BAD_RESTART);
+            }
             RErrorHandling.invokeRestart(restart, args);
             // invokeRestart is expected to always return via a ReturnException
             throw error(RError.Message.RESTART_NOT_ON_STACK);
@@ -188,7 +167,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = ".signalCondition", kind = INTERNAL, parameterNames = {"condition", "msg", "call"}, behavior = COMPLEX)
-    public abstract static class SignalCondition extends RBuiltinNode {
+    public abstract static class SignalCondition extends RBuiltinNode.Arg3 {
 
         static {
             Casts.noCasts(SignalCondition.class);
@@ -202,7 +181,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = "geterrmessage", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class Geterrmessage extends RBuiltinNode {
+    public abstract static class Geterrmessage extends RBuiltinNode.Arg0 {
         @Specialization
         protected String geterrmessage() {
             return RErrorHandling.geterrmessage();
@@ -210,7 +189,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = "seterrmessage", visibility = OFF, kind = INTERNAL, parameterNames = "msg", behavior = COMPLEX)
-    public abstract static class Seterrmessage extends RBuiltinNode {
+    public abstract static class Seterrmessage extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Seterrmessage.class);
@@ -225,7 +204,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = ".dfltWarn", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX)
-    public abstract static class DfltWarn extends RBuiltinNode {
+    public abstract static class DfltWarn extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(DfltWarn.class);
@@ -240,7 +219,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = ".dfltStop", kind = INTERNAL, parameterNames = {"message", "call"}, behavior = COMPLEX)
-    public abstract static class DfltStop extends RBuiltinNode {
+    public abstract static class DfltStop extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(DfltStop.class);
@@ -255,7 +234,7 @@ public class ConditionFunctions {
     }
 
     @RBuiltin(name = "printDeferredWarnings", visibility = OFF, kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class PrintDeferredWarnings extends RBuiltinNode {
+    public abstract static class PrintDeferredWarnings extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected RNull printDeferredWarnings() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index efa1508a88..976df1b8bd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -125,7 +125,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  */
 public abstract class ConnectionFunctions {
     @RBuiltin(name = "stdin", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class Stdin extends RBuiltinNode {
+    public abstract static class Stdin extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector stdin() {
@@ -134,7 +134,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "stdout", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class Stdout extends RBuiltinNode {
+    public abstract static class Stdout extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector stdout() {
@@ -143,7 +143,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "stderr", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class Stderr extends RBuiltinNode {
+    public abstract static class Stderr extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector stderr() {
@@ -219,7 +219,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "file", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method", "raw"}, behavior = IO)
-    public abstract static class File extends RBuiltinNode {
+    public abstract static class File extends RBuiltinNode.Arg6 {
 
         static {
             Casts casts = new Casts(File.class);
@@ -279,7 +279,7 @@ public abstract class ConnectionFunctions {
      * uncompressed files, and files compressed by {@code bzip2, xz, lzma}.
      */
 
-    public abstract static class ZZFileAdapter extends RBuiltinNode {
+    public abstract static class ZZFileAdapter extends RBuiltinNode.Arg4 {
         private final RCompression.Type cType;
 
         protected ZZFileAdapter(RCompression.Type cType) {
@@ -347,7 +347,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "textConnection", kind = INTERNAL, parameterNames = {"description", "text", "open", "env", "encoding"}, behavior = IO)
-    public abstract static class TextConnection extends RBuiltinNode {
+    public abstract static class TextConnection extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(TextConnection.class);
@@ -375,7 +375,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "textConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class TextConnectionValue extends RBuiltinNode {
+    public abstract static class TextConnectionValue extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(TextConnectionValue.class);
@@ -395,7 +395,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "socketConnection", kind = INTERNAL, parameterNames = {"host", "port", "server", "blocking", "open", "encoding", "timeout"}, behavior = IO)
-    public abstract static class SocketConnection extends RBuiltinNode {
+    public abstract static class SocketConnection extends RBuiltinNode.Arg7 {
 
         static {
             Casts casts = new Casts(SocketConnection.class);
@@ -422,7 +422,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "url", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding", "method"}, behavior = IO)
-    public abstract static class URLConnection extends RBuiltinNode {
+    public abstract static class URLConnection extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(URLConnection.class);
@@ -450,7 +450,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "rawConnection", kind = INTERNAL, parameterNames = {"description", "object", "open"}, behavior = IO)
-    public abstract static class RawConnection extends RBuiltinNode {
+    public abstract static class RawConnection extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(RawConnection.class);
@@ -481,7 +481,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "rawConnectionValue", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class RawConnectionValue extends RBuiltinNode {
+    public abstract static class RawConnectionValue extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(RawConnectionValue.class);
@@ -501,7 +501,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "summary.connection", kind = INTERNAL, parameterNames = {"object"}, behavior = IO)
-    public abstract static class Summary extends RBuiltinNode {
+    public abstract static class Summary extends RBuiltinNode.Arg1 {
         private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"description", "class", "mode", "text", "opened", "can read", "can write"},
                         RDataFactory.COMPLETE_VECTOR);
 
@@ -527,7 +527,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "open", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "open", "blocking"}, behavior = IO)
-    public abstract static class Open extends RBuiltinNode {
+    public abstract static class Open extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(Open.class);
@@ -556,7 +556,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "isOpen", kind = INTERNAL, parameterNames = {"con", "rw"}, behavior = IO)
-    public abstract static class IsOpen extends RBuiltinNode {
+    public abstract static class IsOpen extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(IsOpen.class);
@@ -586,7 +586,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "close", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "type"}, behavior = IO)
-    public abstract static class Close extends RBuiltinNode {
+    public abstract static class Close extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(Close.class);
@@ -608,7 +608,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "readLines", kind = INTERNAL, parameterNames = {"con", "n", "ok", "warn", "encoding", "skipNul"}, behavior = IO)
-    public abstract static class ReadLines extends RBuiltinNode {
+    public abstract static class ReadLines extends RBuiltinNode.Arg6 {
 
         static {
             Casts casts = new Casts(ReadLines.class);
@@ -637,7 +637,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "writeLines", visibility = OFF, kind = INTERNAL, parameterNames = {"text", "con", "sep", "useBytes"}, behavior = IO)
-    public abstract static class WriteLines extends RBuiltinNode {
+    public abstract static class WriteLines extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(WriteLines.class);
@@ -660,7 +660,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "flush", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class Flush extends RBuiltinNode {
+    public abstract static class Flush extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Flush.class);
@@ -680,7 +680,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "pushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"data", "con", "newLine", "type"}, behavior = IO)
-    public abstract static class PushBack extends RBuiltinNode {
+    public abstract static class PushBack extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(PushBack.class);
@@ -699,7 +699,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "pushBackLength", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class PushBackLength extends RBuiltinNode {
+    public abstract static class PushBackLength extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(PushBackLength.class);
@@ -713,7 +713,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "clearPushBack", visibility = OFF, kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class PushBackClear extends RBuiltinNode {
+    public abstract static class PushBackClear extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(PushBackClear.class);
@@ -728,7 +728,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "readChar", kind = INTERNAL, parameterNames = {"con", "nchars", "useBytes"}, behavior = IO)
-    public abstract static class ReadChar extends RBuiltinNode {
+    public abstract static class ReadChar extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(ReadChar.class);
@@ -763,7 +763,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "writeChar", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "nchars", "sep", "useBytes"}, behavior = IO)
-    public abstract static class WriteChar extends RBuiltinNode {
+    public abstract static class WriteChar extends RBuiltinNode.Arg5 {
 
         static {
             // @formatter:off
@@ -832,7 +832,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "readBin", kind = INTERNAL, parameterNames = {"con", "what", "n", "size", "signed", "swap"}, behavior = IO)
-    public abstract static class ReadBin extends RBuiltinNode {
+    public abstract static class ReadBin extends RBuiltinNode.Arg6 {
 
         static {
             Casts casts = new Casts(ReadBin.class);
@@ -1124,7 +1124,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "writeBin", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "size", "swap", "useBytes"}, behavior = IO)
-    public abstract static class WriteBin extends RBuiltinNode {
+    public abstract static class WriteBin extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(WriteBin.class);
@@ -1168,7 +1168,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "getConnection", kind = INTERNAL, parameterNames = {"what"}, behavior = IO)
-    public abstract static class GetConnection extends RBuiltinNode {
+    public abstract static class GetConnection extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(GetConnection.class);
@@ -1188,7 +1188,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "getAllConnections", kind = INTERNAL, parameterNames = {}, behavior = IO)
-    public abstract static class GetAllConnections extends RBuiltinNode {
+    public abstract static class GetAllConnections extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected RAbstractIntVector getAllConnections() {
@@ -1197,7 +1197,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "isSeekable", kind = INTERNAL, parameterNames = "con", behavior = IO)
-    public abstract static class IsSeekable extends RBuiltinNode {
+    public abstract static class IsSeekable extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(IsSeekable.class);
@@ -1212,7 +1212,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "seek", kind = INTERNAL, parameterNames = {"con", "where", "origin", "rw"}, behavior = IO)
-    public abstract static class Seek extends RBuiltinNode {
+    public abstract static class Seek extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(Seek.class);
@@ -1250,7 +1250,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "fifo", kind = INTERNAL, parameterNames = {"description", "open", "blocking", "encoding"}, behavior = IO)
-    public abstract static class Fifo extends RBuiltinNode {
+    public abstract static class Fifo extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(Fifo.class);
@@ -1279,7 +1279,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "pipe", kind = INTERNAL, parameterNames = {"description", "open", "encoding"}, behavior = IO)
-    public abstract static class Pipe extends RBuiltinNode {
+    public abstract static class Pipe extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(Pipe.class);
@@ -1305,7 +1305,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "isIncomplete", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class IsIncomplete extends RBuiltinNode {
+    public abstract static class IsIncomplete extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(IsIncomplete.class);
@@ -1322,7 +1322,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = "truncate", kind = INTERNAL, parameterNames = {"con"}, behavior = IO)
-    public abstract static class Truncate extends RBuiltinNode {
+    public abstract static class Truncate extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Truncate.class);
@@ -1343,7 +1343,7 @@ public abstract class ConnectionFunctions {
     }
 
     @RBuiltin(name = ".fastr.channelConnection", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"channel", "open", "encoding"}, behavior = IO)
-    public abstract static class ChannelConnection extends RBuiltinNode {
+    public abstract static class ChannelConnection extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(ChannelConnection.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
index 2a64ec2f8e..bb5c8b3413 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Contributors.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.conn.StdConnections;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "contributors", visibility = OFF, kind = SUBSTITUTE, parameterNames = {}, behavior = IO)
-public abstract class Contributors extends RBuiltinNode {
+public abstract class Contributors extends RBuiltinNode.Arg0 {
 
     private static final String CONTRIBUTORS = Utils.getResourceAsString(Contributors.class, "CONTRIBUTORS", true);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java
index d9f2875e1c..e3080d28c8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "copyDFattr", kind = INTERNAL, parameterNames = {"", ""}, behavior = COMPLEX)
-public abstract class CopyDFAttr extends RBuiltinNode {
+public abstract class CopyDFAttr extends RBuiltinNode.Arg2 {
 
     static {
         Casts.noCasts(CopyDFAttr.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
index 4928c3ee38..56ddfda615 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "crossprod", kind = INTERNAL, parameterNames = {"x", "y"}, behavior = PURE)
-public abstract class Crossprod extends RBuiltinNode {
+public abstract class Crossprod extends RBuiltinNode.Arg2 {
 
     @Child private MatMult matMult = MatMultNodeGen.create(/* promoteDimNames: */ false);
     @Child private Transpose transpose;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
index b108f85ee4..b21e15c0bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMax.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "cummax", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class CumMax extends RBuiltinNode {
+public abstract class CumMax extends RBuiltinNode.Arg1 {
 
     private final NACheck na = NACheck.create();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
index fe04402556..c558b2df55 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumMin.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "cummin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class CumMin extends RBuiltinNode {
+public abstract class CumMin extends RBuiltinNode.Arg1 {
 
     private final NACheck na = NACheck.create();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
index 50a2f53a3b..69767d4e3d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumProd.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "cumprod", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class CumProd extends RBuiltinNode {
+public abstract class CumProd extends RBuiltinNode.Arg1 {
 
     private final NACheck na = NACheck.create();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
index d0aa710798..683d2b46ad 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CumSum.java
@@ -57,7 +57,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "cumsum", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class CumSum extends RBuiltinNode {
+public abstract class CumSum extends RBuiltinNode.Arg1 {
 
     private final NACheck na = NACheck.create();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
index 1a1f358599..d0361a493f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.conn.RConnection;
  * The {@code dput .Internal}.
  */
 @RBuiltin(name = "dput", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "file", "opts"}, behavior = IO)
-public abstract class DPut extends RBuiltinNode {
+public abstract class DPut extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(DPut.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java
index 2fc9b6f40b..963c5131f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java
@@ -23,7 +23,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "date", kind = INTERNAL, parameterNames = {}, behavior = IO)
-public abstract class Date extends RBuiltinNode {
+public abstract class Date extends RBuiltinNode.Arg0 {
 
     @Specialization
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
index f63bcc40cc..963a91850b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
@@ -137,7 +137,7 @@ public class DatePOSIXFunctions {
     }
 
     @RBuiltin(name = "Date2POSIXlt", kind = INTERNAL, parameterNames = "x", behavior = PURE)
-    public abstract static class Date2POSIXlt extends RBuiltinNode {
+    public abstract static class Date2POSIXlt extends RBuiltinNode.Arg1 {
 
         @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
@@ -173,7 +173,7 @@ public class DatePOSIXFunctions {
     }
 
     @RBuiltin(name = "as.POSIXlt", kind = INTERNAL, parameterNames = {"x", "tz"}, behavior = READS_STATE)
-    public abstract static class AsPOSIXlt extends RBuiltinNode {
+    public abstract static class AsPOSIXlt extends RBuiltinNode.Arg2 {
 
         @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
@@ -215,7 +215,7 @@ public class DatePOSIXFunctions {
     }
 
     @RBuiltin(name = "as.POSIXct", kind = INTERNAL, parameterNames = {"x", "tz"}, behavior = READS_STATE)
-    public abstract static class AsPOSIXct extends RBuiltinNode {
+    public abstract static class AsPOSIXct extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(AsPOSIXct.class);
@@ -273,7 +273,7 @@ public class DatePOSIXFunctions {
     }
 
     @RBuiltin(name = "POSIXlt2Date", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class POSIXlt2Date extends RBuiltinNode {
+    public abstract static class POSIXlt2Date extends RBuiltinNode.Arg1 {
         private static final RStringVector CLASS_ATTR = (RStringVector) RDataFactory.createStringVectorFromScalar("Date").makeSharedPermanent();
 
         static {
@@ -324,7 +324,7 @@ public class DatePOSIXFunctions {
     }
 
     @RBuiltin(name = "format.POSIXlt", kind = INTERNAL, parameterNames = {"x", "format", "usetz"}, behavior = READS_STATE)
-    public abstract static class FormatPOSIXlt extends RBuiltinNode {
+    public abstract static class FormatPOSIXlt extends RBuiltinNode.Arg3 {
 
         private static final HashMap<String, String> TIME_ZONE_MAPPING = new HashMap<>();
 
@@ -390,7 +390,7 @@ public class DatePOSIXFunctions {
     }
 
     @RBuiltin(name = "strptime", kind = INTERNAL, parameterNames = {"x", "format", "tz"}, behavior = PURE)
-    public abstract static class StrPTime extends RBuiltinNode {
+    public abstract static class StrPTime extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(StrPTime.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
index 6ed51005c6..e0793ec5a6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
@@ -29,6 +29,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling;
 import com.oracle.truffle.r.runtime.RError;
@@ -37,29 +38,27 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public class DebugFunctions {
 
-    protected abstract static class ErrorAndFunAdapter extends RBuiltinNode {
-
-        protected static Casts createCasts(Class<? extends ErrorAndFunAdapter> extCls) {
-            Casts casts = new Casts(extCls);
-            casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE);
-            return casts;
-        }
+    protected static Casts createCasts(Class<? extends RBuiltinNode> extCls) {
+        Casts casts = new Casts(extCls);
+        casts.arg("fun").mustBe(RFunction.class, Message.ARG_MUST_BE_CLOSURE);
+        return casts;
+    }
 
-        protected void doDebug(RFunction fun, Object text, Object condition, boolean once) throws RError {
-            // GnuR does not generate an error for builtins, but debug (obviously) has no effect
-            if (!fun.isBuiltin()) {
-                if (!DebugHandling.enableDebug(fun, text, condition, once, false)) {
-                    throw error(RError.Message.GENERIC, "failed to attach debug handler (not instrumented?)");
-                }
+    protected static void doDebug(RBaseNode node, RFunction fun, Object text, Object condition, boolean once) throws RError {
+        // GnuR does not generate an error for builtins, but debug (obviously) has no effect
+        if (!fun.isBuiltin()) {
+            if (!DebugHandling.enableDebug(fun, text, condition, once, false)) {
+                throw node.error(RError.Message.GENERIC, "failed to attach debug handler (not instrumented?)");
             }
         }
     }
 
     @RBuiltin(name = "debug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX)
-    public abstract static class Debug extends ErrorAndFunAdapter {
+    public abstract static class Debug extends RBuiltinNode.Arg3 {
 
         static {
             createCasts(Debug.class);
@@ -67,14 +66,14 @@ public class DebugFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RNull doDebug(RFunction fun, Object text, Object condition) {
-            doDebug(fun, text, condition, false);
+        protected RNull debug(RFunction fun, Object text, Object condition) {
+            doDebug(this, fun, text, condition, false);
             return RNull.instance;
         }
     }
 
     @RBuiltin(name = "debugonce", visibility = OFF, kind = INTERNAL, parameterNames = {"fun", "text", "condition"}, behavior = COMPLEX)
-    public abstract static class DebugOnce extends ErrorAndFunAdapter {
+    public abstract static class DebugOnce extends RBuiltinNode.Arg3 {
 
         static {
             createCasts(DebugOnce.class);
@@ -84,13 +83,13 @@ public class DebugFunctions {
         @TruffleBoundary
         protected RNull debugonce(RFunction fun, Object text, Object condition) {
             // TODO implement
-            doDebug(fun, text, condition, true);
+            doDebug(this, fun, text, condition, true);
             return RNull.instance;
         }
     }
 
     @RBuiltin(name = "undebug", visibility = OFF, kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX)
-    public abstract static class UnDebug extends ErrorAndFunAdapter {
+    public abstract static class UnDebug extends RBuiltinNode.Arg1 {
 
         static {
             createCasts(UnDebug.class);
@@ -107,7 +106,7 @@ public class DebugFunctions {
     }
 
     @RBuiltin(name = "isdebugged", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
-    public abstract static class IsDebugged extends ErrorAndFunAdapter {
+    public abstract static class IsDebugged extends RBuiltinNode.Arg1 {
 
         static {
             createCasts(IsDebugged.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
index 41271c43ea..d62180268e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DelayedAssign.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 
 @RBuiltin(name = "delayedAssign", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "value", "eval.env", "assign.env"}, behavior = COMPLEX)
-public abstract class DelayedAssign extends RBuiltinNode {
+public abstract class DelayedAssign extends RBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(DelayedAssign.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
index c00c28bee4..fdd7a26615 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
@@ -28,7 +28,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 // Part of this transcribed from GnuR src/main/deparse.c
 
 @RBuiltin(name = "deparse", kind = INTERNAL, parameterNames = {"expr", "width.cutoff", "backtick", "control", "nlines"}, behavior = PURE)
-public abstract class Deparse extends RBuiltinNode {
+public abstract class Deparse extends RBuiltinNode.Arg5 {
 
     static {
         Casts casts = new Casts(Deparse.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
index c9c2b803af..6d2ba76bcb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Diag.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "diag", kind = INTERNAL, parameterNames = {"x", "nrow", "ncol"}, behavior = PURE)
-public abstract class Diag extends RBuiltinNode {
+public abstract class Diag extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(Diag.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
index 9e495172e5..ddc5113be3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
 @RBuiltin(name = "dim", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class Dim extends RBuiltinNode {
+public abstract class Dim extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(Dim.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
index 2993a023e5..bcbd242272 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
 @RBuiltin(name = "dimnames", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class DimNames extends RBuiltinNode {
+public abstract class DimNames extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 0c6e143e00..31f074a456 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -66,7 +66,7 @@ import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = ".fastr.do.call", visibility = CUSTOM, kind = RBuiltinKind.INTERNAL, parameterNames = {"what", "args", "quote", "envir"}, behavior = COMPLEX)
-public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNodeChildren {
+public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSyntaxNodeChildren {
 
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
index 295782ffed..c326691292 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "drop", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class Drop extends RBuiltinNode {
+public abstract class Drop extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile nullDimensions = ConditionProfile.createBinaryProfile();
     private final ConditionProfile resultIsVector = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
index b2043833e9..dface54eb3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
@@ -16,8 +16,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyList;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.binary.CastTypeNode;
@@ -32,18 +32,14 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 
 public class DuplicatedFunctions {
 
-    protected abstract static class Adapter extends RBuiltinNode {
-        @Child protected CastTypeNode castTypeNode;
-        @Child protected TypeofNode typeof;
-
-        private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile();
+    @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE)
+    public abstract static class Duplicated extends RBuiltinNode.Arg4 {
 
         protected static void casts(Casts casts) {
             // these are similar to those in DuplicatedFunctions.java
@@ -54,37 +50,6 @@ public class DuplicatedFunctions {
             casts.arg("fromLast").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
         }
 
-        protected boolean isIncomparable(RAbstractVector incomparables) {
-            if (incomparable.profile(incomparables.getLength() == 1 && incomparables instanceof RLogicalVector && ((RAbstractLogicalVector) incomparables).getDataAt(0) == RRuntime.LOGICAL_FALSE)) {
-                return false;
-            } else {
-                return true;
-            }
-        }
-
-        protected boolean notAbstractVector(Object o) {
-            return !(o instanceof RAbstractVector);
-        }
-
-        protected boolean empty(RAbstractContainer x) {
-            return x.getLength() == 0;
-        }
-
-        protected void initChildren() {
-            if (castTypeNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                castTypeNode = insert(CastTypeNodeGen.create(null, null));
-            }
-            if (typeof == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                typeof = insert(TypeofNodeGen.create());
-            }
-        }
-    }
-
-    @RBuiltin(name = "duplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax"}, behavior = PURE)
-    public abstract static class Duplicated extends Adapter {
-
         static {
             Casts casts = new Casts(Duplicated.class);
             casts(casts);
@@ -93,29 +58,48 @@ public class DuplicatedFunctions {
             casts.arg("nmax").asIntegerVector().findFirst(RRuntime.INT_NA);
         }
 
+        private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile();
+
+        protected boolean isIncomparable(RAbstractVector incomparables) {
+            if (incomparable.profile(incomparables.getLength() == 1 && incomparables instanceof RLogicalVector && ((RAbstractLogicalVector) incomparables).getDataAt(0) == RRuntime.LOGICAL_FALSE)) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+
         @TruffleBoundary
         protected static RLogicalVector analyzeAndCreateResult(RAbstractVector x, RAbstractVector incomparables, byte fromLast) {
             DuplicationHelper ds = DuplicationHelper.analyze(x, incomparables, false, RRuntime.fromLogical(fromLast));
             return RDataFactory.createLogicalVector(ds.getDupVec(), RDataFactory.COMPLETE_VECTOR);
         }
 
-        @Specialization(guards = {"!isIncomparable(incomparables)", "!empty(x)"})
+        @Specialization(guards = {"!isIncomparable(incomparables)", "x.getLength() != 0"})
         protected RLogicalVector duplicatedFalseIncomparables(RAbstractVector x, @SuppressWarnings("unused") RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) {
             return analyzeAndCreateResult(x, null, fromLast);
         }
 
-        @Specialization(guards = {"isIncomparable(incomparables)", "!empty(x)"})
-        protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax) {
-            initChildren();
+        protected static TypeofNode createTypeof() {
+            return TypeofNodeGen.create();
+        }
+
+        protected static CastTypeNode createCastType() {
+            return CastTypeNodeGen.create();
+        }
+
+        @Specialization(guards = {"isIncomparable(incomparables)", "x.getLength() != 0"})
+        protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast, @SuppressWarnings("unused") int nmax,
+                        @Cached("createTypeof()") TypeofNode typeof,
+                        @Cached("createCastType()") CastTypeNode castTypeNode) {
             RType xType = typeof.execute(x);
             RAbstractVector vector = (RAbstractVector) (castTypeNode.execute(incomparables, xType));
             return analyzeAndCreateResult(x, vector, fromLast);
         }
 
         @SuppressWarnings("unused")
-        @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"})
-        protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, Object incomparables, byte fromLast, int nmax) {
-            initChildren();
+        @Specialization(guards = {"!isRAbstractVector(incomparables)", "x.getLength() != 0"})
+        protected RLogicalVector duplicatedTrueIncomparables(RAbstractVector x, Object incomparables, byte fromLast, int nmax,
+                        @Cached("createTypeof()") TypeofNode typeof) {
             RType xType = typeof.execute(x);
             // TODO: this is not quite correct, as passing expression generated some obscure error
             // message, but is it worth fixing
@@ -123,44 +107,62 @@ public class DuplicatedFunctions {
         }
 
         @SuppressWarnings("unused")
-        @Specialization(guards = "empty(x)")
+        @Specialization(guards = "x.getLength() == 0")
         protected RLogicalVector duplicatedEmpty(RAbstractVector x, Object incomparables, byte fromLast, int nmax) {
             return RDataFactory.createEmptyLogicalVector();
         }
     }
 
     @RBuiltin(name = "anyDuplicated", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast"}, behavior = PURE)
-    public abstract static class AnyDuplicated extends Adapter {
+    public abstract static class AnyDuplicated extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(AnyDuplicated.class);
-            casts(casts);
+            Duplicated.casts(casts);
+        }
+
+        private final ConditionProfile incomparable = ConditionProfile.createBinaryProfile();
+
+        protected boolean isIncomparable(RAbstractVector incomparables) {
+            if (incomparable.profile(incomparables.getLength() == 1 && incomparables instanceof RLogicalVector && ((RAbstractLogicalVector) incomparables).getDataAt(0) == RRuntime.LOGICAL_FALSE)) {
+                return false;
+            } else {
+                return true;
+            }
         }
 
         @SuppressWarnings("unused")
-        @Specialization(guards = {"!isIncomparable(incomparables)", "!empty(x)"})
+        @Specialization(guards = {"!isIncomparable(incomparables)", "x.getLength() != 0"})
         protected int anyDuplicatedFalseIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast) {
             return DuplicationHelper.analyze(x, null, true, RRuntime.fromLogical(fromLast)).getIndex();
         }
 
-        @Specialization(guards = {"isIncomparable(incomparables)", "!empty(x)"})
-        protected int anyDuplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast) {
-            initChildren();
+        protected static TypeofNode createTypeof() {
+            return TypeofNodeGen.create();
+        }
+
+        protected static CastTypeNode createCastType() {
+            return CastTypeNodeGen.create();
+        }
+
+        @Specialization(guards = {"isIncomparable(incomparables)", "x.getLength() != 0"})
+        protected int anyDuplicatedTrueIncomparables(RAbstractVector x, RAbstractVector incomparables, byte fromLast,
+                        @Cached("createTypeof()") TypeofNode typeof,
+                        @Cached("createCastType()") CastTypeNode castTypeNode) {
             RType xType = typeof.execute(x);
             return DuplicationHelper.analyze(x, (RAbstractVector) (castTypeNode.execute(incomparables, xType)), true, RRuntime.fromLogical(fromLast)).getIndex();
         }
 
-        @Specialization(guards = {"notAbstractVector(incomparables)", "!empty(x)"})
+        @Specialization(guards = {"!isRAbstractVector(incomparables)", "x.getLength() != 0"})
         @TruffleBoundary
         protected int anyDuplicatedTrueIncomparables(RAbstractVector x, Object incomparables, @SuppressWarnings("unused") byte fromLast) {
-            initChildren();
             // TODO: this is not quite correct, as passing expression generated some obscure error
             // message, but is it worth fixing
             throw error(RError.Message.CANNOT_COERCE, TypeofNode.getTypeof(incomparables).getName(), TypeofNode.getTypeof(x).getName());
         }
 
         @SuppressWarnings("unused")
-        @Specialization(guards = "empty(x)")
+        @Specialization(guards = "x.getLength() == 0")
         protected int anyDuplicatedEmpty(RAbstractVector x, Object incomparables, byte fromLast) {
             return 0;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
index 535ada9f47..1156a95d30 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
@@ -58,7 +58,7 @@ public class DynLoadFunctions {
     private static final String DLLINFOLIST_CLASS = "DLLInfoList";
 
     @RBuiltin(name = "dyn.load", visibility = OFF, kind = INTERNAL, parameterNames = {"lib", "local", "now", "unused"}, behavior = COMPLEX)
-    public abstract static class DynLoad extends RBuiltinNode {
+    public abstract static class DynLoad extends RBuiltinNode.Arg4 {
         @Child private DLL.LoadPackageDLLNode loadPackageDLLNode = DLL.LoadPackageDLLNode.create();
 
         static {
@@ -82,7 +82,7 @@ public class DynLoadFunctions {
     }
 
     @RBuiltin(name = "dyn.unload", visibility = OFF, kind = INTERNAL, parameterNames = {"lib"}, behavior = COMPLEX)
-    public abstract static class DynUnload extends RBuiltinNode {
+    public abstract static class DynUnload extends RBuiltinNode.Arg1 {
         @Child DLL.UnloadNode dllUnloadNode = DLL.UnloadNode.create();
 
         static {
@@ -103,7 +103,7 @@ public class DynLoadFunctions {
     }
 
     @RBuiltin(name = "getLoadedDLLs", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class GetLoadedDLLs extends RBuiltinNode {
+    public abstract static class GetLoadedDLLs extends RBuiltinNode.Arg0 {
 
         @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create();
 
@@ -126,7 +126,7 @@ public class DynLoadFunctions {
     }
 
     @RBuiltin(name = "is.loaded", kind = INTERNAL, parameterNames = {"symbol", "PACKAGE", "type"}, behavior = READS_STATE)
-    public abstract static class IsLoaded extends RBuiltinNode {
+    public abstract static class IsLoaded extends RBuiltinNode.Arg3 {
         @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
 
         static {
@@ -162,7 +162,7 @@ public class DynLoadFunctions {
     }
 
     @RBuiltin(name = "getSymbolInfo", kind = INTERNAL, parameterNames = {"symbol", "package", "withRegistrationInfo"}, behavior = READS_STATE)
-    public abstract static class GetSymbolInfo extends RBuiltinNode {
+    public abstract static class GetSymbolInfo extends RBuiltinNode.Arg3 {
         @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
 
         static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
index 2cdec5a98c..edff830f72 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "encodeString", kind = INTERNAL, parameterNames = {"x", "width", "quote", "justify", "na.encode"}, behavior = READS_STATE)
-public abstract class EncodeString extends RBuiltinNode {
+public abstract class EncodeString extends RBuiltinNode.Arg5 {
 
     private enum JUSTIFY {
         LEFT,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
index 6bd38e8e75..e06312a5ed 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodingFunctions.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public class EncodingFunctions {
 
     @RBuiltin(name = "Encoding", kind = INTERNAL, parameterNames = "x", behavior = PURE)
-    public abstract static class Encoding extends RBuiltinNode {
+    public abstract static class Encoding extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Encoding.class);
@@ -53,7 +53,7 @@ public class EncodingFunctions {
     }
 
     @RBuiltin(name = "setEncoding", kind = INTERNAL, parameterNames = {"x", "value"}, behavior = PURE)
-    public abstract static class SetEncoding extends RBuiltinNode {
+    public abstract static class SetEncoding extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(SetEncoding.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 1883d63bc9..1f9ed8bb22 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -93,11 +93,8 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
  */
 public class EnvFunctions {
 
-    protected abstract static class Adapter extends RBuiltinNode {
-    }
-
     @RBuiltin(name = "as.environment", kind = PRIMITIVE, parameterNames = {"fun"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
-    public abstract static class AsEnvironment extends Adapter {
+    public abstract static class AsEnvironment extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(AsEnvironment.class);
@@ -200,7 +197,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "emptyenv", kind = PRIMITIVE, parameterNames = {}, behavior = PURE)
-    public abstract static class EmptyEnv extends RBuiltinNode {
+    public abstract static class EmptyEnv extends RBuiltinNode.Arg0 {
 
         @Specialization
         protected REnvironment emptyenv() {
@@ -209,7 +206,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "globalenv", kind = PRIMITIVE, parameterNames = {}, behavior = PURE)
-    public abstract static class GlobalEnv extends RBuiltinNode {
+    public abstract static class GlobalEnv extends RBuiltinNode.Arg0 {
 
         @Specialization
         protected Object globalenv() {
@@ -221,7 +218,7 @@ public class EnvFunctions {
      * Returns the "package:base" environment.
      */
     @RBuiltin(name = "baseenv", kind = PRIMITIVE, parameterNames = {}, behavior = PURE)
-    public abstract static class BaseEnv extends RBuiltinNode {
+    public abstract static class BaseEnv extends RBuiltinNode.Arg0 {
 
         @Specialization
         protected Object baseenv() {
@@ -230,7 +227,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "topenv", kind = INTERNAL, parameterNames = {"envir", "matchThisEnv"}, behavior = COMPLEX)
-    public abstract static class TopEnv extends Adapter {
+    public abstract static class TopEnv extends RBuiltinNode.Arg2 {
 
         static {
             Casts.noCasts(TopEnv.class);
@@ -238,6 +235,7 @@ public class EnvFunctions {
 
         @Child private FrameFunctions.ParentFrame parentFrameNode;
 
+        @Override
         public abstract Object execute(VirtualFrame frame, Object execute, Object instance);
 
         @Specialization
@@ -287,7 +285,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "parent.env", kind = INTERNAL, parameterNames = {"env"}, behavior = READS_FRAME)
-    public abstract static class ParentEnv extends Adapter {
+    public abstract static class ParentEnv extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(ParentEnv.class);
@@ -304,7 +302,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "parent.env<-", kind = INTERNAL, parameterNames = {"env", "value"}, behavior = COMPLEX)
-    public abstract static class SetParentEnv extends Adapter {
+    public abstract static class SetParentEnv extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(SetParentEnv.class);
@@ -324,7 +322,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "is.environment", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class IsEnvironment extends RBuiltinNode {
+    public abstract static class IsEnvironment extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(IsEnvironment.class);
@@ -337,7 +335,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "environment", kind = INTERNAL, parameterNames = {"fun"}, behavior = COMPLEX)
-    public abstract static class Environment extends RBuiltinNode {
+    public abstract static class Environment extends RBuiltinNode.Arg1 {
 
         private final ConditionProfile attributable = ConditionProfile.createBinaryProfile();
         @Child private GetFixedAttributeNode getEnvAttrNode;
@@ -407,7 +405,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "environment<-", kind = PRIMITIVE, parameterNames = {"env", "value"}, behavior = COMPLEX)
-    public abstract static class UpdateEnvironment extends RBuiltinNode {
+    public abstract static class UpdateEnvironment extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(UpdateEnvironment.class);
@@ -487,7 +485,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "environmentName", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
-    public abstract static class EnvironmentName extends RBuiltinNode {
+    public abstract static class EnvironmentName extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(EnvironmentName.class);
@@ -506,7 +504,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "new.env", kind = INTERNAL, parameterNames = {"hash", "parent", "size"}, behavior = COMPLEX)
-    public abstract static class NewEnv extends RBuiltinNode {
+    public abstract static class NewEnv extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(NewEnv.class);
@@ -525,7 +523,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "search", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class Search extends RBuiltinNode {
+    public abstract static class Search extends RBuiltinNode.Arg0 {
         @Specialization
         protected RStringVector search() {
             return RDataFactory.createStringVector(REnvironment.searchPath(), RDataFactory.COMPLETE_VECTOR);
@@ -533,7 +531,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "lockEnvironment", visibility = OFF, kind = INTERNAL, parameterNames = {"env", "bindings"}, behavior = COMPLEX)
-    public abstract static class LockEnvironment extends RBuiltinNode {
+    public abstract static class LockEnvironment extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(LockEnvironment.class);
@@ -550,7 +548,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "environmentIsLocked", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE)
-    public abstract static class EnvironmentIsLocked extends RBuiltinNode {
+    public abstract static class EnvironmentIsLocked extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(EnvironmentIsLocked.class);
@@ -564,7 +562,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "lockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX)
-    public abstract static class LockBinding extends RBuiltinNode {
+    public abstract static class LockBinding extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(LockBinding.class);
@@ -580,7 +578,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "unlockBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = COMPLEX)
-    public abstract static class UnlockBinding extends RBuiltinNode {
+    public abstract static class UnlockBinding extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(UnlockBinding.class);
@@ -596,7 +594,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "bindingIsLocked", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE)
-    public abstract static class BindingIsLocked extends RBuiltinNode {
+    public abstract static class BindingIsLocked extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(BindingIsLocked.class);
@@ -611,7 +609,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "makeActiveBinding", visibility = OFF, kind = INTERNAL, parameterNames = {"sym", "fun", "env"}, behavior = COMPLEX)
-    public abstract static class MakeActiveBinding extends RBuiltinNode {
+    public abstract static class MakeActiveBinding extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(MakeActiveBinding.class);
@@ -656,7 +654,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "bindingIsActive", kind = INTERNAL, parameterNames = {"sym", "env"}, behavior = PURE)
-    public abstract static class BindingIsActive extends RBuiltinNode {
+    public abstract static class BindingIsActive extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(BindingIsActive.class);
@@ -675,7 +673,7 @@ public class EnvFunctions {
     }
 
     @RBuiltin(name = "env2list", kind = INTERNAL, parameterNames = {"x", "all.names", "sorted"}, behavior = PURE)
-    public abstract static class EnvToList extends RBuiltinNode {
+    public abstract static class EnvToList extends RBuiltinNode.Arg3 {
 
         @Child private CopyNode copy;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
index 2164f840c0..1a2c94f5c7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Eval.java
@@ -62,7 +62,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * Contains the {@code eval} {@code .Internal} implementation.
  */
 @RBuiltin(name = "eval", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"expr", "envir", "enclos"}, behavior = COMPLEX)
-public abstract class Eval extends RBuiltinNode {
+public abstract class Eval extends RBuiltinNode.Arg3 {
 
     /**
      * Profiling for catching {@link ReturnException}s.
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java
index f08f18daa3..2e8a04837d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Exists.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "exists", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits"}, behavior = PURE)
-public abstract class Exists extends RBuiltinNode {
+public abstract class Exists extends RBuiltinNode.Arg4 {
 
     @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
index f4b9d0c8e5..6e245e1ed7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Expression.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
 @RBuiltin(name = "expression", kind = PRIMITIVE, parameterNames = {"..."}, nonEvalArgs = 0, behavior = PURE)
-public abstract class Expression extends RBuiltinNode {
+public abstract class Expression extends RBuiltinNode.Arg1 {
     /*
      * Owing to the nonEvalArgs, all arguments are RPromise, but an expression may contain
      * non-RLanguage elements.
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index ef3d5d4f01..14493a1eeb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -88,7 +88,7 @@ import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 public class FileFunctions {
 
     @RBuiltin(name = "file.access", kind = INTERNAL, parameterNames = {"names", "mode"}, behavior = IO)
-    public abstract static class FileAccess extends RBuiltinNode {
+    public abstract static class FileAccess extends RBuiltinNode.Arg2 {
         private static final int EXECUTE = 1;
         private static final int WRITE = 2;
         private static final int READ = 4;
@@ -124,7 +124,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.append", kind = INTERNAL, parameterNames = {"file1", "file2"}, behavior = IO)
-    public abstract static class FileAppend extends RBuiltinNode {
+    public abstract static class FileAppend extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(FileAppend.class);
@@ -220,7 +220,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.create", kind = INTERNAL, parameterNames = {"vec", "showWarnings"}, behavior = IO)
-    public abstract static class FileCreate extends RBuiltinNode {
+    public abstract static class FileCreate extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(FileCreate.class);
@@ -254,7 +254,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.info", kind = INTERNAL, parameterNames = {"fn", "extra_cols"}, behavior = IO)
-    public abstract static class FileInfo extends RBuiltinNode {
+    public abstract static class FileInfo extends RBuiltinNode.Arg2 {
         // @formatter:off
         private  enum Column {
             size, isdir, mode, mtime, ctime, atime, uid, gid, uname, grname;
@@ -424,7 +424,7 @@ public class FileFunctions {
         }
     }
 
-    private abstract static class FileLinkAdaptor extends RBuiltinNode {
+    private abstract static class FileLinkAdaptor extends RBuiltinNode.Arg2 {
 
         protected static void casts(Class<? extends FileLinkAdaptor> builtinClass) {
             Casts casts = new Casts(builtinClass);
@@ -502,7 +502,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.remove", kind = INTERNAL, parameterNames = {"file"}, behavior = IO)
-    public abstract static class FileRemove extends RBuiltinNode {
+    public abstract static class FileRemove extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(FileRemove.class);
@@ -531,7 +531,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.rename", kind = INTERNAL, parameterNames = {"from", "to"}, behavior = IO)
-    public abstract static class FileRename extends RBuiltinNode {
+    public abstract static class FileRename extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(FileRename.class);
@@ -567,7 +567,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.exists", kind = INTERNAL, parameterNames = {"file"}, behavior = IO)
-    public abstract static class FileExists extends RBuiltinNode {
+    public abstract static class FileExists extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(FileExists.class);
@@ -594,7 +594,7 @@ public class FileFunctions {
 
     // TODO Implement all the options
     @RBuiltin(name = "list.files", kind = INTERNAL, parameterNames = {"path", "pattern", "all.files", "full.names", "recursive", "ignore.case", "include.dirs", "no.."}, behavior = IO)
-    public abstract static class ListFiles extends RBuiltinNode {
+    public abstract static class ListFiles extends RBuiltinNode.Arg8 {
         private static final String DOT = ".";
         private static final String DOTDOT = "..";
 
@@ -738,7 +738,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "list.dirs", kind = INTERNAL, parameterNames = {"directory", "full.names", "recursive"}, behavior = IO)
-    public abstract static class ListDirs extends RBuiltinNode {
+    public abstract static class ListDirs extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(ListDirs.class);
@@ -794,7 +794,7 @@ public class FileFunctions {
 
     // TODO handle the general case, which is similar to paste
     @RBuiltin(name = "file.path", kind = INTERNAL, parameterNames = {"paths", "fsep"}, behavior = IO)
-    public abstract static class FilePath extends RBuiltinNode {
+    public abstract static class FilePath extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(FilePath.class);
@@ -893,7 +893,7 @@ public class FileFunctions {
      * {@code file.copy} builtin. This is only called when the target is a directory.
      */
     @RBuiltin(name = "file.copy", kind = INTERNAL, parameterNames = {"from", "to", "overwrite", "recursive", "copy.mode", "copy.date"}, behavior = IO)
-    public abstract static class FileCopy extends RBuiltinNode {
+    public abstract static class FileCopy extends RBuiltinNode.Arg6 {
 
         static {
             Casts casts = new Casts(FileCopy.class);
@@ -1028,7 +1028,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "file.show", kind = INTERNAL, parameterNames = {"files", "header", "title", "delete.file", "pager"}, visibility = OFF, behavior = IO)
-    public abstract static class FileShow extends RBuiltinNode {
+    public abstract static class FileShow extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(FileShow.class);
@@ -1086,7 +1086,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "dirname", kind = INTERNAL, parameterNames = {"path"}, behavior = IO)
-    public abstract static class DirName extends RBuiltinNode {
+    public abstract static class DirName extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(DirName.class);
@@ -1105,7 +1105,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "basename", kind = INTERNAL, parameterNames = {"path"}, behavior = IO)
-    public abstract static class BaseName extends RBuiltinNode {
+    public abstract static class BaseName extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(BaseName.class);
@@ -1124,7 +1124,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "unlink", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "recursive", "force"}, behavior = IO)
-    public abstract static class Unlink extends RBuiltinNode {
+    public abstract static class Unlink extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(Unlink.class);
@@ -1193,7 +1193,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "dir.create", visibility = OFF, kind = INTERNAL, parameterNames = {"path", "showWarnings", "recursive", "mode"}, behavior = IO)
-    public abstract static class DirCreate extends RBuiltinNode {
+    public abstract static class DirCreate extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(DirCreate.class);
@@ -1251,7 +1251,7 @@ public class FileFunctions {
     }
 
     @RBuiltin(name = "dir.exists", kind = INTERNAL, parameterNames = "paths", behavior = IO)
-    public abstract static class DirExists extends RBuiltinNode {
+    public abstract static class DirExists extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(DirExists.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java
index 3368086a65..3cef036d53 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
 @RBuiltin(name = "forceAndCall", kind = PRIMITIVE, parameterNames = {"n", "FUN", "..."}, nonEvalArgs = 2, behavior = COMPLEX)
-public abstract class ForceAndCall extends RBuiltinNode {
+public abstract class ForceAndCall extends RBuiltinNode.Arg3 {
 
     @Child private RExplicitCallNode call = RExplicitCallNode.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
index ce083781b2..91e682f999 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Formals.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 @RBuiltin(name = "formals", kind = INTERNAL, parameterNames = {"fun"}, behavior = PURE)
-public abstract class Formals extends RBuiltinNode {
+public abstract class Formals extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(Formals.class);
@@ -72,9 +72,6 @@ public abstract class Formals extends RBuiltinNode {
             return RNull.instance;
         }
         FunctionDefinitionNode fdNode = (FunctionDefinitionNode) fun.getTarget().getRootNode();
-        if (fdNode.getParameterCount() == 0) {
-            return RNull.instance;
-        }
         FormalArguments formalArgs = fdNode.getFormalArguments();
         Object succ = RNull.instance;
         for (int i = formalArgs.getSignature().getLength() - 1; i >= 0; i--) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index d383f0330e..aaeb3235e0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @SuppressWarnings("unused")
 @RBuiltin(name = "format", kind = INTERNAL, parameterNames = {"x", "trim", "digits", "nsmall", "width", "justify", "na.encode", "scientific", "decimal.mark"}, behavior = PURE)
-public abstract class Format extends RBuiltinNode {
+public abstract class Format extends RBuiltinNode.Arg9 {
 
     @Child private CastIntegerNode castInteger;
     @Child protected ValuePrinterNode valuePrinter = new ValuePrinterNode();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
index f0d0e4ea81..bab1c07593 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "formatC", kind = INTERNAL, parameterNames = {"x", "mode", "width", "digits", "format", "flag", "i.strlen"}, behavior = PURE)
-public abstract class FormatC extends RBuiltinNode {
+public abstract class FormatC extends RBuiltinNode.Arg7 {
 
     @Child private RoundArithmetic round = new RoundArithmetic();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
index 19e877dcd4..84af1f0ca3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
@@ -78,6 +78,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -90,7 +91,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  */
 public class FrameFunctions {
 
-    public abstract static class FrameHelper extends RBuiltinNode {
+    public static final class FrameHelper extends RBaseNode {
 
         private final ConditionProfile currentFrameProfile = ConditionProfile.createBinaryProfile();
 
@@ -99,7 +100,11 @@ public class FrameFunctions {
          * only use the frame internally should not materialize it, i.e., they should use
          * {@link FrameAccess#READ_ONLY} or {@link FrameAccess#READ_WRITE}.
          */
-        protected abstract FrameAccess frameAccess();
+        private final FrameAccess access;
+
+        public FrameHelper(FrameAccess access) {
+            this.access = access;
+        }
 
         protected Frame getFrame(VirtualFrame frame, int n) {
             int actualFrame = decodeFrameNumber(RArguments.getCall(frame), n);
@@ -161,7 +166,7 @@ public class FrameFunctions {
                     }
                     notifyRCallNodes(actualFrame, RArguments.getCall(frame));
                 }
-                return Utils.getStackFrame(frameAccess(), actualFrame);
+                return Utils.getStackFrame(access, actualFrame);
             }
         }
 
@@ -181,18 +186,15 @@ public class FrameFunctions {
     }
 
     @RBuiltin(name = "sys.call", kind = INTERNAL, parameterNames = {"which"}, behavior = COMPLEX)
-    public abstract static class SysCall extends FrameHelper {
+    public abstract static class SysCall extends RBuiltinNode.Arg1 {
+
+        @Child private FrameHelper helper = new FrameHelper(FrameAccess.READ_ONLY);
 
         static {
             Casts casts = new Casts(SysCall.class);
             casts.arg("which").asIntegerVector().findFirst();
         }
 
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.READ_ONLY;
-        }
-
         @Specialization
         protected Object sysCall(VirtualFrame frame, int which) {
             /*
@@ -203,7 +205,7 @@ public class FrameFunctions {
 
         @TruffleBoundary
         private Object createCall(RCaller currentCall, int which) {
-            RCaller call = getCall(currentCall, which);
+            RCaller call = helper.getCall(currentCall, which);
             assert !call.isPromise();
             if (call == null || !call.isValidCaller()) {
                 return RNull.instance;
@@ -227,12 +229,9 @@ public class FrameFunctions {
      * using "..." that make the code a lot more complex that it seems it ought to be.
      */
     @RBuiltin(name = "match.call", kind = INTERNAL, parameterNames = {"definition", "call", "expand.dots", "envir"}, behavior = COMPLEX)
-    public abstract static class MatchCall extends FrameHelper {
+    public abstract static class MatchCall extends RBuiltinNode.Arg4 {
 
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.READ_ONLY;
-        }
+        @Child private FrameHelper helper = new FrameHelper(FrameAccess.READ_ONLY);
 
         static {
             Casts casts = new Casts(MatchCall.class);
@@ -401,7 +400,7 @@ public class FrameFunctions {
     }
 
     @RBuiltin(name = "sys.nframe", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class SysNFrame extends RBuiltinNode {
+    public abstract static class SysNFrame extends RBuiltinNode.Arg0 {
 
         private final BranchProfile isPromiseCurrentProfile = BranchProfile.create();
         private final BranchProfile isPromiseResultProfile = BranchProfile.create();
@@ -422,13 +421,11 @@ public class FrameFunctions {
         }
     }
 
-    private abstract static class DeoptHelper extends FrameHelper {
-        protected final PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode();
-
-    }
-
     @RBuiltin(name = "sys.frame", kind = INTERNAL, parameterNames = {"which"}, behavior = COMPLEX)
-    public abstract static class SysFrame extends DeoptHelper {
+    public abstract static class SysFrame extends RBuiltinNode.Arg1 {
+
+        @Child private FrameHelper helper = new FrameHelper(FrameAccess.MATERIALIZE);
+        @Child private PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode();
 
         private final ConditionProfile zeroProfile = ConditionProfile.createBinaryProfile();
 
@@ -438,11 +435,6 @@ public class FrameFunctions {
             return SysFrameNodeGen.create();
         }
 
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.MATERIALIZE;
-        }
-
         static {
             Casts casts = new Casts(SysFrame.class);
             casts.arg("which").asIntegerVector().findFirst();
@@ -454,23 +446,21 @@ public class FrameFunctions {
             if (zeroProfile.profile(which == 0)) {
                 result = REnvironment.globalEnv();
             } else {
-                Frame callerFrame = getFrame(frame, which);
+                Frame callerFrame = helper.getFrame(frame, which);
                 result = REnvironment.frameToEnvironment(callerFrame.materialize());
             }
 
             // Deoptimize every promise which is now in this frame, as it might leave it's stack
             deoptFrameNode.deoptimizeFrame(result.getFrame());
-
             return result;
         }
     }
 
     @RBuiltin(name = "sys.frames", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class SysFrames extends DeoptHelper {
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.MATERIALIZE;
-        }
+    public abstract static class SysFrames extends RBuiltinNode.Arg0 {
+
+        @Child private FrameHelper helper = new FrameHelper(FrameAccess.MATERIALIZE);
+        @Child private PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode();
 
         @Specialization
         protected Object sysFrames(VirtualFrame frame) {
@@ -481,7 +471,7 @@ public class FrameFunctions {
                 RPairList result = RDataFactory.createPairList();
                 RPairList next = result;
                 for (int i = 1; i < depth; i++) {
-                    MaterializedFrame mf = getNumberedFrame(frame, i).materialize();
+                    MaterializedFrame mf = helper.getNumberedFrame(frame, i).materialize();
                     deoptFrameNode.deoptimizeFrame(mf);
                     next.setCar(REnvironment.frameToEnvironment(mf));
                     if (i != depth - 1) {
@@ -498,12 +488,7 @@ public class FrameFunctions {
     }
 
     @RBuiltin(name = "sys.calls", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class SysCalls extends FrameHelper {
-
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.READ_ONLY;
-        }
+    public abstract static class SysCalls extends RBuiltinNode.Arg0 {
 
         @Specialization
         protected Object sysCalls(VirtualFrame frame) {
@@ -545,7 +530,7 @@ public class FrameFunctions {
     }
 
     @RBuiltin(name = "sys.parent", kind = INTERNAL, parameterNames = {"n"}, behavior = COMPLEX)
-    public abstract static class SysParent extends RBuiltinNode {
+    public abstract static class SysParent extends RBuiltinNode.Arg1 {
 
         private final BranchProfile nullCallerProfile = BranchProfile.create();
         private final BranchProfile promiseProfile = BranchProfile.create();
@@ -576,14 +561,11 @@ public class FrameFunctions {
     }
 
     @RBuiltin(name = "sys.function", kind = INTERNAL, parameterNames = {"which"}, splitCaller = true, alwaysSplit = true, behavior = COMPLEX)
-    public abstract static class SysFunction extends FrameHelper {
+    public abstract static class SysFunction extends RBuiltinNode.Arg1 {
 
-        public abstract Object executeObject(VirtualFrame frame, int which);
+        @Child private FrameHelper helper = new FrameHelper(FrameAccess.READ_ONLY);
 
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.READ_ONLY;
-        }
+        public abstract Object executeObject(VirtualFrame frame, int which);
 
         static {
             Casts casts = new Casts(SysFunction.class);
@@ -593,7 +575,7 @@ public class FrameFunctions {
         @Specialization
         protected Object sysFunction(VirtualFrame frame, int which) {
             // N.B. Despite the spec, n==0 is treated as the current function
-            Frame callerFrame = getFrame(frame, which);
+            Frame callerFrame = helper.getFrame(frame, which);
             RFunction func = RArguments.getFunction(callerFrame);
 
             if (func == null) {
@@ -605,12 +587,7 @@ public class FrameFunctions {
     }
 
     @RBuiltin(name = "sys.parents", kind = INTERNAL, parameterNames = {}, behavior = COMPLEX)
-    public abstract static class SysParents extends FrameHelper {
-
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.READ_ONLY;
-        }
+    public abstract static class SysParents extends RBuiltinNode.Arg0 {
 
         @Specialization
         protected RIntVector sysParents(VirtualFrame frame) {
@@ -649,7 +626,9 @@ public class FrameFunctions {
      * The environment of the caller of the function that called parent.frame.
      */
     @RBuiltin(name = "parent.frame", kind = SUBSTITUTE, parameterNames = {"n"}, behavior = COMPLEX)
-    public abstract static class ParentFrame extends FrameHelper {
+    public abstract static class ParentFrame extends RBuiltinNode.Arg1 {
+
+        @Child private FrameHelper helper = new FrameHelper(FrameAccess.MATERIALIZE);
 
         private final BranchProfile nullCallerProfile = BranchProfile.create();
         private final BranchProfile promiseProfile = BranchProfile.create();
@@ -667,11 +646,6 @@ public class FrameFunctions {
             return new Object[]{1};
         }
 
-        @Override
-        protected final FrameAccess frameAccess() {
-            return FrameAccess.MATERIALIZE;
-        }
-
         @Specialization(guards = "n == 1")
         protected REnvironment parentFrameDirect(VirtualFrame frame, @SuppressWarnings("unused") int n,
                         @Cached("new()") GetCallerFrameNode getCaller) {
@@ -708,7 +682,7 @@ public class FrameFunctions {
             // */
             // parentDepth--;
             // }
-            return REnvironment.frameToEnvironment(getNumberedFrame(frame, call.getDepth()).materialize());
+            return REnvironment.frameToEnvironment(helper.getNumberedFrame(frame, call.getDepth()).materialize());
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
index f2dd9f3eb1..7a5326f066 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Gc.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 
 @RBuiltin(name = "gc", kind = INTERNAL, parameterNames = {"verbose", "reset"}, behavior = COMPLEX)
-public abstract class Gc extends RBuiltinNode {
+public abstract class Gc extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(Gc.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java
index 2a2ddedc86..62e9ca8f72 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java
@@ -21,7 +21,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "class", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class GetClass extends RBuiltinNode {
+public abstract class GetClass extends RBuiltinNode.Arg1 {
 
     @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(true, false);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index 1293084d77..a05fba7d0a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode;
@@ -73,14 +72,16 @@ import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * assert: not expected to be fast even when called as, e.g., {@code get("x")}.
  */
 public class GetFunctions {
-    public abstract static class Adapter extends RBuiltinNode {
-        protected final ValueProfile modeProfile = ValueProfile.createIdentityProfile();
+    private static final class Helper extends RBaseNode {
+
         protected final BranchProfile recursiveProfile = BranchProfile.create();
+
         @Child private PromiseHelperNode promiseHelper = new PromiseHelperNode();
         @Child protected TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create();
 
@@ -160,7 +161,9 @@ public class GetFunctions {
     }
 
     @RBuiltin(name = "get", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits"}, behavior = COMPLEX)
-    public abstract static class Get extends Adapter {
+    public abstract static class Get extends RBuiltinNode.Arg4 {
+
+        @Child private Helper helper = new Helper();
 
         private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile();
 
@@ -177,11 +180,11 @@ public class GetFunctions {
 
         @Specialization
         public Object get(VirtualFrame frame, String x, REnvironment envir, String mode, boolean inherits) {
-            RType modeType = typeFromMode.execute(mode);
+            RType modeType = helper.typeFromMode.execute(mode);
             if (inheritsProfile.profile(inherits)) {
-                return getInherits(frame, x, envir, modeType, mode, true);
+                return helper.getInherits(frame, x, envir, modeType, mode, true);
             } else {
-                return getAndCheck(frame, x, envir, modeType, mode, true);
+                return helper.getAndCheck(frame, x, envir, modeType, mode, true);
             }
         }
 
@@ -200,7 +203,9 @@ public class GetFunctions {
     }
 
     @RBuiltin(name = "get0", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits", "ifnotfound"}, behavior = COMPLEX)
-    public abstract static class Get0 extends Adapter {
+    public abstract static class Get0 extends RBuiltinNode.Arg5 {
+
+        @Child private Helper helper = new Helper();
 
         private final ConditionProfile inheritsProfile = ConditionProfile.createBinaryProfile();
 
@@ -216,11 +221,11 @@ public class GetFunctions {
         @Specialization
         protected Object get0(VirtualFrame frame, String x, REnvironment envir, String mode, boolean inherits, Object ifnotfound) {
             Object result;
-            RType modeType = typeFromMode.execute(mode);
+            RType modeType = helper.typeFromMode.execute(mode);
             if (inheritsProfile.profile(inherits)) {
-                result = getInherits(frame, x, envir, modeType, mode, false);
+                result = helper.getInherits(frame, x, envir, modeType, mode, false);
             } else {
-                result = getAndCheck(frame, x, envir, modeType, mode, false);
+                result = helper.getAndCheck(frame, x, envir, modeType, mode, false);
             }
             if (result == null) {
                 result = ifnotfound;
@@ -242,7 +247,9 @@ public class GetFunctions {
     }
 
     @RBuiltin(name = "mget", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "ifnotfound", "inherits"}, behavior = COMPLEX)
-    public abstract static class MGet extends Adapter {
+    public abstract static class MGet extends RBuiltinNode.Arg5 {
+
+        @Child private Helper helper = new Helper();
 
         private final BranchProfile wrongLengthErrorProfile = BranchProfile.create();
 
@@ -318,12 +325,12 @@ public class GetFunctions {
                 if (inheritsProfile.profile(inherits)) {
                     Object r = envir.get(x);
                     if (r == null || !RRuntime.checkType(r, modeType)) {
-                        recursiveProfile.enter();
+                        helper.recursiveProfile.enter();
                         REnvironment env = envir;
                         while (env != REnvironment.emptyEnv()) {
                             env = env.getParent();
                             if (env != REnvironment.emptyEnv()) {
-                                r = checkPromise(frame, env.get(x), x);
+                                r = helper.checkPromise(frame, env.get(x), x);
                                 if (r != null && RRuntime.checkType(r, modeType)) {
                                     break;
                                 }
@@ -336,7 +343,7 @@ public class GetFunctions {
                         state.data[i] = r;
                     }
                 } else {
-                    Object r = checkPromise(frame, envir.get(x), x);
+                    Object r = helper.checkPromise(frame, envir.get(x), x);
                     if (r != null && RRuntime.checkType(r, modeType)) {
                         state.data[i] = r;
                     } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
index 44d7c6121b..8301704079 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
 @RBuiltin(name = "oldClass", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class GetOldClass extends RBuiltinNode {
+public abstract class GetOldClass extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile();
     @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
index 4262e5e87a..6368703c0f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetText.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "gettext", kind = INTERNAL, parameterNames = {"domain", "args"}, behavior = PURE)
-public abstract class GetText extends RBuiltinNode {
+public abstract class GetText extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(GetText.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java
index 1e5ab0b374..c8244e9b43 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
 @RBuiltin(name = "getwd", kind = INTERNAL, parameterNames = {}, behavior = IO)
-public abstract class Getwd extends RBuiltinNode {
+public abstract class Getwd extends RBuiltinNode.Arg0 {
 
     @Child private BaseRFFI.GetwdNode getwdNode = BaseRFFI.GetwdNode.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index f5ee34bcfe..250ccd5ed6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -29,9 +29,14 @@ import java.util.regex.PatternSyntaxException;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -48,6 +53,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 /**
@@ -66,57 +72,58 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * Parts of this code, notably the perl support, were translated from GnuR grep.c.
  */
 public class GrepFunctions {
-    public abstract static class CommonCodeAdapter extends RBuiltinNode {
-        @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode();
-        @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getRFFI().getPCRERFFI().createCompileNode();
+    protected static void castPattern(Casts casts) {
+        // with default error message, NO_CALLER does not work
+        casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT,
+                        "pattern");
+    }
 
-        protected static void castPattern(Casts casts) {
-            // with default error message, NO_CALLER does not work
-            casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT,
-                            "pattern");
-        }
+    protected static void castPatternSingle(Casts casts) {
+        // with default error message, NO_CALLER does not work
+        casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT,
+                        "pattern").shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "pattern").findFirst();
+    }
 
-        protected static void castPatternSingle(Casts casts) {
-            // with default error message, NO_CALLER does not work
-            casts.arg("pattern").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "pattern").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT,
-                            "pattern").shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "pattern").findFirst();
-        }
+    protected static void castText(Casts casts, String textId) {
+        casts.arg(textId).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, textId);
+    }
 
-        protected static void castText(Casts casts, String textId) {
-            casts.arg(textId).mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, textId);
-        }
+    protected static void castIgnoreCase(Casts casts) {
+        casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+    }
 
-        protected static void castIgnoreCase(Casts casts) {
-            casts.arg("ignore.case").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
-        }
+    protected static void castPerl(Casts casts) {
+        casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+    }
 
-        protected static void castPerl(Casts casts) {
-            casts.arg("perl").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
-        }
+    protected static void castFixed(Casts casts, byte defaultValue) {
+        casts.arg("fixed").asLogicalVector().findFirst(defaultValue).map(toBoolean());
+    }
 
-        protected static void castFixed(Casts casts, byte defaultValue) {
-            casts.arg("fixed").asLogicalVector().findFirst(defaultValue).map(toBoolean());
-        }
+    protected static void castValue(Casts casts) {
+        casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+    }
 
-        protected static void castValue(Casts casts) {
-            casts.arg("value").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
-        }
+    protected static void castCosts(Casts casts) {
+        casts.arg("costs").defaultError(RError.Message.INVALID_ARG, "costs").mustBe((missingValue().or(nullValue()).not())).asIntegerVector();
+    }
 
-        protected static void castUseBytes(Casts casts) {
-            casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
-        }
+    protected static void castUseBytes(Casts casts) {
+        casts.arg("useBytes").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+    }
 
-        protected static void castInvert(Casts casts) {
-            casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
-        }
+    protected static void castInvert(Casts casts) {
+        casts.arg("invert").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).map(toBoolean());
+    }
 
-        protected static void castCosts(Casts casts) {
-            casts.arg("costs").defaultError(RError.Message.INVALID_ARG, "costs").mustBe((missingValue().or(nullValue()).not())).asIntegerVector();
-        }
+    protected static void castBounds(Casts casts) {
+        casts.arg("bounds").defaultError(RError.Message.INVALID_ARG, "bounds").mustBe((missingValue().or(nullValue()).not())).asDoubleVector();
+    }
 
-        protected static void castBounds(Casts casts) {
-            casts.arg("bounds").defaultError(RError.Message.INVALID_ARG, "bounds").mustBe((missingValue().or(nullValue()).not())).asDoubleVector();
-        }
+    @NodeInfo(cost = NodeCost.NONE)
+    public static class CommonCodeNode extends RBaseNode {
+        @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode();
+        @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getRFFI().getPCRERFFI().createCompileNode();
 
         /**
          * Temporary method that handles the check for the arguments that are common to the majority
@@ -209,7 +216,7 @@ public class GrepFunctions {
         }
     }
 
-    private abstract static class GrepAdapter extends CommonCodeAdapter {
+    protected static final class GrepCommonCodeNode extends CommonCodeNode {
         @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
 
         protected Object doGrep(String patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean value, boolean perlPar, boolean fixed,
@@ -292,7 +299,7 @@ public class GrepFunctions {
             }
         }
 
-        protected void findAllMatches(boolean[] result, String pattern, RAbstractStringVector vector, boolean fixed, boolean ignoreCase) {
+        protected static void findAllMatches(boolean[] result, String pattern, RAbstractStringVector vector, boolean fixed, boolean ignoreCase) {
             for (int i = 0; i < result.length; i++) {
                 String text = vector.getDataAt(i);
                 if (!RRuntime.isNA(text)) {
@@ -311,8 +318,21 @@ public class GrepFunctions {
         }
     }
 
+    public static CommonCodeNode createCommon() {
+        return new CommonCodeNode();
+    }
+
+    public static GrepCommonCodeNode createGrepCommon() {
+        return new GrepCommonCodeNode();
+    }
+
+    public static SubCommonCodeNode createSubCommon() {
+        return new SubCommonCodeNode();
+    }
+
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "grep", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE)
-    public abstract static class Grep extends GrepAdapter {
+    public abstract static class Grep extends RBuiltinNode.Arg8 {
 
         static {
             Casts casts = new Casts(Grep.class);
@@ -358,13 +378,15 @@ public class GrepFunctions {
         @Specialization
         @TruffleBoundary
         protected Object grepValueFalse(String patternArgVec, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical,
-                        boolean useBytes, boolean invertLogical) {
-            return doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, false);
+                        boolean useBytes, boolean invertLogical,
+                        @Cached("createGrepCommon()") GrepCommonCodeNode common) {
+            return common.doGrep(patternArgVec, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, false);
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "grepl", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "value", "perl", "fixed", "useBytes", "invert"}, behavior = PURE)
-    public abstract static class GrepL extends GrepAdapter {
+    public abstract static class GrepL extends RBuiltinNode.Arg8 {
 
         static {
             Casts casts = new Casts(GrepL.class);
@@ -380,21 +402,22 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object grepl(String pattern, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical,
-                        boolean useBytes, boolean invertLogical) {
+        protected Object grepl(String pattern, RAbstractStringVector vector, boolean ignoreCaseLogical, boolean valueLogical, boolean perlLogical, boolean fixedLogical, boolean useBytes,
+                        boolean invertLogical,
+                        @Cached("createGrepCommon()") GrepCommonCodeNode common) {
             // invert is passed but is always FALSE
-            return doGrep(pattern, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, true);
+            return common.doGrep(pattern, vector, ignoreCaseLogical, valueLogical, perlLogical, fixedLogical, useBytes, invertLogical, true);
         }
     }
 
-    protected abstract static class SubAdapter extends CommonCodeAdapter {
-        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+    protected static void castReplacement(Casts casts) {
+        // with default error message, NO_CALLER does not work
+        casts.arg("replacement").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, "replacement").shouldBe(
+                        singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "replacement").findFirst();
+    }
 
-        protected static void castReplacement(Casts casts) {
-            // with default error message, NO_CALLER does not work
-            casts.arg("replacement").mustBe(stringValue(), RError.Message.INVALID_ARGUMENT, "replacement").asVector().mustBe(notEmpty(), RError.Message.INVALID_ARGUMENT, "replacement").shouldBe(
-                            singleElement(), RError.Message.ARGUMENT_ONLY_FIRST, "replacement").findFirst();
-        }
+    protected static final class SubCommonCodeNode extends CommonCodeNode {
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
 
         protected RStringVector doSub(String patternArg, String replacementArg, RAbstractStringVector vector, boolean ignoreCase, boolean perlPar,
                         boolean fixedPar, @SuppressWarnings("unused") boolean useBytes, boolean gsub) {
@@ -662,8 +685,9 @@ public class GrepFunctions {
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "sub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
-    public abstract static class Sub extends SubAdapter {
+    public abstract static class Sub extends RBuiltinNode.Arg7 {
 
         static {
             Casts casts = new Casts(Sub.class);
@@ -678,14 +702,15 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RStringVector subRegexp(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical,
-                        boolean fixedLogical, boolean useBytes) {
-            return doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, false);
+        protected RStringVector subRegexp(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical, boolean fixedLogical, boolean useBytes,
+                        @Cached("createSubCommon()") SubCommonCodeNode common) {
+            return common.doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, false);
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "gsub", kind = INTERNAL, parameterNames = {"pattern", "replacement", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
-    public abstract static class GSub extends SubAdapter {
+    public abstract static class GSub extends RBuiltinNode.Arg7 {
 
         static {
             Casts casts = new Casts(GSub.class);
@@ -700,14 +725,15 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RStringVector gsub(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical,
-                        boolean fixedLogical, boolean useBytes) {
-            return doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, true);
+        protected RStringVector gsub(String patternArgVec, String replacementVec, RAbstractStringVector x, boolean ignoreCaseLogical, boolean perlLogical, boolean fixedLogical, boolean useBytes,
+                        @Cached("createSubCommon()") SubCommonCodeNode common) {
+            return common.doSub(patternArgVec, replacementVec, x, ignoreCaseLogical, perlLogical, fixedLogical, useBytes, true);
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "regexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
-    public abstract static class Regexp extends CommonCodeAdapter {
+    public abstract static class Regexp extends RBuiltinNode.Arg6 {
 
         @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length");
         @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes");
@@ -756,8 +782,9 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL) {
-            checkExtraArgs(false, false, false, useBytesL, false);
+        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL,
+                        @Cached("createCommon()") CommonCodeNode common) {
+            common.checkExtraArgs(false, false, false, useBytesL, false);
             boolean ignoreCase = ignoreCaseL;
             boolean fixed = fixedL;
             boolean perl = perlL;
@@ -782,7 +809,7 @@ public class GrepFunctions {
                 Arrays.fill(result, 1);
             } else {
                 for (int i = 0; i < vector.getLength(); i++) {
-                    Info res = getInfo(pattern, vector.getDataAt(i), ignoreCase, perl, fixed).get(0);
+                    Info res = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed).get(0);
                     result[i] = res.index;
                     matchLength[i] = res.size;
                     if (res.hasCapture) {
@@ -827,7 +854,7 @@ public class GrepFunctions {
             return ret;
         }
 
-        protected List<Info> getInfo(String pattern, String text, boolean ignoreCase, boolean perl, boolean fixed) {
+        protected List<Info> getInfo(CommonCodeNode common, String pattern, String text, boolean ignoreCase, boolean perl, boolean fixed) {
             List<Info> list = new ArrayList<>();
             if (fixed) {
                 int index = 0;
@@ -844,7 +871,7 @@ public class GrepFunctions {
                     index += pattern.length();
                 }
             } else if (perl) {
-                PCRERFFI.Result pcre = compilePerlPattern(pattern, ignoreCase);
+                PCRERFFI.Result pcre = common.compilePerlPattern(pattern, ignoreCase);
                 int maxCaptureCount = getCaptureCountNode.execute(pcre.result, 0);
                 int[] ovector = new int[(maxCaptureCount + 1) * 3];
                 int offset = 0;
@@ -897,6 +924,7 @@ public class GrepFunctions {
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "gregexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
     public abstract static class Gregexpr extends Regexp {
 
@@ -935,8 +963,9 @@ public class GrepFunctions {
         @Specialization
         @TruffleBoundary
         @Override
-        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL) {
-            checkExtraArgs(false, false, false, useBytesL, false);
+        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL,
+                        @Cached("createCommon()") CommonCodeNode common) {
+            common.checkExtraArgs(false, false, false, useBytesL, false);
             boolean ignoreCase = ignoreCaseL;
             boolean fixed = fixedL;
             boolean perl = perlL;
@@ -966,7 +995,7 @@ public class GrepFunctions {
                         setUseBytesAttrNode.execute(res, RRuntime.LOGICAL_TRUE);
                     }
                 } else {
-                    List<Info> l = getInfo(pattern, vector.getDataAt(i), ignoreCase, perl, fixed);
+                    List<Info> l = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed);
                     res = toIndexOrSizeVector(l, true);
                     setMatchLengthAttrNode.execute(res, toIndexOrSizeVector(l, false));
                     if (useBytes) {
@@ -1043,8 +1072,9 @@ public class GrepFunctions {
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "agrep", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE)
-    public abstract static class AGrep extends CommonCodeAdapter {
+    public abstract static class AGrep extends RBuiltinNode.Arg8 {
 
         static {
             Casts casts = new Casts(AGrep.class);
@@ -1061,13 +1091,12 @@ public class GrepFunctions {
         @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
-        protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds,
-                        boolean useBytes,
-                        boolean fixed) {
+        protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds, boolean useBytes, boolean fixed,
+                        @Cached("createCommon()") CommonCodeNode common) {
             // TODO implement completely; this is a very basic implementation for fixed=TRUE only.
-            checkExtraArgs(ignoreCase, false, false, useBytes, false);
-            valueCheck(value);
-            checkNotImplemented(!fixed, "fixed", false);
+            common.checkExtraArgs(ignoreCase, false, false, useBytes, false);
+            common.valueCheck(value);
+            common.checkNotImplemented(!fixed, "fixed", false);
             int[] tmp = new int[vector.getLength()];
             int numMatches = 0;
             long maxDistance = Math.round(pattern.length() * bounds.getDataAt(0));
@@ -1078,7 +1107,7 @@ public class GrepFunctions {
                     numMatches++;
                 }
             }
-            tmp = trimIntResult(tmp, numMatches, tmp.length);
+            tmp = common.trimIntResult(tmp, numMatches, tmp.length);
             if (tmp == null) {
                 return RDataFactory.createEmptyIntVector();
             } else {
@@ -1159,8 +1188,9 @@ public class GrepFunctions {
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "agrepl", kind = INTERNAL, parameterNames = {"pattern", "x", "ignore.case", "value", "costs", "bounds", "useBytes", "fixed"}, behavior = PURE)
-    public abstract static class AGrepL extends CommonCodeAdapter {
+    public abstract static class AGrepL extends RBuiltinNode.Arg8 {
 
         static {
             Casts casts = new Casts(AGrepL.class);
@@ -1177,11 +1207,10 @@ public class GrepFunctions {
         @SuppressWarnings("unused")
         @Specialization
         @TruffleBoundary
-        protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds,
-                        boolean useBytes,
-                        boolean fixed) {
+        protected Object aGrep(String pattern, RAbstractStringVector vector, boolean ignoreCase, boolean value, RAbstractIntVector costs, RAbstractDoubleVector bounds, boolean useBytes, boolean fixed,
+                        @Cached("createCommon()") CommonCodeNode common) {
             // TODO implement properly, this only supports strict equality!
-            checkExtraArgs(ignoreCase, false, false, useBytes, false);
+            common.checkExtraArgs(ignoreCase, false, false, useBytes, false);
             byte[] data = new byte[vector.getLength()];
             for (int i = 0; i < vector.getLength(); i++) {
                 data[i] = RRuntime.asLogical(pattern.equals(vector.getDataAt(i)));
@@ -1190,8 +1219,9 @@ public class GrepFunctions {
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "strsplit", kind = INTERNAL, parameterNames = {"x", "split", "fixed", "perl", "useBytes"}, behavior = PURE)
-    public abstract static class Strsplit extends CommonCodeAdapter {
+    public abstract static class Strsplit extends RBuiltinNode.Arg5 {
         @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
 
         static {
@@ -1207,14 +1237,14 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected RList split(RAbstractStringVector x, RAbstractStringVector splitArg, boolean fixedLogical, boolean perlLogical, @SuppressWarnings("unused") boolean useBytes) {
-            boolean fixed = fixedLogical;
-            boolean perl = checkPerlFixed(perlLogical, fixed);
+        protected RList split(RAbstractStringVector x, RAbstractStringVector splitArg, boolean fixed, boolean perlLogical, @SuppressWarnings("unused") boolean useBytes,
+                        @Cached("createCommon()") CommonCodeNode common) {
+            boolean perl = common.checkPerlFixed(perlLogical, fixed);
             RStringVector[] result = new RStringVector[x.getLength()];
             // treat split = NULL as split = ""
             RAbstractStringVector split = splitArg.getLength() == 0 ? RDataFactory.createStringVectorFromScalar("") : splitArg;
             String[] splits = new String[split.getLength()];
-            long pcreTables = perl ? maketablesNode.execute() : 0;
+            long pcreTables = perl ? common.maketablesNode.execute() : 0;
             PCRERFFI.Result[] pcreSplits = perl ? new PCRERFFI.Result[splits.length] : null;
 
             na.enable(x);
@@ -1223,7 +1253,7 @@ public class GrepFunctions {
                 splits[i] = fixed || perl ? split.getDataAt(i) : RegExp.checkPreDefinedClasses(split.getDataAt(i));
                 if (perl) {
                     if (!currentSplit.isEmpty()) {
-                        pcreSplits[i] = compileNode.execute(currentSplit, 0, pcreTables);
+                        pcreSplits[i] = common.compileNode.execute(currentSplit, 0, pcreTables);
                         if (pcreSplits[i].result == 0) {
                             // TODO output warning if pcre.errorMessage not NULL
                             throw error(RError.Message.INVALID_REGEXP, currentSplit);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index f95d1d95a6..965159a003 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -79,7 +79,7 @@ public class HiddenInternalFunctions {
      * Transcribed from GnuR {@code do_makeLazy} in src/main/builtin.c.
      */
     @RBuiltin(name = "makeLazy", visibility = OFF, kind = INTERNAL, parameterNames = {"names", "values", "expr", "eval.env", "assign.env"}, behavior = COMPLEX)
-    public abstract static class MakeLazy extends RBuiltinNode {
+    public abstract static class MakeLazy extends RBuiltinNode.Arg5 {
         @Child private Eval eval;
 
         private void initEval() {
@@ -142,7 +142,7 @@ public class HiddenInternalFunctions {
      * possibly with different names. Promises are not forced and active bindings are preserved.
      */
     @RBuiltin(name = "importIntoEnv", kind = INTERNAL, parameterNames = {"impenv", "impnames", "expenv", "expnames"}, behavior = COMPLEX)
-    public abstract static class ImportIntoEnv extends RBuiltinNode {
+    public abstract static class ImportIntoEnv extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(ImportIntoEnv.class);
@@ -184,7 +184,7 @@ public class HiddenInternalFunctions {
      * Transcribed from {@code lazyLoaadDBFetch} in src/serialize.c.
      */
     @RBuiltin(name = "lazyLoadDBfetch", kind = PRIMITIVE, parameterNames = {"key", "datafile", "compressed", "envhook"}, behavior = PURE)
-    public abstract static class LazyLoadDBFetch extends RBuiltinNode {
+    public abstract static class LazyLoadDBFetch extends RBuiltinNode.Arg4 {
 
         @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2);
 
@@ -274,7 +274,7 @@ public class HiddenInternalFunctions {
     }
 
     @RBuiltin(name = "getRegisteredRoutines", kind = INTERNAL, parameterNames = "info", behavior = COMPLEX)
-    public abstract static class GetRegisteredRoutines extends RBuiltinNode {
+    public abstract static class GetRegisteredRoutines extends RBuiltinNode.Arg1 {
         private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{".C", ".Call", ".Fortran", ".External"}, RDataFactory.COMPLETE_VECTOR);
         private static final RStringVector NATIVE_ROUTINE_LIST = RDataFactory.createStringVectorFromScalar("NativeRoutineList");
 
@@ -324,7 +324,7 @@ public class HiddenInternalFunctions {
     }
 
     @RBuiltin(name = "getVarsFromFrame", kind = INTERNAL, parameterNames = {"vars", "e", "force"}, behavior = COMPLEX)
-    public abstract static class GetVarsFromFrame extends RBuiltinNode {
+    public abstract static class GetVarsFromFrame extends RBuiltinNode.Arg3 {
         @Child private PromiseHelperNode promiseHelper;
 
         static {
@@ -361,7 +361,7 @@ public class HiddenInternalFunctions {
     }
 
     @RBuiltin(name = "lazyLoadDBinsertValue", kind = INTERNAL, parameterNames = {"value", "file", "ascii", "compsxp", "hook"}, behavior = COMPLEX)
-    public abstract static class LazyLoadDBinsertValue extends RBuiltinNode {
+    public abstract static class LazyLoadDBinsertValue extends RBuiltinNode.Arg5 {
 
         @Child private CallRFunctionCachedNode callCache = CallRFunctionCachedNodeGen.create(2);
 
@@ -465,7 +465,7 @@ public class HiddenInternalFunctions {
     }
 
     @RBuiltin(name = "lazyLoadDBflush", kind = INTERNAL, parameterNames = "path", behavior = COMPLEX)
-    public abstract static class LazyLoadDBFlush extends RBuiltinNode {
+    public abstract static class LazyLoadDBFlush extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(LazyLoadDBFlush.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
index c03a1d9ba8..4b75dccff9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "iconv", kind = INTERNAL, parameterNames = {"x", "from", "to", "sub", "mark", "toRaw"}, behavior = PURE)
-public abstract class IConv extends RBuiltinNode {
+public abstract class IConv extends RBuiltinNode.Arg6 {
 
     static {
         Casts casts = new Casts(IConv.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
index bf863d14ac..9200d000ff 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
@@ -65,7 +65,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * checked for NA (regardless of whether they are used).
  */
 @RBuiltin(name = "identical", kind = INTERNAL, parameterNames = {"x", "y", "num.eq", "single.NA", "attrib.as.set", "ignore.bytecode", "ignore.environment"}, behavior = PURE)
-public abstract class Identical extends RBuiltinNode {
+public abstract class Identical extends RBuiltinNode.Arg7 {
 
     protected abstract byte executeByte(Object x, Object y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java
index b45abeda28..bcd8c7f39f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java
@@ -27,7 +27,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "inherits", kind = INTERNAL, parameterNames = {"x", "what", "which"}, behavior = PURE)
-public abstract class InheritsBuiltin extends RBuiltinNode {
+public abstract class InheritsBuiltin extends RBuiltinNode.Arg3 {
 
     @Child InheritsNode inheritsNode = InheritsNodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
index 1984f96e01..c595f2f997 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToBits.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 
 @RBuiltin(name = "intToBits", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class IntToBits extends RBuiltinNode {
+public abstract class IntToBits extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(IntToBits.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
index 2c391f761f..531147ade9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IntToUtf8.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "intToUtf8", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE)
-public abstract class IntToUtf8 extends RBuiltinNode {
+public abstract class IntToUtf8 extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(IntToUtf8.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
index 55bf8f6b8c..424889c116 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 @RBuiltin(name = "interactive", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE)
-public abstract class Interactive extends RBuiltinNode {
+public abstract class Interactive extends RBuiltinNode.Arg0 {
     @Specialization
     protected byte interactive() {
         return RRuntime.asLogical(RContext.getInstance().isInteractive());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java
index 5b684d04ab..e355db1727 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
  * visible.
  */
 @RBuiltin(name = ".Internal", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"call"}, nonEvalArgs = 0, behavior = COMPLEX)
-public abstract class Internal extends RBuiltinNode {
+public abstract class Internal extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(Internal.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java
index 55ec16e7d4..de675420cf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Invisible.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "invisible", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
-public abstract class Invisible extends RBuiltinNode {
+public abstract class Invisible extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(Invisible.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java
index 4666c8694d..8599ff3cdf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsATTY.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "isatty", kind = INTERNAL, parameterNames = {"con"}, behavior = PURE)
-public abstract class IsATTY extends RBuiltinNode {
+public abstract class IsATTY extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(IsATTY.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
index 98b5684683..075d0dbb03 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
@@ -53,7 +53,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public class IsFiniteFunctions {
 
-    public abstract static class Adapter extends RBuiltinNode {
+    public abstract static class Adapter extends RBuiltinNode.Arg1 {
 
         @Child private GetDimAttributeNode getDims = GetDimAttributeNode.create();
         @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java
index 48cc21c956..dd4dab9a05 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 // from apply.c
 
 @RBuiltin(name = "islistfactor", kind = INTERNAL, parameterNames = {"x", "recursive"}, behavior = PURE)
-public abstract class IsListFactor extends RBuiltinNode {
+public abstract class IsListFactor extends RBuiltinNode.Arg2 {
 
     protected abstract static class IsListFactorInternal extends Node {
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java
index 22f316102e..6785523853 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 @RBuiltin(name = ".isMethodsDispatchOn", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE)
-public abstract class IsMethodsDispatchOn extends RBuiltinNode {
+public abstract class IsMethodsDispatchOn extends RBuiltinNode.Arg0 {
 
     public abstract byte execute();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
index b2a9cb0863..c08de1b1f1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
@@ -54,7 +54,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "is.na", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class IsNA extends RBuiltinNode {
+public abstract class IsNA extends RBuiltinNode.Arg1 {
 
     @Child private IsNA recursiveIsNA;
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java
index d4939ab3a5..231e1e43fe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsS4.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 
 @RBuiltin(name = "isS4", kind = PRIMITIVE, parameterNames = {"object"}, behavior = PURE)
-public abstract class IsS4 extends RBuiltinNode {
+public abstract class IsS4 extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(IsS4.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
index cffe0507af..9152317546 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "is.single", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class IsSingle extends RBuiltinNode {
+public abstract class IsSingle extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(IsSingle.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
index 2c7aa8fd52..74152f23bf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
@@ -68,7 +68,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
  */
 public class IsTypeFunctions {
 
-    protected abstract static class MissingAdapter extends RBuiltinNode {
+    protected abstract static class MissingAdapter extends RBuiltinNode.Arg1 {
 
         protected static Casts createCasts(Class<? extends MissingAdapter> extCls) {
             Casts casts = new Casts(extCls);
@@ -553,7 +553,7 @@ public class IsTypeFunctions {
     }
 
     @RBuiltin(name = "is.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, behavior = PURE)
-    public abstract static class IsVector extends RBuiltinNode {
+    public abstract static class IsVector extends RBuiltinNode.Arg2 {
 
         private final ConditionProfile attrNull = ConditionProfile.createBinaryProfile();
         private final ConditionProfile attrEmpty = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
index e9daf68f71..4c098438be 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsUnsorted.java
@@ -44,10 +44,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.BinaryCompare;
 
-@RBuiltin(name = "is.unsorted", kind = INTERNAL, parameterNames = {"x", "strictly"}, behavior = PURE)
 // TODO support strictly
 // TODO support lists
-public abstract class IsUnsorted extends RBuiltinNode {
+@RBuiltin(name = "is.unsorted", kind = INTERNAL, parameterNames = {"x", "strictly"}, behavior = PURE)
+public abstract class IsUnsorted extends RBuiltinNode.Arg2 {
 
     @Child private BinaryMapBooleanFunctionNode ge = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_EQUAL.createOperation());
     @Child private BinaryMapBooleanFunctionNode gt = new BinaryMapBooleanFunctionNode(BinaryCompare.GREATER_THAN.createOperation());
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 5be9dfbdad..76f62d8d8d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -13,9 +13,11 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimGt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.or;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix;
@@ -37,7 +39,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
@@ -68,7 +70,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 public class LaFunctions {
 
     @RBuiltin(name = "La_version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class Version extends RBuiltinNode {
+    public abstract static class Version extends RBuiltinNode.Arg0 {
         @Child LapackRFFI.IlaverNode ilaverNode = RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode();
 
         @Specialization
@@ -80,19 +82,17 @@ public class LaFunctions {
         }
     }
 
-    private abstract static class RsgRBuiltinNode extends RBuiltinNode {
-        protected static final String[] NAMES = new String[]{"values", "vectors"};
+    protected static final String[] NAMES = new String[]{"values", "vectors"};
 
-        protected static Casts createCasts(Class<? extends RsgRBuiltinNode> extClass) {
-            Casts casts = new Casts(extClass);
-            casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), Message.MUST_BE_SQUARE_NUMERIC, "x");
-            casts.arg("onlyValues").defaultError(Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
-            return casts;
-        }
+    protected static Casts createCasts(Class<? extends RBuiltinNode> extClass) {
+        Casts casts = new Casts(extClass);
+        casts.arg("matrix").asDoubleVector(false, true, false).mustBe(squareMatrix(), Message.MUST_BE_SQUARE_NUMERIC, "x");
+        casts.arg("onlyValues").defaultError(Message.INVALID_ARGUMENT, "only.values").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
+        return casts;
     }
 
     @RBuiltin(name = "La_rg", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE)
-    public abstract static class Rg extends RsgRBuiltinNode {
+    public abstract static class Rg extends RBuiltinNode.Arg2 {
 
         private final ConditionProfile hasComplexValues = ConditionProfile.createBinaryProfile();
 
@@ -192,7 +192,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_rs", kind = INTERNAL, parameterNames = {"matrix", "onlyValues"}, behavior = PURE)
-    public abstract static class Rs extends RsgRBuiltinNode {
+    public abstract static class Rs extends RBuiltinNode.Arg2 {
 
         static {
             createCasts(Rs.class);
@@ -253,7 +253,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_qr", kind = INTERNAL, parameterNames = {"in"}, behavior = PURE)
-    public abstract static class Qr extends RBuiltinNode {
+    public abstract static class Qr extends RBuiltinNode.Arg1 {
 
         @CompilationFinal private static final String[] NAMES = new String[]{"qr", "rank", "qraux", "pivot"};
 
@@ -301,7 +301,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "qr_coef_real", kind = INTERNAL, parameterNames = {"q", "b"}, behavior = PURE)
-    public abstract static class QrCoefReal extends RBuiltinNode {
+    public abstract static class QrCoefReal extends RBuiltinNode.Arg2 {
 
         private static final char SIDE = 'L';
         private static final char TRANS = 'T';
@@ -360,7 +360,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "det_ge_real", kind = INTERNAL, parameterNames = {"a", "uselog"}, behavior = PURE)
-    public abstract static class DetGeReal extends RBuiltinNode {
+    public abstract static class DetGeReal extends RBuiltinNode.Arg2 {
 
         private static final RStringVector NAMES_VECTOR = RDataFactory.createStringVector(new String[]{"modulus", "sign"}, RDataFactory.COMPLETE_VECTOR);
         private static final RStringVector DET_CLASS = RDataFactory.createStringVector(new String[]{"det"}, RDataFactory.COMPLETE_VECTOR);
@@ -442,7 +442,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_chol", kind = INTERNAL, parameterNames = {"a", "pivot", "tol"}, behavior = PURE)
-    public abstract static class LaChol extends RBuiltinNode {
+    public abstract static class LaChol extends RBuiltinNode.Arg3 {
 
         private final ConditionProfile noPivot = ConditionProfile.createBinaryProfile();
 
@@ -510,7 +510,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_chol2inv", kind = INTERNAL, parameterNames = {"a", "size"}, behavior = PURE)
-    public abstract static class LaChol2Inv extends RBuiltinNode {
+    public abstract static class LaChol2Inv extends RBuiltinNode.Arg2 {
 
         @Child private SetFixedAttributeNode setPivotAttrNode = SetFixedAttributeNode.create("pivot");
         @Child private SetFixedAttributeNode setRankAttrNode = SetFixedAttributeNode.create("rank");
@@ -518,7 +518,7 @@ public class LaFunctions {
         static {
             Casts casts = new Casts(LaChol2Inv.class);
             casts.arg("a").asDoubleVector(false, true, false).mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a");
-            casts.arg("size").asIntegerVector().mustBe(Predef.notEmpty()).findFirst().mustBe(Predef.gt(0), Message.MUST_BE_POSITIVE_INT);
+            casts.arg("size").asIntegerVector().mustBe(notEmpty()).findFirst().mustBe(gt(0), Message.MUST_BE_POSITIVE_INT);
         }
 
         @Specialization
@@ -559,7 +559,7 @@ public class LaFunctions {
     }
 
     @RBuiltin(name = "La_solve", kind = INTERNAL, parameterNames = {"a", "bin", "tolin"}, behavior = PURE)
-    public abstract static class LaSolve extends RBuiltinNode {
+    public abstract static class LaSolve extends RBuiltinNode.Arg3 {
         @Child private CastDoubleNode castDouble = CastDoubleNodeGen.create(false, false, false);
 
         private static Function<RAbstractDoubleVector, Object> getDimVal(int dim) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index f9e0d535c6..50fad3a19e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * See the comment in {@link VApply} regarding "...".
  */
 @RBuiltin(name = "lapply", kind = INTERNAL, parameterNames = {"X", "FUN"}, splitCaller = true, behavior = COMPLEX)
-public abstract class Lapply extends RBuiltinNode {
+public abstract class Lapply extends RBuiltinNode.Arg2 {
 
     private static final Source CALL_SOURCE = RSource.fromTextInternal("FUN(X[[i]], ...)", RSource.Internal.LAPPLY);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
index df92d3e9fa..2acf888097 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "length", kind = PRIMITIVE, dispatch = INTERNAL_GENERIC, parameterNames = {"x"}, behavior = PURE)
-public abstract class Length extends RBuiltinNode {
+public abstract class Length extends RBuiltinNode.Arg1 {
 
     public abstract int executeInt(VirtualFrame frame, Object vector);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
index a9eb95fc48..69e7498c34 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
@@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "lengths", kind = INTERNAL, parameterNames = {"x", "use.names"}, behavior = PURE)
-public abstract class Lengths extends RBuiltinNode {
+public abstract class Lengths extends RBuiltinNode.Arg2 {
 
     @Child private RLengthNode lengthNode;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
index 6c6bc4795b..b98566310e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.conn.StdConnections;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "license", visibility = OFF, aliases = {"licence"}, kind = SUBSTITUTE, parameterNames = {}, behavior = IO)
-public abstract class License extends RBuiltinNode {
+public abstract class License extends RBuiltinNode.Arg0 {
 
     @Specialization
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java
index f1ab5acbb7..60a62338d6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "list2env", kind = INTERNAL, parameterNames = {"x", "envir"}, behavior = PURE)
-public abstract class List2Env extends RBuiltinNode {
+public abstract class List2Env extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(List2Env.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java
index e7ffa8d42c..dc16026b21 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ListBuiltin.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 
 @RBuiltin(name = "list", kind = PRIMITIVE, parameterNames = {"..."}, behavior = PURE)
-public abstract class ListBuiltin extends RBuiltinNode {
+public abstract class ListBuiltin extends RBuiltinNode.Arg1 {
 
     protected static final int CACHE_LIMIT = 2;
     protected static final int MAX_SHARE_OBJECT_NODES = 16;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
index 01788ee13c..9d7e4eec31 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java
@@ -30,7 +30,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.base.SerializeFunctions.Adapter;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -52,7 +51,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 public class LoadSaveFunctions {
 
     @RBuiltin(name = "loadFromConn2", visibility = OFF, kind = INTERNAL, parameterNames = {"con", "envir", "verbose"}, behavior = IO)
-    public abstract static class LoadFromConn2 extends RBuiltinNode {
+    public abstract static class LoadFromConn2 extends RBuiltinNode.Arg3 {
 
         private final NACheck naCheck = NACheck.create();
 
@@ -110,7 +109,7 @@ public class LoadSaveFunctions {
     }
 
     @RBuiltin(name = "load", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "envir"}, behavior = IO)
-    public abstract static class Load extends RBuiltinNode {
+    public abstract static class Load extends RBuiltinNode.Arg2 {
         // now deprecated but still used by some packages
 
         static {
@@ -186,7 +185,7 @@ public class LoadSaveFunctions {
     }
 
     @RBuiltin(name = "saveToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "con", "ascii", "version", "environment", "eval.promises"}, behavior = IO)
-    public abstract static class SaveToConn extends Adapter {
+    public abstract static class SaveToConn extends RBuiltinNode.Arg6 {
         private static final String ASCII_HEADER = "RDA2\n";
         private static final String XDR_HEADER = "RDX2\n";
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
index 4f043390f4..aae947e9a6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
@@ -52,7 +52,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public class LocaleFunctions {
 
     @RBuiltin(name = "Sys.getlocale", kind = INTERNAL, parameterNames = {"category"}, behavior = READS_STATE)
-    public abstract static class GetLocale extends RBuiltinNode {
+    public abstract static class GetLocale extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(GetLocale.class);
@@ -90,7 +90,7 @@ public class LocaleFunctions {
     }
 
     @RBuiltin(name = "Sys.setlocale", kind = INTERNAL, parameterNames = {"category", "locale"}, behavior = MODIFIES_STATE)
-    public abstract static class SetLocale extends RBuiltinNode {
+    public abstract static class SetLocale extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(SetLocale.class);
@@ -107,7 +107,7 @@ public class LocaleFunctions {
     }
 
     @RBuiltin(name = "Sys.localeconv", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class LocaleConv extends RBuiltinNode {
+    public abstract static class LocaleConv extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected Object localeconv() {
@@ -117,7 +117,7 @@ public class LocaleFunctions {
     }
 
     @RBuiltin(name = "l10n_info", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class L10nInfo extends RBuiltinNode {
+    public abstract static class L10nInfo extends RBuiltinNode.Arg0 {
         private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"MBCS", "UTF-8", "Latin-1"}, RDataFactory.COMPLETE_VECTOR);
 
         @Specialization
@@ -132,7 +132,7 @@ public class LocaleFunctions {
     }
 
     @RBuiltin(name = "enc2native", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE)
-    public abstract static class Enc2Native extends RBuiltinNode {
+    public abstract static class Enc2Native extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Enc2Native.class);
@@ -147,7 +147,7 @@ public class LocaleFunctions {
     }
 
     @RBuiltin(name = "enc2utf8", kind = PRIMITIVE, parameterNames = "x", behavior = READS_STATE)
-    public abstract static class Enc2Utf8 extends RBuiltinNode {
+    public abstract static class Enc2Utf8 extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Enc2Utf8.class);
@@ -162,7 +162,7 @@ public class LocaleFunctions {
     }
 
     @RBuiltin(name = "bindtextdomain", kind = PRIMITIVE, parameterNames = {"domain", "dirname"}, behavior = READS_STATE)
-    public abstract static class BindTextDomain extends RBuiltinNode {
+    public abstract static class BindTextDomain extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(BindTextDomain.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 3bce1da46d..628a844754 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -60,7 +60,7 @@ import java.util.function.Function;
 
 public class LogFunctions {
     @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Log extends RBuiltinNode {
+    public abstract static class Log extends RBuiltinNode.Arg2 {
 
         private final NAProfile naX = NAProfile.create();
         private final BranchProfile nanProfile = BranchProfile.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
index f2323827fc..275ed1e26c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ls.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "ls", aliases = {"objects"}, kind = INTERNAL, parameterNames = {"envir", "all.names", "sorted"}, behavior = PURE)
-public abstract class Ls extends RBuiltinNode {
+public abstract class Ls extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(Ls.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
index 1272133457..0a382c92aa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeNames.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "make.names", kind = INTERNAL, parameterNames = {"names", "allow_"}, behavior = PURE)
-public abstract class MakeNames extends RBuiltinNode {
+public abstract class MakeNames extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile namesLengthZero = ConditionProfile.createBinaryProfile();
     private final NACheck dummyCheck = NACheck.create(); // never triggered (used for vector update)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
index 6fd3a0feca..eddadcd858 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MakeUnique.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "make.unique", kind = INTERNAL, parameterNames = {"names", "sep"}, behavior = PURE)
-public abstract class MakeUnique extends RBuiltinNode {
+public abstract class MakeUnique extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile namesProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile duplicatesProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
index 4a40c0ac4d..e649410a89 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
@@ -62,7 +62,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * the longest vector, with the usual recycling rule.
  */
 @RBuiltin(name = "mapply", kind = INTERNAL, parameterNames = {"FUN", "dots", "MoreArgs"}, splitCaller = true, behavior = COMPLEX)
-public abstract class Mapply extends RBuiltinNode {
+public abstract class Mapply extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(Mapply.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index d6baac0ef1..1321af4d0c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -62,7 +62,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "%*%", kind = PRIMITIVE, parameterNames = {"", ""}, behavior = PURE)
-public abstract class MatMult extends RBuiltinNode {
+public abstract class MatMult extends RBuiltinNode.Arg2 {
 
     private static final int BLOCK_SIZE = 64;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index 9c984f8551..e15199525e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -68,7 +68,7 @@ import com.oracle.truffle.r.runtime.ops.na.NAProfile;
  * TODO: handle "incomparables" parameter.
  */
 @RBuiltin(name = "match", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "incomparables"}, behavior = PURE)
-public abstract class Match extends RBuiltinNode {
+public abstract class Match extends RBuiltinNode.Arg4 {
 
     protected abstract Object executeRIntVector(Object x, Object table, Object noMatch, Object incomparables);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
index b9d9c1f7c5..f672ab2914 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
@@ -63,7 +63,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "match.arg", kind = SUBSTITUTE, parameterNames = {"arg", "choices", "several.ok"}, nonEvalArgs = {0}, behavior = COMPLEX)
-public abstract class MatchArg extends RBuiltinNode {
+public abstract class MatchArg extends RBuiltinNode.Arg3 {
 
     static {
         Casts.noCasts(MatchArg.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
index 552a480a2c..e28e0f1136 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
@@ -57,7 +57,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "match.fun", kind = SUBSTITUTE, parameterNames = {"fun", "descend"}, nonEvalArgs = 0, behavior = COMPLEX)
-public abstract class MatchFun extends RBuiltinNode {
+public abstract class MatchFun extends RBuiltinNode.Arg2 {
 
     @Override
     public Object[] getDefaultParameterValues() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
index feb1059c09..161972a202 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "matrix", kind = INTERNAL, parameterNames = {"data", "nrow", "ncol", "byrow", "dimnames", "missingNr", "missingNc"}, behavior = PURE)
-public abstract class Matrix extends RBuiltinNode {
+public abstract class Matrix extends RBuiltinNode.Arg7 {
 
     @Child private Transpose transpose;
     @Child private UpdateDimNames updateDimNames;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
index 2e898cf529..6c3556db61 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
 @RBuiltin(name = "max", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
-public abstract class Max extends RBuiltinNode {
+public abstract class Max extends RBuiltinNode.Arg2 {
 
     private static final ReduceSemantics semantics = new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX,
                     RError.Message.NO_NONMISSING_MAX_NA, false, true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
index dc04a0b928..3cd1cf689c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
 @RBuiltin(name = "mean", kind = INTERNAL, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class Mean extends RBuiltinNode {
+public abstract class Mean extends RBuiltinNode.Arg1 {
 
     private final BranchProfile emptyProfile = BranchProfile.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
index 530074e875..c2ededbc78 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
  * Note: invoked from merge.data.frame.
  */
 @RBuiltin(name = "merge", kind = INTERNAL, parameterNames = {"xinds", "yinds", "all.x", "all.y"}, behavior = PURE)
-public abstract class Merge extends RBuiltinNode {
+public abstract class Merge extends RBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(Merge.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
index 09b73c273d..1f14fbafc4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
 @RBuiltin(name = "min", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
-public abstract class Min extends RBuiltinNode {
+public abstract class Min extends RBuiltinNode.Arg2 {
 
     private static final ReduceSemantics semantics = new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN,
                     RError.Message.NO_NONMISSING_MIN_NA, false, true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
index 64f1c93b58..355b1f84a3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Missing.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
  * correctly, because the varargs are already handled by the argument matching.
  */
 @RBuiltin(name = "missing", kind = PRIMITIVE, nonEvalArgs = 0, parameterNames = {"x"}, behavior = COMPLEX)
-public abstract class Missing extends RBuiltinNode {
+public abstract class Missing extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Missing.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java
index 6a166f0a12..4298b5e9ca 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 
 // TODO Figure out how to distinguish f(,,a) from f(a) - RMissing is used in both contexts
 @RBuiltin(name = "nargs", kind = PRIMITIVE, parameterNames = {}, behavior = RBehavior.READS_FRAME)
-public abstract class NArgs extends RBuiltinNode {
+public abstract class NArgs extends RBuiltinNode.Arg0 {
 
     private final BranchProfile isPromiseProfile = BranchProfile.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
index 7f3e1055f3..8c6b7d81d1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java
@@ -51,7 +51,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 // TODO interpret "type" and "allowNA" arguments
 @RBuiltin(name = "nchar", kind = INTERNAL, parameterNames = {"x", "type", "allowNA", "keepNA"}, behavior = PURE)
-public abstract class NChar extends RBuiltinNode {
+public abstract class NChar extends RBuiltinNode.Arg4 {
     private static final String[] TYPES = new String[]{"bytes", "chars", "width"};
     private static final int TYPE_BYTES = 0;
     private static final int TYPE_CHARS = 1;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java
index d72cda8937..b3959ceda7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NGetText.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "ngettext", kind = INTERNAL, parameterNames = {"n", "msg1", "msg2", "domain"}, behavior = COMPLEX)
-public abstract class NGetText extends RBuiltinNode {
+public abstract class NGetText extends RBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(NGetText.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index b8ec8ffd1b..741fd707d6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "nzchar", kind = PRIMITIVE, parameterNames = {"x", "keepNA"}, behavior = PURE)
-public abstract class NZChar extends RBuiltinNode {
+public abstract class NZChar extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(NZChar.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index cbce750d09..1bdd1932b9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 @RBuiltin(name = "names", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class Names extends RBuiltinNode {
+public abstract class Names extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile hasNames = ConditionProfile.createBinaryProfile();
     @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
index b91bffd815..6c3e1267f3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NamespaceFunctions.java
@@ -50,7 +50,7 @@ public class NamespaceFunctions {
     }
 
     @RBuiltin(name = "getRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE)
-    public abstract static class GetRegisteredNamespace extends RBuiltinNode {
+    public abstract static class GetRegisteredNamespace extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(GetRegisteredNamespace.class);
@@ -79,7 +79,7 @@ public class NamespaceFunctions {
     }
 
     @RBuiltin(name = "isRegisteredNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = READS_STATE)
-    public abstract static class IsRegisteredNamespace extends RBuiltinNode {
+    public abstract static class IsRegisteredNamespace extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(IsRegisteredNamespace.class);
@@ -108,7 +108,7 @@ public class NamespaceFunctions {
     }
 
     @RBuiltin(name = "isNamespaceEnv", kind = INTERNAL, parameterNames = {"env"}, behavior = PURE)
-    public abstract static class IsNamespaceEnv extends RBuiltinNode {
+    public abstract static class IsNamespaceEnv extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(IsNamespaceEnv.class);
@@ -126,7 +126,7 @@ public class NamespaceFunctions {
     }
 
     @RBuiltin(name = "getNamespaceRegistry", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class GetNamespaceRegistry extends RBuiltinNode {
+    public abstract static class GetNamespaceRegistry extends RBuiltinNode.Arg0 {
         @Specialization
         protected REnvironment doGetNamespaceRegistry() {
             return REnvironment.getNamespaceRegistry();
@@ -134,7 +134,7 @@ public class NamespaceFunctions {
     }
 
     @RBuiltin(name = "registerNamespace", kind = INTERNAL, parameterNames = {"name", "env"}, behavior = MODIFIES_STATE)
-    public abstract static class RegisterNamespace extends RBuiltinNode {
+    public abstract static class RegisterNamespace extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(RegisterNamespace.class);
@@ -161,7 +161,7 @@ public class NamespaceFunctions {
     }
 
     @RBuiltin(name = "unregisterNamespace", kind = INTERNAL, parameterNames = {"name"}, behavior = MODIFIES_STATE)
-    public abstract static class UnregisterNamespace extends RBuiltinNode {
+    public abstract static class UnregisterNamespace extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(UnregisterNamespace.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
index 501f00d7cc..a046161d57 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NormalizePath.java
@@ -48,7 +48,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "normalizePath", kind = INTERNAL, parameterNames = {"path", "winslash", "mustwork"}, behavior = IO)
-public abstract class NormalizePath extends RBuiltinNode {
+public abstract class NormalizePath extends RBuiltinNode.Arg3 {
 
     private final ConditionProfile doesNotNeedToWork = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
index 26a9bc602f..c540de9687 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
@@ -46,7 +46,7 @@ public class NumericalFunctions {
      * specialization, which would trigger the code generation performed by the annotation
      * processor.
      */
-    public abstract static class DummyNode extends RBuiltinNode {
+    public abstract static class DummyNode extends RBuiltinNode.Arg1 {
 
         @Specialization
         protected Object dummySpec(@SuppressWarnings("unused") Object value) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index 993863cf59..be986b41a2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -54,7 +54,7 @@ import com.oracle.truffle.r.runtime.ops.na.NAProfile;
  * evaluating function using a new slot in {@link RArguments} and run it on function exit.
  */
 @RBuiltin(name = "on.exit", visibility = OFF, kind = PRIMITIVE, parameterNames = {"expr", "add"}, nonEvalArgs = 0, behavior = COMPLEX)
-public abstract class OnExit extends RBuiltinNode {
+public abstract class OnExit extends RBuiltinNode.Arg2 {
 
     @Child private FrameSlotNode onExitSlot = FrameSlotNode.create(RFrameSlot.OnExit, true);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
index 11140af453..f79c0a4863 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
@@ -57,7 +57,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public class OptionsFunctions {
 
     @RBuiltin(name = "options", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"..."}, behavior = MODIFIES_STATE)
-    public abstract static class Options extends RBuiltinNode {
+    public abstract static class Options extends RBuiltinNode.Arg1 {
 
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
@@ -190,7 +190,7 @@ public class OptionsFunctions {
     }
 
     @RBuiltin(name = "getOption", kind = INTERNAL, parameterNames = "x", behavior = READS_STATE)
-    public abstract static class GetOption extends RBuiltinNode {
+    public abstract static class GetOption extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(GetOption.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
index b9e0292d51..56edbde21b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMatch.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "pmatch", kind = INTERNAL, parameterNames = {"x", "table", "nomatch", "duplicates.ok"}, behavior = PURE)
-public abstract class PMatch extends RBuiltinNode {
+public abstract class PMatch extends RBuiltinNode.Arg4 {
 
     private final ConditionProfile nomatchNA = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index 28fec92997..4b9aed674a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -66,7 +66,7 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-public abstract class PMinMax extends RBuiltinNode {
+public abstract class PMinMax extends RBuiltinNode.Arg2 {
 
     @Child private MultiElemStringHandler stringHandler;
     @Child private CastToVectorNode castVector;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index f4f37e8495..b351ea5aef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -91,7 +91,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * On the R side, GnuR adds similar R attributes to the result, which is important for R tooling.
  */
 @RBuiltin(name = "parse", kind = INTERNAL, parameterNames = {"conn", "n", "text", "prompt", "srcfile", "encoding"}, behavior = IO)
-public abstract class Parse extends RBuiltinNode {
+public abstract class Parse extends RBuiltinNode.Arg6 {
     @Child private CastIntegerNode castIntNode;
     @Child private CastStringNode castStringNode;
     @Child private CastToVectorNode castVectorNode;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index 36bbd68139..dfe6386183 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -52,7 +52,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "paste", kind = INTERNAL, parameterNames = {"", "sep", "collapse"}, behavior = PURE)
-public abstract class Paste extends RBuiltinNode {
+public abstract class Paste extends RBuiltinNode.Arg3 {
 
     private static final String[] ONE_EMPTY_STRING = new String[]{""};
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java
index c00334447c..6b18011d04 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste0.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RList;
  * efficient.
  */
 @RBuiltin(name = "paste0", kind = INTERNAL, parameterNames = {"list", "collapse"}, behavior = PURE)
-public abstract class Paste0 extends RBuiltinNode {
+public abstract class Paste0 extends RBuiltinNode.Arg2 {
 
     @Child private Paste pasteNode = PasteNodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java
index fe07eed30f..280c627acb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PathExpand.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "path.expand", kind = INTERNAL, parameterNames = "path", behavior = IO)
-public abstract class PathExpand extends RBuiltinNode {
+public abstract class PathExpand extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(PathExpand.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
index 01bdd569f5..f44ff63f51 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
 @RBuiltin(name = "pretty", kind = INTERNAL, parameterNames = {"l", "u", "n", "min.n", "shrink.sml", "hi", "eps.correct"}, behavior = PURE)
-public abstract class Pretty extends RBuiltinNode {
+public abstract class Pretty extends RBuiltinNode.Arg7 {
 
     private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"l", "u", "n"}, RDataFactory.COMPLETE_VECTOR);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
index 3845cc9588..3dcea15589 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
 
 @RBuiltin(name = ".Primitive", kind = PRIMITIVE, parameterNames = "name", behavior = PURE)
-public abstract class Primitive extends RBuiltinNode {
+public abstract class Primitive extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Primitive.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
index 6f4906fe55..873b10c3c1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java
@@ -52,7 +52,7 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
 public class PrintFunctions {
 
     @RBuiltin(name = "print.default", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "digits", "quote", "na.print", "print.gap", "right", "max", "useSource", "noOpt"}, behavior = IO)
-    public abstract static class PrintDefault extends RBuiltinNode {
+    public abstract static class PrintDefault extends RBuiltinNode.Arg9 {
 
         @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create();
 
@@ -106,7 +106,7 @@ public class PrintFunctions {
     }
 
     @RBuiltin(name = "print.function", visibility = OFF, kind = INTERNAL, parameterNames = {"x", "useSource", "..."}, behavior = IO)
-    public abstract static class PrintFunction extends RBuiltinNode {
+    public abstract static class PrintFunction extends RBuiltinNode.Arg3 {
 
         @Child private ValuePrinterNode valuePrinter = new ValuePrinterNode();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java
index 24496e3ae2..2afa720a9e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 
 @RBuiltin(name = "proc.time", kind = PRIMITIVE, parameterNames = {}, behavior = IO)
-public abstract class ProcTime extends RBuiltinNode {
+public abstract class ProcTime extends RBuiltinNode.Arg0 {
 
     private static final String[] NAMES = new String[]{"user.self", "sys.self", "elapsed", "user.child", "sys.child"};
     private static final RStringVector PROC_TIME_CLASS = RDataFactory.createStringVectorFromScalar("proc_time");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
index 34cd247dd9..e9c8a1a306 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
 @RBuiltin(name = "prod", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
-public abstract class Prod extends RBuiltinNode {
+public abstract class Prod extends RBuiltinNode.Arg2 {
 
     // TODO: handle multiple arguments, handle na.rm
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index c696b7bd65..8a2811b1f8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-public abstract class Quantifier extends RBuiltinNode {
+public abstract class Quantifier extends RBuiltinNode.Arg2 {
     protected static final int MAX_CACHED_LENGTH = 10;
 
     private final NACheck naCheck = NACheck.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index d3e1003add..9d9aa1803a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "quit", visibility = OFF, kind = INTERNAL, parameterNames = {"save", "status", "runLast"}, behavior = COMPLEX)
-public abstract class Quit extends RBuiltinNode {
+public abstract class Quit extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(Quit.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
index a43472d12f..9daaa44d05 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quote.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 
 @RBuiltin(name = "quote", nonEvalArgs = 0, kind = PRIMITIVE, parameterNames = {"expr"}, behavior = PURE)
-public abstract class Quote extends RBuiltinNode {
+public abstract class Quote extends RBuiltinNode.Arg1 {
 
     protected static final int LIMIT = 3;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
index 8abbd12d7a..146b768b00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RNGFunctions.java
@@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
 
 public class RNGFunctions {
     @RBuiltin(name = "set.seed", visibility = OFF, kind = INTERNAL, parameterNames = {"seed", "kind", "normal.kind"}, behavior = MODIFIES_STATE)
-    public abstract static class SetSeed extends RBuiltinNode {
+    public abstract static class SetSeed extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(SetSeed.class);
@@ -76,7 +76,7 @@ public class RNGFunctions {
     }
 
     @RBuiltin(name = "RNGkind", kind = INTERNAL, parameterNames = {"kind", "normkind"}, behavior = MODIFIES_STATE)
-    public abstract static class RNGkind extends RBuiltinNode {
+    public abstract static class RNGkind extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(RNGkind.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java
index 53e566ab53..14acdea47a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 
 @RBuiltin(name = "Version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-public abstract class RVersion extends RBuiltinNode {
+public abstract class RVersion extends RBuiltinNode.Arg0 {
 
     @Specialization
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
index 72ab6ad5c7..f80721c116 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
 @RBuiltin(name = "range", kind = PRIMITIVE, parameterNames = {"...", "na.rm", "finite"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
-public abstract class Range extends RBuiltinNode {
+public abstract class Range extends RBuiltinNode.Arg3 {
 
     private static final ReduceSemantics minSemantics = new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN,
                     RError.Message.NO_NONMISSING_MIN_NA, false, true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
index 19ba218041..c15016ffb9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "rank", kind = INTERNAL, parameterNames = {"x", "len", "ties.method"}, behavior = PURE)
-public abstract class Rank extends RBuiltinNode {
+public abstract class Rank extends RBuiltinNode.Arg3 {
 
     @Child private Order.OrderVector1Node orderVector1Node;
     @Child private Order.CmpNode orderCmpNode;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
index 74712ceaeb..f1fc024fe9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawFunctions.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public class RawFunctions {
 
     @RBuiltin(name = "charToRaw", kind = INTERNAL, parameterNames = "x", behavior = PURE)
-    public abstract static class CharToRaw extends RBuiltinNode {
+    public abstract static class CharToRaw extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(CharToRaw.class);
@@ -72,7 +72,7 @@ public class RawFunctions {
     }
 
     @RBuiltin(name = "rawToChar", kind = INTERNAL, parameterNames = {"x", "multiple"}, behavior = PURE)
-    public abstract static class RawToChar extends RBuiltinNode {
+    public abstract static class RawToChar extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(RawToChar.class);
@@ -106,7 +106,7 @@ public class RawFunctions {
     }
 
     @RBuiltin(name = "rawShift", kind = INTERNAL, parameterNames = {"x", "n"}, behavior = PURE)
-    public abstract static class RawShift extends RBuiltinNode {
+    public abstract static class RawShift extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(RawShift.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
index 389eb9cbc4..3afe3566f5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RawToBits.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 
 @RBuiltin(name = "rawToBits", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class RawToBits extends RBuiltinNode {
+public abstract class RawToBits extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(RawToBits.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
index c009097405..7b259a0324 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadDCF.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "readDCF", kind = INTERNAL, parameterNames = {"conn", "fields", "keepwhite"}, behavior = IO)
-public abstract class ReadDCF extends RBuiltinNode {
+public abstract class ReadDCF extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(ReadDCF.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
index 0614534417..c39fa3a1b6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ReadREnviron.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 @RBuiltin(name = "readRenviron", visibility = OFF, kind = INTERNAL, parameterNames = "x", behavior = COMPLEX)
-public abstract class ReadREnviron extends RBuiltinNode {
+public abstract class ReadREnviron extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(ReadREnviron.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
index bc5411859c..f5d72cb3b6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "readline", kind = INTERNAL, parameterNames = "prompt", behavior = IO)
-public abstract class Readline extends RBuiltinNode {
+public abstract class Readline extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Readline.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
index 6d88f338e4..5d82e00576 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
  * The {@code Recall} {@code .Internal}.
  */
 @RBuiltin(name = "Recall", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"..."}, nonEvalArgs = {0}, behavior = COMPLEX)
-public abstract class Recall extends RBuiltinNode {
+public abstract class Recall extends RBuiltinNode.Arg1 {
 
     @Child private LocalReadVariableNode readArgs = LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java
index 5182327ab4..90b72ab45c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  * the recording like GnuR does.
  */
 @RBuiltin(name = "recordGraphics", kind = INTERNAL, parameterNames = {"expr", "list", "env"}, behavior = COMPLEX)
-public abstract class RecordGraphics extends RBuiltinNode {
+public abstract class RecordGraphics extends RBuiltinNode.Arg3 {
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
     @Child private RList2EnvNode list2EnvNode = new RList2EnvNode();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
index 88bd9e9c80..bade5694f1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RegFinalizer.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "reg.finalizer", kind = INTERNAL, parameterNames = {"e", "f", "onexit"}, behavior = COMPLEX)
-public abstract class RegFinalizer extends RBuiltinNode {
+public abstract class RegFinalizer extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(RegFinalizer.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index 2da580ca12..cd00bcf957 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -87,7 +87,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * </ol>
  */
 @RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class Repeat extends RBuiltinNode {
+public abstract class Repeat extends RBuiltinNode.Arg2 {
 
     private static final PipelineBuilder PB_TIMES;
     private static final PipelineBuilder PB_LENGTH_OUT;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
index a9a9c80e8a..3c27d15d99 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatInternal.java
@@ -53,7 +53,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "rep.int", kind = INTERNAL, parameterNames = {"x", "times"}, behavior = PURE)
-public abstract class RepeatInternal extends RBuiltinNode {
+public abstract class RepeatInternal extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile timesOneProfile = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
index da12e4f3b1..91f3883d1e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "rep_len", kind = INTERNAL, parameterNames = {"x", "length.out"}, behavior = PURE)
-public abstract class RepeatLength extends RBuiltinNode {
+public abstract class RepeatLength extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(RepeatLength.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java
index e990562976..643ac7f8f9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Return.java
@@ -66,7 +66,7 @@ final class ReturnSpecial extends RNode {
  * {@link FunctionDefinitionNode}.
  */
 @RBuiltin(name = "return", kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX, nonEvalArgs = {0})
-public abstract class Return extends RBuiltinNode {
+public abstract class Return extends RBuiltinNode.Arg1 {
 
     public static RNode createSpecial(@SuppressWarnings("unused") ArgumentsSignature signature, RNode[] arguments, @SuppressWarnings("unused") boolean inReplacement) {
         return arguments.length == 1 ? new ReturnSpecial(arguments[0]) : null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java
index 2a735cdb0a..b5f44e9c07 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
  * R.home builtin.
  */
 @RBuiltin(name = "R.home", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-public abstract class Rhome extends RBuiltinNode {
+public abstract class Rhome extends RBuiltinNode.Arg0 {
 
     @Specialization
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
index b3176f58ae..ea10c5aea5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
@@ -51,7 +51,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
  * Note: remove is invoked from builtin wrappers 'rm' and 'remove' that are identical.
  */
 @RBuiltin(name = "remove", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "envir", "inherits"}, behavior = COMPLEX)
-public abstract class Rm extends RBuiltinNode {
+public abstract class Rm extends RBuiltinNode.Arg3 {
 
     private final BranchProfile invalidateProfile = BranchProfile.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
index 13230809be..0b5877e50c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "round", kind = PRIMITIVE, parameterNames = {"x", "digits"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class Round extends RBuiltinNode {
+public abstract class Round extends RBuiltinNode.Arg2 {
 
     public static final UnaryArithmeticFactory ROUND = RoundArithmetic::new;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
index e7ac9923d1..e3c1c87469 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "row", kind = INTERNAL, parameterNames = {"dims"}, behavior = PURE)
-public abstract class Row extends RBuiltinNode {
+public abstract class Row extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Row.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
index c8b0232b06..2a1ebf4a7b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 public class RowsumFunctions {
 
     @RBuiltin(name = "rowsum_matrix", kind = INTERNAL, parameterNames = {"x", "g", "uniqueg", "snarm", "rn"}, behavior = PURE)
-    public abstract static class Rowsum extends RBuiltinNode {
+    public abstract static class Rowsum extends RBuiltinNode.Arg5 {
 
         private final ConditionProfile typeProfile = ConditionProfile.createBinaryProfile();
         private final NACheck na = NACheck.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
index 867f378c97..8c2dfd931f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
@@ -52,41 +52,44 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-public abstract class S3DispatchFunctions extends RBuiltinNode {
+public abstract class S3DispatchFunctions {
 
-    @Child private S3FunctionLookupNode methodLookup;
-    @Child private CallMatcherNode callMatcher;
+    private static final class Helper extends RBaseNode {
+        @Child private S3FunctionLookupNode methodLookup;
+        @Child private CallMatcherNode callMatcher;
 
-    private final ConditionProfile callerFrameSlowPath = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile topLevelFrameProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile callerFrameSlowPath = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile topLevelFrameProfile = ConditionProfile.createBinaryProfile();
 
-    protected S3DispatchFunctions(boolean nextMethod) {
-        methodLookup = S3FunctionLookupNode.create(true, nextMethod);
-        callMatcher = CallMatcherNode.create(false);
-    }
+        protected Helper(boolean nextMethod) {
+            methodLookup = S3FunctionLookupNode.create(true, nextMethod);
+            callMatcher = CallMatcherNode.create(false);
+        }
 
-    protected MaterializedFrame getCallerFrame(VirtualFrame frame) {
-        MaterializedFrame funFrame = RArguments.getCallerFrame(frame);
-        if (callerFrameSlowPath.profile(funFrame == null)) {
-            funFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE).materialize();
-            RError.performanceWarning("slow caller frame access in UseMethod dispatch");
+        protected MaterializedFrame getCallerFrame(VirtualFrame frame) {
+            MaterializedFrame funFrame = RArguments.getCallerFrame(frame);
+            if (callerFrameSlowPath.profile(funFrame == null)) {
+                funFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE).materialize();
+                RError.performanceWarning("slow caller frame access in UseMethod dispatch");
+            }
+            // S3 method can be dispatched from top-level where there is no caller frame
+            return topLevelFrameProfile.profile(funFrame == null) ? frame.materialize() : funFrame;
         }
-        // S3 method can be dispatched from top-level where there is no caller frame
-        return topLevelFrameProfile.profile(funFrame == null) ? frame.materialize() : funFrame;
-    }
 
-    protected Object dispatch(VirtualFrame frame, String generic, RStringVector type, String group, MaterializedFrame callerFrame, MaterializedFrame genericDefFrame,
-                    ArgumentsSignature suppliedSignature, Object[] suppliedArguments) {
-        Result lookupResult = methodLookup.execute(frame, generic, type, group, callerFrame, genericDefFrame);
+        protected Object dispatch(VirtualFrame frame, String generic, RStringVector type, String group, MaterializedFrame callerFrame, MaterializedFrame genericDefFrame,
+                        ArgumentsSignature suppliedSignature, Object[] suppliedArguments) {
+            Result lookupResult = methodLookup.execute(frame, generic, type, group, callerFrame, genericDefFrame);
 
-        S3Args s3Args = new S3Args(lookupResult.generic, lookupResult.clazz, lookupResult.targetFunctionName, callerFrame, genericDefFrame, group);
-        Object result = callMatcher.execute(frame, suppliedSignature, suppliedArguments, lookupResult.function, lookupResult.targetFunctionName, s3Args);
-        return result;
+            S3Args s3Args = new S3Args(lookupResult.generic, lookupResult.clazz, lookupResult.targetFunctionName, callerFrame, genericDefFrame, group);
+            Object result = callMatcher.execute(frame, suppliedSignature, suppliedArguments, lookupResult.function, lookupResult.targetFunctionName, s3Args);
+            return result;
+        }
     }
 
     @RBuiltin(name = "UseMethod", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"generic", "object"}, behavior = COMPLEX)
-    public abstract static class UseMethod extends S3DispatchFunctions {
+    public abstract static class UseMethod extends RBuiltinNode.Arg2 {
 
         /*
          * TODO: If more than two parameters are passed to UseMethod the extra parameters are
@@ -95,6 +98,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
 
         @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNodeGen.create(true, true);
         @Child private PromiseCheckHelperNode promiseCheckHelper;
+        @Child private Helper helper = new Helper(false);
 
         private final BranchProfile firstArgMissing = BranchProfile.create();
         private final ConditionProfile argMissingProfile = ConditionProfile.createBinaryProfile();
@@ -104,10 +108,6 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
             Casts.noCasts(UseMethod.class);
         }
 
-        protected UseMethod() {
-            super(false);
-        }
-
         @Specialization
         protected Object execute(VirtualFrame frame, String generic, Object arg) {
             Object dispatchedObject;
@@ -119,12 +119,12 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
             }
 
             RStringVector type = dispatchedObject == null ? RDataFactory.createEmptyStringVector() : classHierarchyNode.execute(dispatchedObject);
-            MaterializedFrame callerFrame = getCallerFrame(frame);
+            MaterializedFrame callerFrame = helper.getCallerFrame(frame);
             MaterializedFrame genericDefFrame = RArguments.getEnclosingFrame(frame);
 
             ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(frame);
             Object[] suppliedArguments = RArguments.getArguments(frame);
-            Object result = dispatch(frame, generic, type, null, callerFrame, genericDefFrame, suppliedSignature, suppliedArguments);
+            Object result = helper.dispatch(frame, generic, type, null, callerFrame, genericDefFrame, suppliedSignature, suppliedArguments);
             throw new ReturnException(result, RArguments.getCall(frame));
         }
 
@@ -173,7 +173,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
     }
 
     @RBuiltin(name = "NextMethod", visibility = CUSTOM, kind = SUBSTITUTE, parameterNames = {"generic", "object", "..."}, behavior = COMPLEX)
-    public abstract static class NextMethod extends S3DispatchFunctions {
+    public abstract static class NextMethod extends RBuiltinNode.Arg3 {
 
         @Child private LocalReadVariableNode rvnGroup = LocalReadVariableNode.create(RRuntime.R_DOT_GROUP, false);
         @Child private LocalReadVariableNode rvnClass = LocalReadVariableNode.create(RRuntime.R_DOT_CLASS, false);
@@ -186,6 +186,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
 
         @Child private PromiseHelperNode promiseHelper;
         @Child private ClassHierarchyNode hierarchy;
+        @Child private Helper helper = new Helper(true);
 
         private final ConditionProfile emptyArgsProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile genericCallFrameNullProfile = ConditionProfile.createBinaryProfile();
@@ -199,10 +200,6 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
             Casts.noCasts(NextMethod.class);
         }
 
-        protected NextMethod() {
-            super(true);
-        }
-
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{RNull.instance, RNull.instance, RArgsValuesAndNames.EMPTY};
@@ -252,7 +249,7 @@ public abstract class S3DispatchFunctions extends RBuiltinNode {
                 suppliedArguments = combinedResult.getArguments();
                 finalSignature = combinedResult.getSignature();
             }
-            return dispatch(frame, generic, readType(frame), group, genericCallFrame, genericDefFrame, finalSignature, suppliedArguments);
+            return helper.dispatch(frame, generic, readType(frame), group, genericCallFrame, genericDefFrame, finalSignature, suppliedArguments);
         }
 
         private MaterializedFrame getDefFrame(VirtualFrame frame) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
index fd7cbae8c1..1e79a7792b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.rng.RRNG;
 
 @RBuiltin(name = "sample", kind = INTERNAL, parameterNames = {"x", "size", "replace", "prob"}, behavior = MODIFIES_STATE)
-public abstract class Sample extends RBuiltinNode {
+public abstract class Sample extends RBuiltinNode.Arg4 {
     private final ConditionProfile sampleSizeProfile = ConditionProfile.createBinaryProfile();
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
index e5ce462981..8adbb2699e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  * Sample2 is more efficient special case implementation of {@link Sample}.
  */
 @RBuiltin(name = "sample2", kind = INTERNAL, parameterNames = {"x", "size"}, behavior = MODIFIES_STATE)
-public abstract class Sample2 extends RBuiltinNode {
+public abstract class Sample2 extends RBuiltinNode.Arg2 {
     private static final double U = 33554432.0;
     static final double MAX_INT = Integer.MAX_VALUE;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 85512d6eba..62c1180a12 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -58,7 +58,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "scan", kind = INTERNAL, parameterNames = {"file", "what", "nmax", "sep", "dec", "quote", "skip", "nlines", "na.strings", "flush", "fill", "strip.white", "quiet", "blank.lines.skip",
                 "multi.line", "comment.char", "allowEscapes", "encoding", "skipNull"}, behavior = IO)
-public abstract class Scan extends RBuiltinNode {
+public abstract class Scan extends RBuiltinNode.Arg19 {
 
     private static final int SCAN_BLOCKSIZE = 1000;
     private static final int NO_COMCHAR = 100000; /* won't occur even in Unicode */
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 25e8d6eaeb..2207d23444 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -324,7 +324,7 @@ public final class SeqFunctions {
 
     @TypeSystemReference(RTypes.class)
     @RBuiltin(name = "seq_along", kind = PRIMITIVE, parameterNames = {"along.with"}, behavior = PURE)
-    public abstract static class SeqAlong extends RBuiltinNode {
+    public abstract static class SeqAlong extends RBuiltinNode.Arg1 {
         @Child private ClassHierarchyNode classHierarchyNode = ClassHierarchyNode.create();
 
         static {
@@ -366,7 +366,7 @@ public final class SeqFunctions {
 
     @TypeSystemReference(RTypes.class)
     @RBuiltin(name = "seq_len", kind = PRIMITIVE, parameterNames = {"length.out"}, behavior = PURE)
-    public abstract static class SeqLen extends RBuiltinNode {
+    public abstract static class SeqLen extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(SeqLen.class);
@@ -403,12 +403,11 @@ public final class SeqFunctions {
      *
      * N.B. javac gives error "cannot find symbol" on plain "@RBuiltin".
      */
-    @TypeSystemReference(RTypes.class)
+    @SuppressWarnings("unused")
     @ImportStatic({AsRealNodeGen.class, SeqFunctions.class})
     @com.oracle.truffle.r.runtime.builtins.RBuiltin(name = "seq.int", kind = PRIMITIVE, parameterNames = {"from", "to", "by", "length.out", "along.with",
                     "..."}, dispatch = INTERNAL_GENERIC, genericName = "seq", behavior = PURE)
-    @SuppressWarnings("unused")
-    public abstract static class SeqInt extends RBuiltinNode {
+    public abstract static class SeqInt extends RBuiltinNode.Arg5 {
         private final BranchProfile error = BranchProfile.create();
         private final boolean seqFastPath;
 
@@ -426,7 +425,8 @@ public final class SeqFunctions {
             casts.arg("length.out").allowMissing().mapIf(nullValue(), missingConstant());
         }
 
-        protected abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith);
+        @Override
+        public abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith);
 
         protected SeqInt(boolean seqFastPath) {
             this.seqFastPath = seqFastPath;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
index 7ca7bccf00..8d1d966573 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SerializeFunctions.java
@@ -35,6 +35,7 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -46,52 +47,51 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public class SerializeFunctions {
 
-    public abstract static class Adapter extends RBuiltinNode {
-        @TruffleBoundary
-        protected Object doUnserializeFromConnBase(int connIndex, @SuppressWarnings("unused") REnvironment refhook) {
-            try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen("rb")) {
-                if (!openConn.canRead()) {
-                    throw error(RError.Message.CONNECTION_NOT_OPEN_READ);
-                }
-                return RSerialize.unserialize(openConn);
-            } catch (IOException ex) {
-                throw error(RError.Message.GENERIC, ex.getMessage());
+    @TruffleBoundary
+    protected static Object doUnserializeFromConnBase(RBaseNode node, int connIndex, @SuppressWarnings("unused") REnvironment refhook) {
+        try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen("rb")) {
+            if (!openConn.canRead()) {
+                throw node.error(RError.Message.CONNECTION_NOT_OPEN_READ);
             }
+            return RSerialize.unserialize(openConn);
+        } catch (IOException ex) {
+            throw node.error(RError.Message.GENERIC, ex.getMessage());
         }
+    }
+
+    @TruffleBoundary
+    protected static Object doUnserializeFromRaw(RAbstractRawVector data, @SuppressWarnings("unused") REnvironment refhook) {
+        return RSerialize.unserialize(data);
+    }
 
-        @TruffleBoundary
-        protected Object doUnserializeFromRaw(RAbstractRawVector data, @SuppressWarnings("unused") REnvironment refhook) {
-            return RSerialize.unserialize(data);
-        }
-
-        @TruffleBoundary
-        protected Object doSerializeToConnBase(Object object, int connIndex, int type, @SuppressWarnings("unused") byte xdrLogical, @SuppressWarnings("unused") RNull version,
-                        @SuppressWarnings("unused") RNull refhook) {
-            // xdr is only relevant if ascii is false
-            try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen(type != RSerialize.XDR ? "wt" : "wb")) {
-                if (!openConn.canWrite()) {
-                    throw error(RError.Message.CONNECTION_NOT_OPEN_WRITE);
-                }
-                if (type == RSerialize.XDR && openConn.isTextMode()) {
-                    throw error(RError.Message.BINARY_CONNECTION_REQUIRED);
-                }
-                RSerialize.serialize(openConn, object, type, RSerialize.DEFAULT_VERSION, null);
-                return RNull.instance;
-            } catch (IOException ex) {
-                throw error(RError.Message.GENERIC, ex.getMessage());
+    @TruffleBoundary
+    protected static Object doSerializeToConnBase(RBaseNode node, Object object, int connIndex, int type, @SuppressWarnings("unused") byte xdrLogical, @SuppressWarnings("unused") RNull version,
+                    @SuppressWarnings("unused") RNull refhook) {
+        // xdr is only relevant if ascii is false
+        try (RConnection openConn = RConnection.fromIndex(connIndex).forceOpen(type != RSerialize.XDR ? "wt" : "wb")) {
+            if (!openConn.canWrite()) {
+                throw node.error(RError.Message.CONNECTION_NOT_OPEN_WRITE);
             }
+            if (type == RSerialize.XDR && openConn.isTextMode()) {
+                throw node.error(RError.Message.BINARY_CONNECTION_REQUIRED);
+            }
+            RSerialize.serialize(openConn, object, type, RSerialize.DEFAULT_VERSION, null);
+            return RNull.instance;
+        } catch (IOException ex) {
+            throw node.error(RError.Message.GENERIC, ex.getMessage());
         }
+    }
 
-        protected static void connection(Casts casts) {
-            casts.arg("con").mustBe(integerValue()).asIntegerVector().findFirst();
-        }
+    protected static void connection(Casts casts) {
+        casts.arg("con").mustBe(integerValue()).asIntegerVector().findFirst();
     }
 
     @RBuiltin(name = "unserializeFromConn", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO)
-    public abstract static class UnserializeFromConn extends Adapter {
+    public abstract static class UnserializeFromConn extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(UnserializeFromConn.class);
@@ -100,18 +100,18 @@ public class SerializeFunctions {
 
         @Specialization
         protected Object doUnserializeFromConn(int conn, @SuppressWarnings("unused") RNull refhook) {
-            return doUnserializeFromConnBase(conn, null);
+            return doUnserializeFromConnBase(this, conn, null);
         }
 
         @Specialization
         protected Object doUnserializeFromConn(int conn, @SuppressWarnings("unused") REnvironment refhook) {
             // TODO figure out what this really means?
-            return doUnserializeFromConnBase(conn, null);
+            return doUnserializeFromConnBase(this, conn, null);
         }
     }
 
     @RBuiltin(name = "serializeToConn", visibility = OFF, kind = INTERNAL, parameterNames = {"object", "con", "ascii", "version", "refhook"}, behavior = IO)
-    public abstract static class SerializeToConn extends Adapter {
+    public abstract static class SerializeToConn extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(SerializeToConn.class);
@@ -132,7 +132,7 @@ public class SerializeFunctions {
             } else {
                 type = RSerialize.XDR;
             }
-            return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook);
+            return doSerializeToConnBase(this, object, conn, type, RRuntime.LOGICAL_NA, version, refhook);
         }
 
         @SuppressWarnings("unused")
@@ -144,7 +144,7 @@ public class SerializeFunctions {
     }
 
     @RBuiltin(name = "unserialize", kind = INTERNAL, parameterNames = {"con", "refhook"}, behavior = IO)
-    public abstract static class Unserialize extends Adapter {
+    public abstract static class Unserialize extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(Unserialize.class);
@@ -154,7 +154,7 @@ public class SerializeFunctions {
 
         @Specialization
         protected Object unSerialize(int conn, @SuppressWarnings("unused") RNull refhook) {
-            return doUnserializeFromConnBase(conn, null);
+            return doUnserializeFromConnBase(this, conn, null);
         }
 
         @Specialization
@@ -164,7 +164,7 @@ public class SerializeFunctions {
     }
 
     @RBuiltin(name = "serialize", kind = INTERNAL, parameterNames = {"object", "con", "type", "version", "refhook"}, behavior = IO)
-    public abstract static class Serialize extends Adapter {
+    public abstract static class Serialize extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(Serialize.class);
@@ -174,7 +174,7 @@ public class SerializeFunctions {
 
         @Specialization
         protected Object serialize(Object object, int conn, int type, RNull version, RNull refhook) {
-            return doSerializeToConnBase(object, conn, type, RRuntime.LOGICAL_NA, version, refhook);
+            return doSerializeToConnBase(this, object, conn, type, RRuntime.LOGICAL_NA, version, refhook);
         }
 
         @SuppressWarnings("unused")
@@ -186,7 +186,7 @@ public class SerializeFunctions {
     }
 
     @RBuiltin(name = "serializeb", kind = INTERNAL, parameterNames = {"object", "con", "xdr", "version", "refhook"}, behavior = IO)
-    public abstract static class SerializeB extends Adapter {
+    public abstract static class SerializeB extends RBuiltinNode.Arg5 {
 
         static {
             Casts casts = new Casts(SerializeB.class);
@@ -199,7 +199,7 @@ public class SerializeFunctions {
             if (!RRuntime.fromLogical(xdrLogical)) {
                 throw RError.nyi(this, "xdr==FALSE");
             }
-            return doSerializeToConnBase(object, conn, RRuntime.LOGICAL_FALSE, xdrLogical, version, refhook);
+            return doSerializeToConnBase(this, object, conn, RRuntime.LOGICAL_FALSE, xdrLogical, version, refhook);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
index c590cebea8..bc74b10deb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetS4Object.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSequence;
 
 @RBuiltin(name = "setS4Object", kind = INTERNAL, parameterNames = {"object", "flag", "complete"}, behavior = PURE)
-public abstract class SetS4Object extends RBuiltinNode {
+public abstract class SetS4Object extends RBuiltinNode.Arg3 {
 
     @Child private AsS4 asS4 = AsS4NodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java
index 1b89fd845d..175bf4347b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SetTimeLimit.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "setTimeLimit", kind = INTERNAL, parameterNames = {"cpu", "elapsed", "transient"}, visibility = OFF, behavior = COMPLEX)
-public abstract class SetTimeLimit extends RBuiltinNode {
+public abstract class SetTimeLimit extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(SetTimeLimit.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
index 42c91558b5..92ca9352ea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
 @RBuiltin(name = "setwd", visibility = OFF, kind = INTERNAL, parameterNames = "path", behavior = IO)
-public abstract class Setwd extends RBuiltinNode {
+public abstract class Setwd extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Setwd.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
index d06c25acbd..9d9e87d1c0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ShortRowNames.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "shortRowNames", kind = INTERNAL, parameterNames = {"x", "type"}, behavior = PURE)
-public abstract class ShortRowNames extends RBuiltinNode {
+public abstract class ShortRowNames extends RBuiltinNode.Arg2 {
 
     private final BranchProfile naValueMet = BranchProfile.create();
     private final ValueProfile operandTypeProfile = ValueProfile.createClassProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
index 5c3afc71a8..1ef56ebc6b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
@@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "signif", kind = PRIMITIVE, parameterNames = {"x", "digits"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class Signif extends RBuiltinNode {
+public abstract class Signif extends RBuiltinNode.Arg2 {
 
     @Override
     public Object[] getDefaultParameterValues() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
index c187408a6a..313a824464 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SinkFunctions.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 public class SinkFunctions {
     @RBuiltin(name = "sink", visibility = OFF, kind = INTERNAL, parameterNames = {"file", "closeOnExit", "type", "split"}, behavior = IO)
-    public abstract static class Sink extends RBuiltinNode {
+    public abstract static class Sink extends RBuiltinNode.Arg4 {
 
         static {
             Casts casts = new Casts(Sink.class);
@@ -77,7 +77,7 @@ public class SinkFunctions {
     }
 
     @RBuiltin(name = "sink.number", kind = INTERNAL, parameterNames = {"type"}, behavior = IO)
-    public abstract static class SinkNumber extends RBuiltinNode {
+    public abstract static class SinkNumber extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(SinkNumber.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
index f352c35e80..98c7e64200 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
@@ -34,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 
 @RBuiltin(name = "@", kind = PRIMITIVE, parameterNames = {"", ""}, nonEvalArgs = 1, behavior = COMPLEX)
-public abstract class Slot extends RBuiltinNode {
+public abstract class Slot extends RBuiltinNode.Arg2 {
 
     @Child private UpdateShareableChildValueNode sharedAttrUpdate = UpdateShareableChildValueNode.create();
     @Child private AccessSlotNode accessSlotNode = AccessSlotNodeGen.create(true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index 1dc73f7345..1cbef88f11 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
@@ -41,7 +42,7 @@ import java.util.Collections;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -66,88 +67,86 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  */
 public class SortFunctions {
 
-    private abstract static class Adapter extends RBuiltinNode {
-        protected static void addCastForX(Casts casts) {
-            casts.arg("x").allowNull().mustBe(rawValue().not(), RAW_SORT).mustBe(instanceOf(RAbstractListVector.class).not(), ONLY_ATOMIC_CAN_BE_SORTED).mustBe(
-                            abstractVectorValue(), ONLY_ATOMIC_CAN_BE_SORTED);
-        }
+    protected static void addCastForX(Casts casts) {
+        casts.arg("x").allowNull().mustBe(rawValue().not(), RAW_SORT).mustBe(instanceOf(RAbstractListVector.class).not(), ONLY_ATOMIC_CAN_BE_SORTED).mustBe(
+                        abstractVectorValue(), ONLY_ATOMIC_CAN_BE_SORTED);
+    }
 
-        protected static void addCastForDecreasing(Casts casts) {
-            casts.arg("decreasing").defaultError(INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
-        }
+    protected static void addCastForDecreasing(Casts casts) {
+        casts.arg("decreasing").defaultError(INVALID_LOGICAL, "decreasing").mustBe(numericValue()).asLogicalVector().findFirst().map(toBoolean());
+    }
 
-        @TruffleBoundary
-        private static double[] sort(double[] data, boolean decreasing) {
-            // no reverse comparator for primitives
-            Arrays.parallelSort(data);
-            if (decreasing) {
-                int len = data.length;
-                for (int i = len / 2 - 1; i >= 0; i--) {
-                    double temp = data[i];
-                    data[i] = data[len - i - 1];
-                    data[len - i - 1] = temp;
-                }
+    @TruffleBoundary
+    private static double[] sort(double[] data, boolean decreasing) {
+        // no reverse comparator for primitives
+        Arrays.parallelSort(data);
+        if (decreasing) {
+            int len = data.length;
+            for (int i = len / 2 - 1; i >= 0; i--) {
+                double temp = data[i];
+                data[i] = data[len - i - 1];
+                data[len - i - 1] = temp;
             }
-            return data;
         }
+        return data;
+    }
 
-        @TruffleBoundary
-        private static int[] sort(int[] data, boolean decreasing) {
-            Arrays.parallelSort(data);
-            if (decreasing) {
-                int len = data.length;
-                for (int i = len / 2 - 1; i >= 0; i--) {
-                    int temp = data[i];
-                    data[i] = data[len - i - 1];
-                    data[len - i - 1] = temp;
-                }
+    @TruffleBoundary
+    private static int[] sort(int[] data, boolean decreasing) {
+        Arrays.parallelSort(data);
+        if (decreasing) {
+            int len = data.length;
+            for (int i = len / 2 - 1; i >= 0; i--) {
+                int temp = data[i];
+                data[i] = data[len - i - 1];
+                data[len - i - 1] = temp;
             }
-            return data;
         }
+        return data;
+    }
 
-        @TruffleBoundary
-        private static byte[] sort(byte[] data, boolean decreasing) {
-            Arrays.parallelSort(data);
-            if (decreasing) {
-                int len = data.length;
-                for (int i = len / 2 - 1; i >= 0; i--) {
-                    byte temp = data[i];
-                    data[i] = data[len - i - 1];
-                    data[len - i - 1] = temp;
-                }
+    @TruffleBoundary
+    private static byte[] sort(byte[] data, boolean decreasing) {
+        Arrays.parallelSort(data);
+        if (decreasing) {
+            int len = data.length;
+            for (int i = len / 2 - 1; i >= 0; i--) {
+                byte temp = data[i];
+                data[i] = data[len - i - 1];
+                data[len - i - 1] = temp;
             }
-            return data;
         }
+        return data;
+    }
 
-        @TruffleBoundary
-        private static String[] sort(String[] data, boolean decreasing) {
-            if (decreasing) {
-                Arrays.parallelSort(data, Collections.reverseOrder());
-            } else {
-                Arrays.parallelSort(data);
-            }
-            return data;
+    @TruffleBoundary
+    private static String[] sort(String[] data, boolean decreasing) {
+        if (decreasing) {
+            Arrays.parallelSort(data, Collections.reverseOrder());
+        } else {
+            Arrays.parallelSort(data);
         }
+        return data;
+    }
 
-        protected RDoubleVector jdkSort(RAbstractDoubleVector vec, boolean decreasing) {
-            double[] data = vec.materialize().getDataCopy();
-            return RDataFactory.createDoubleVector(sort(data, decreasing), vec.isComplete());
-        }
+    protected static RDoubleVector jdkSort(RAbstractDoubleVector vec, boolean decreasing) {
+        double[] data = vec.materialize().getDataCopy();
+        return RDataFactory.createDoubleVector(sort(data, decreasing), vec.isComplete());
+    }
 
-        protected RIntVector jdkSort(RAbstractIntVector vec, boolean decreasing) {
-            int[] data = vec.materialize().getDataCopy();
-            return RDataFactory.createIntVector(sort(data, decreasing), vec.isComplete());
-        }
+    protected static RIntVector jdkSort(RAbstractIntVector vec, boolean decreasing) {
+        int[] data = vec.materialize().getDataCopy();
+        return RDataFactory.createIntVector(sort(data, decreasing), vec.isComplete());
+    }
 
-        protected RStringVector jdkSort(RAbstractStringVector vec, boolean decreasing) {
-            String[] data = vec.materialize().getDataCopy();
-            return RDataFactory.createStringVector(sort(data, decreasing), vec.isComplete());
-        }
+    protected static RStringVector jdkSort(RAbstractStringVector vec, boolean decreasing) {
+        String[] data = vec.materialize().getDataCopy();
+        return RDataFactory.createStringVector(sort(data, decreasing), vec.isComplete());
+    }
 
-        protected RLogicalVector jdkSort(RAbstractLogicalVector vec, boolean decreasing) {
-            byte[] data = vec.materialize().getDataCopy();
-            return RDataFactory.createLogicalVector(sort(data, decreasing), vec.isComplete());
-        }
+    protected static RLogicalVector jdkSort(RAbstractLogicalVector vec, boolean decreasing) {
+        byte[] data = vec.materialize().getDataCopy();
+        return RDataFactory.createLogicalVector(sort(data, decreasing), vec.isComplete());
     }
 
     /**
@@ -158,7 +157,7 @@ public class SortFunctions {
      * N.B. The R code strips out {@code NA} and {@code NaN} values before calling the builtin.
      */
     @RBuiltin(name = "sort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE)
-    public abstract static class Sort extends Adapter {
+    public abstract static class Sort extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(Sort.class);
@@ -187,25 +186,25 @@ public class SortFunctions {
         }
 
         @Specialization
-        protected RLogicalVector sort(RAbstractComplexVector vec, boolean decreasing) {
-            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1); // [TODO] implement
-                                                                                // complex sort
+        protected RLogicalVector sort(@SuppressWarnings("unused") RAbstractComplexVector vec, @SuppressWarnings("unused") boolean decreasing) {
+            // TODO: implement complex sort
+            throw RError.error(this, RError.Message.UNIMPLEMENTED_ARG_TYPE, 1);
         }
 
         @Specialization
-        protected RNull sort(RNull vec, boolean decreasing) {
+        protected RNull sort(@SuppressWarnings("unused") RNull vec, @SuppressWarnings("unused") boolean decreasing) {
             return RNull.instance;
         }
 
     }
 
     @RBuiltin(name = "qsort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE)
-    public abstract static class QSort extends Adapter {
+    public abstract static class QSort extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(QSort.class);
             casts.arg("x").defaultError(NOT_NUMERIC_VECTOR).mustBe(instanceOf(RAbstractListVector.class).not()).mustBe(integerValue().or(doubleValue()));
-            casts.arg("decreasing").mapIf(numericValue().not(), Predef.constant(RRuntime.LOGICAL_TRUE)).asLogicalVector().findFirst().map(toBoolean());
+            casts.arg("decreasing").mapIf(numericValue().not(), constant(RRuntime.LOGICAL_TRUE)).asLogicalVector().findFirst().map(toBoolean());
         }
 
         @Specialization
@@ -220,7 +219,7 @@ public class SortFunctions {
     }
 
     @RBuiltin(name = "psort", kind = INTERNAL, parameterNames = {"x", "partial"}, behavior = PURE)
-    public abstract static class PartialSort extends Adapter {
+    public abstract static class PartialSort extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(PartialSort.class);
@@ -258,7 +257,7 @@ public class SortFunctions {
         }
 
         @Specialization
-        protected RNull sort(RNull vec, Object partial) {
+        protected RNull sort(@SuppressWarnings("unused") RNull vec, @SuppressWarnings("unused") Object partial) {
             return RNull.instance;
         }
     }
@@ -270,7 +269,7 @@ public class SortFunctions {
      * now we delegate to {@code order} and do not implement the {@code retgrp} argument.
      */
     @RBuiltin(name = "radixsort", kind = INTERNAL, parameterNames = {"na.last", "decreasing", "retgrp", "sortstr", "..."}, behavior = PURE)
-    public abstract static class RadixSort extends Adapter {
+    public abstract static class RadixSort extends RBuiltinNode.Arg5 {
         @Child private Order orderNode = OrderNodeGen.create();
 
         static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
index b43d2e7fc9..8a5446c3d6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  * identical except for the argument type.
  */
 @RBuiltin(name = "split", kind = INTERNAL, parameterNames = {"x", "f"}, behavior = PURE)
-public abstract class Split extends RBuiltinNode {
+public abstract class Split extends RBuiltinNode.Arg2 {
 
     @Child private RFactorNodes.GetLevels getLevelNode = new RFactorNodes.GetLevels();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
index cb0c9bd89a..fcadf58d32 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
@@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "sprintf", kind = INTERNAL, parameterNames = {"fmt", "..."}, behavior = PURE)
 
-public abstract class Sprintf extends RBuiltinNode {
+public abstract class Sprintf extends RBuiltinNode.Arg2 {
 
     static {
         Casts.noCasts(Sprintf.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
index 4a6f412f95..b96cfacbd5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
@@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 // transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function)
 
 @RBuiltin(name = "standardGeneric", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"f", "fdef"}, behavior = COMPLEX)
-public abstract class StandardGeneric extends RBuiltinNode {
+public abstract class StandardGeneric extends RBuiltinNode.Arg2 {
 
     // TODO: for now, we always go through generic dispatch
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
index 37fc9f60f7..a92d62da66 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StartsEndsWithFunctions.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class StartsEndsWithFunctions {
 
-    private abstract static class Adapter extends RBuiltinNode {
+    private abstract static class Adapter extends RBuiltinNode.Arg2 {
         private final NACheck naCheck = NACheck.create();
         private final ConditionProfile singlePrefixProfile = ConditionProfile.createBinaryProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java
index efb1ada9f4..6012893ec5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Stop.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = "stop", kind = INTERNAL, parameterNames = {"call", "message"}, behavior = COMPLEX)
-public abstract class Stop extends RBuiltinNode {
+public abstract class Stop extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(Stop.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
index 969121a265..46455a6a60 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strrep.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "strrep", kind = INTERNAL, parameterNames = {"x", "times"}, behavior = PURE)
-public abstract class Strrep extends RBuiltinNode {
+public abstract class Strrep extends RBuiltinNode.Arg2 {
     private final NACheck naCheck = NACheck.create();
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
index 86e2c0b11b..57d4d6171b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "strtoi", kind = INTERNAL, parameterNames = {"x", "base"}, behavior = PURE)
-public abstract class Strtoi extends RBuiltinNode {
+public abstract class Strtoi extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(Strtoi.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
index b80c706e89..473d041dbb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java
@@ -35,7 +35,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "strtrim", kind = INTERNAL, parameterNames = {"x", "width"}, behavior = PURE)
-public abstract class Strtrim extends RBuiltinNode {
+public abstract class Strtrim extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(Strtrim.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
index 936b647364..5f20186adf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
@@ -48,7 +48,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "substitute", kind = PRIMITIVE, parameterNames = {"expr", "env"}, nonEvalArgs = 0, behavior = COMPLEX)
-public abstract class Substitute extends RBuiltinNode {
+public abstract class Substitute extends RBuiltinNode.Arg2 {
 
     @Child private Quote quote;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
index a69ab8d054..f3c3760c13 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "substr", kind = INTERNAL, parameterNames = {"x", "start", "stop"}, behavior = PURE)
-public abstract class Substr extends RBuiltinNode {
+public abstract class Substr extends RBuiltinNode.Arg3 {
     private final NACheck na = NACheck.create();
     private final BranchProfile everSeenIllegalRange = BranchProfile.create();
     private final ConditionProfile naIndexesProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
index bcc5478198..aa347076a2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * Sum has combine semantics (TBD: exactly?) and uses a reduce operation on the resulting array.
  */
 @RBuiltin(name = "sum", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
-public abstract class Sum extends RBuiltinNode {
+public abstract class Sum extends RBuiltinNode.Arg2 {
 
     protected static final boolean FULL_PRECISION = FastROptions.FullPrecisionSum.getBooleanValue();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
index af0650a456..e403219f5f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
@@ -52,7 +52,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
  *
  */
 @RBuiltin(name = "switch", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"EXPR", "..."}, nonEvalArgs = 1, behavior = COMPLEX)
-public abstract class Switch extends RBuiltinNode {
+public abstract class Switch extends RBuiltinNode.Arg2 {
 
     @Child private PromiseCheckHelperNode promiseHelper = new PromiseCheckHelperNode();
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
index 79b06579bc..ea2f8107dc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SysFunctions.java
@@ -74,7 +74,7 @@ import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName;
 public class SysFunctions {
 
     @RBuiltin(name = "Sys.getpid", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class SysGetpid extends RBuiltinNode {
+    public abstract static class SysGetpid extends RBuiltinNode.Arg0 {
         @Child private BaseRFFI.GetpidNode getpidNode = BaseRFFI.GetpidNode.create();
 
         @Specialization
@@ -86,7 +86,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.getenv", kind = INTERNAL, parameterNames = {"x", "unset"}, behavior = READS_STATE)
-    public abstract static class SysGetenv extends RBuiltinNode {
+    public abstract static class SysGetenv extends RBuiltinNode.Arg2 {
         private final ConditionProfile zeroLengthProfile = ConditionProfile.createBinaryProfile();
 
         static {
@@ -135,33 +135,31 @@ public class SysFunctions {
      * code depends critically in the current implementation which sets/unsets this environment
      * variable around a call to loadNamespace/attachNamespace.
      */
-    protected abstract static class LoadNamespaceAdapter extends RBuiltinNode {
-        private static final String NS_LOAD = "_R_NS_LOAD_";
-        private static final String LOADNAMESPACE = "loadNamespace";
+    private static final String NS_LOAD = "_R_NS_LOAD_";
+    private static final String LOADNAMESPACE = "loadNamespace";
 
-        protected void checkNSLoad(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values, boolean setting) {
-            if (names.getLength() == 1 && NS_LOAD.equals(names.getDataAt(0))) {
-                doCheckNSLoad(frame.materialize(), values, setting);
-            }
+    protected static void checkNSLoad(VirtualFrame frame, RAbstractStringVector names, RAbstractStringVector values, boolean setting) {
+        if (names.getLength() == 1 && NS_LOAD.equals(names.getDataAt(0))) {
+            doCheckNSLoad(frame.materialize(), values, setting);
         }
+    }
 
-        @TruffleBoundary
-        private static void doCheckNSLoad(MaterializedFrame frame, RAbstractStringVector values, boolean setting) {
-            Frame caller = Utils.getCallerFrame(frame, FrameAccess.READ_ONLY);
-            RFunction func = RArguments.getFunction(caller);
-            if (func.toString().equals(LOADNAMESPACE)) {
-                if (setting) {
-                    RContext.getInstance().setNamespaceName(values.getDataAt(0));
-                } else {
-                    // Now we can run the overrides
-                    RBuiltinPackages.loadDefaultPackageOverrides(RContext.getInstance().getNamespaceName());
-                }
+    @TruffleBoundary
+    private static void doCheckNSLoad(MaterializedFrame frame, RAbstractStringVector values, boolean setting) {
+        Frame caller = Utils.getCallerFrame(frame, FrameAccess.READ_ONLY);
+        RFunction func = RArguments.getFunction(caller);
+        if (func.toString().equals(LOADNAMESPACE)) {
+            if (setting) {
+                RContext.getInstance().setNamespaceName(values.getDataAt(0));
+            } else {
+                // Now we can run the overrides
+                RBuiltinPackages.loadDefaultPackageOverrides(RContext.getInstance().getNamespaceName());
             }
         }
     }
 
     @RBuiltin(name = "Sys.setenv", visibility = OFF, kind = INTERNAL, parameterNames = {"nm", "values"}, behavior = MODIFIES_STATE)
-    public abstract static class SysSetEnv extends LoadNamespaceAdapter {
+    public abstract static class SysSetEnv extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(SysSetEnv.class);
@@ -191,7 +189,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.unsetenv", visibility = OFF, kind = INTERNAL, parameterNames = {"x"}, behavior = READS_STATE)
-    public abstract static class SysUnSetEnv extends LoadNamespaceAdapter {
+    public abstract static class SysUnSetEnv extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(SysUnSetEnv.class);
@@ -217,7 +215,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.sleep", visibility = OFF, kind = INTERNAL, parameterNames = {"time"}, behavior = COMPLEX)
-    public abstract static class SysSleep extends RBuiltinNode {
+    public abstract static class SysSleep extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(SysSleep.class);
@@ -248,7 +246,7 @@ public class SysFunctions {
      * TODO: Handle ~ expansion which is not handled by POSIX.
      */
     @RBuiltin(name = "Sys.readlink", kind = INTERNAL, parameterNames = {"paths"}, behavior = IO)
-    public abstract static class SysReadlink extends RBuiltinNode {
+    public abstract static class SysReadlink extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(SysReadlink.class);
@@ -291,7 +289,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.chmod", visibility = OFF, kind = INTERNAL, parameterNames = {"paths", "octmode", "use_umask"}, behavior = IO)
-    public abstract static class SysChmod extends RBuiltinNode {
+    public abstract static class SysChmod extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(SysChmod.class);
@@ -319,7 +317,7 @@ public class SysFunctions {
 
     // TODO implement
     @RBuiltin(name = "Sys.umask", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"octmode"}, behavior = COMPLEX)
-    public abstract static class SysUmask extends RBuiltinNode {
+    public abstract static class SysUmask extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(SysUmask.class);
@@ -335,7 +333,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.time", kind = INTERNAL, parameterNames = {}, behavior = IO)
-    public abstract static class SysTime extends RBuiltinNode {
+    public abstract static class SysTime extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected double sysTime() {
@@ -344,7 +342,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.info", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class SysInfo extends RBuiltinNode {
+    public abstract static class SysInfo extends RBuiltinNode.Arg0 {
         private static final String[] NAMES = new String[]{"sysname", "release", "version", "nodename", "machine", "login", "user", "effective_user"};
         private static final RStringVector NAMES_ATTR = RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR);
 
@@ -370,7 +368,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "Sys.glob", kind = INTERNAL, parameterNames = {"paths", "dirmask"}, behavior = IO)
-    public abstract static class SysGlob extends RBuiltinNode {
+    public abstract static class SysGlob extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(SysGlob.class);
@@ -399,7 +397,7 @@ public class SysFunctions {
     }
 
     @RBuiltin(name = "setFileTime", kind = INTERNAL, parameterNames = {"path", "time"}, visibility = OFF, behavior = IO)
-    public abstract static class SysSetFileTime extends RBuiltinNode {
+    public abstract static class SysSetFileTime extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(SysSetFileTime.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
index 7aacea27ab..be218cc4bd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "tabulate", kind = INTERNAL, parameterNames = {"bin", "nbins"}, behavior = PURE)
-public abstract class Tabulate extends RBuiltinNode {
+public abstract class Tabulate extends RBuiltinNode.Arg2 {
 
     private final LoopConditionProfile loopProfile = LoopConditionProfile.createCountingProfile();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java
index 022c03adde..c707b09584 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 
 @RBuiltin(name = "tempdir", kind = INTERNAL, parameterNames = {}, behavior = RBehavior.READS_STATE)
-public abstract class TempDir extends RBuiltinNode {
+public abstract class TempDir extends RBuiltinNode.Arg0 {
 
     @Specialization
     protected Object tempdir() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
index 6140aefe45..20632a8ef9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempFile.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "tempfile", kind = INTERNAL, parameterNames = {"pattern", "tempdir", "fileext"}, behavior = COMPLEX)
-public abstract class TempFile extends RBuiltinNode {
+public abstract class TempFile extends RBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(TempFile.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java
index 92d3eb1c98..7078e5bb37 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ToLowerOrUpper.java
@@ -90,7 +90,7 @@ public abstract class ToLowerOrUpper {
     }
 
     @RBuiltin(name = "tolower", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class ToLower extends RBuiltinNode {
+    public abstract static class ToLower extends RBuiltinNode.Arg1 {
 
         @Child private StringMapNode mapNode = StringMapNode.create();
 
@@ -116,7 +116,7 @@ public abstract class ToLowerOrUpper {
     }
 
     @RBuiltin(name = "toupper", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class ToUpper extends RBuiltinNode {
+    public abstract static class ToUpper extends RBuiltinNode.Arg1 {
 
         @Child private StringMapNode mapNode = StringMapNode.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
index 13ee96c682..653e415b77 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
@@ -43,6 +43,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen;
 import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling;
@@ -65,15 +66,15 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public class TraceFunctions {
 
-    private abstract static class PrimTraceAdapter extends RBuiltinNode {
-        @Child private GetFunctions.Get getNode;
+    protected static Casts createCasts(Class<? extends RBuiltinNode> extCls) {
+        Casts casts = new Casts(extCls);
+        casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(),
+                        chain(asStringVector()).with(findFirst().stringElement()).end());
+        return casts;
+    }
 
-        protected static Casts createCasts(Class<? extends PrimTraceAdapter> extCls) {
-            Casts casts = new Casts(extCls);
-            casts.arg("what").mustBe(instanceOf(RFunction.class).or(stringValue()), Message.ARG_MUST_BE_FUNCTION).mapIf(stringValue(),
-                            chain(asStringVector()).with(findFirst().stringElement()).end());
-            return casts;
-        }
+    private abstract static class PrimTraceAdapter extends RBuiltinNode.Arg1 {
+        @Child private GetFunctions.Get getNode;
 
         protected Object getFunction(VirtualFrame frame, String funcName) {
             if (getNode == null) {
@@ -118,7 +119,7 @@ public class TraceFunctions {
             createCasts(PrimUnTrace.class);
         }
 
-        public abstract void execute(VirtualFrame frame, RFunction func);
+        public abstract Object execute(VirtualFrame frame, RFunction func);
 
         @Specialization
         protected RNull primUnTrace(VirtualFrame frame, RAbstractStringVector funcName) {
@@ -137,7 +138,7 @@ public class TraceFunctions {
     }
 
     @RBuiltin(name = "traceOnOff", kind = INTERNAL, parameterNames = "state", behavior = COMPLEX)
-    public abstract static class TraceOnOff extends RBuiltinNode {
+    public abstract static class TraceOnOff extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(TraceOnOff.class);
@@ -163,68 +164,66 @@ public class TraceFunctions {
         }
     }
 
-    public abstract static class TracememBase extends RBuiltinNode {
-        static {
-            MemoryCopyTracer.addListener(new TracememBase.TracememListener());
-        }
+    static {
+        MemoryCopyTracer.addListener(new TracememListener());
+    }
 
-        @TruffleBoundary
-        protected static HashSet<Object> getTracedObjects() {
-            return RContext.getInstance().getInstrumentationState().getTracemem().getTracedObjects();
-        }
+    @TruffleBoundary
+    protected static HashSet<Object> getTracedObjects() {
+        return RContext.getInstance().getInstrumentationState().getTracemem().getTracedObjects();
+    }
 
-        @TruffleBoundary
-        protected static String formatHashCode(Object x) {
-            return String.format("<0x%x>", x.hashCode());
-        }
+    @TruffleBoundary
+    protected static String formatHashCode(Object x) {
+        return String.format("<0x%x>", x.hashCode());
+    }
 
-        @TruffleBoundary
-        protected static void startTracing(Object x) {
-            /*
-             * There is no explicit command to enable tracing, it is implicit in the call to
-             * tracemem. However, it can be disabled by tracingState(F), so we can't unilaterally
-             * turn on tracing here.
-             */
-            getTracedObjects().add(x);
-            boolean tracingState = RContext.getInstance().stateInstrumentation.getTracingState();
-            if (tracingState) {
-                MemoryCopyTracer.setTracingState(true);
-            }
+    @TruffleBoundary
+    protected static void startTracing(Object x) {
+        /*
+         * There is no explicit command to enable tracing, it is implicit in the call to tracemem.
+         * However, it can be disabled by tracingState(F), so we can't unilaterally turn on tracing
+         * here.
+         */
+        getTracedObjects().add(x);
+        boolean tracingState = RContext.getInstance().stateInstrumentation.getTracingState();
+        if (tracingState) {
+            MemoryCopyTracer.setTracingState(true);
         }
+    }
 
-        @TruffleBoundary
-        protected static void printToStdout(String msg) {
-            try {
-                StdConnections.getStdout().writeString(msg, true);
-            } catch (IOException ex) {
-                throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, ex.getMessage());
-            }
+    @TruffleBoundary
+    protected static void printToStdout(String msg) {
+        try {
+            StdConnections.getStdout().writeString(msg, true);
+        } catch (IOException ex) {
+            throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, ex.getMessage());
         }
+    }
 
-        @TruffleBoundary
-        protected static String getStackTrace() {
-            final StringBuffer result = new StringBuffer();
-            Truffle.getRuntime().iterateFrames(frame -> {
-                Frame unwrapped = RArguments.unwrap(frame.getFrame(FrameAccess.READ_ONLY));
-                if (RArguments.isRFrame(unwrapped)) {
-                    RCaller call = RArguments.getCall(unwrapped);
-                    if (call != null && call.isValidCaller()) {
-                        result.append(RContext.getRRuntimeASTAccess().getCallerSource(call));
-                        result.append(' ');
-                    }
+    @TruffleBoundary
+    protected static String getStackTrace() {
+        final StringBuffer result = new StringBuffer();
+        Truffle.getRuntime().iterateFrames(frame -> {
+            Frame unwrapped = RArguments.unwrap(frame.getFrame(FrameAccess.READ_ONLY));
+            if (RArguments.isRFrame(unwrapped)) {
+                RCaller call = RArguments.getCall(unwrapped);
+                if (call != null && call.isValidCaller()) {
+                    result.append(RContext.getRRuntimeASTAccess().getCallerSource(call));
+                    result.append(' ');
                 }
-                return null;
-            });
-            return result.toString();
-        }
+            }
+            return null;
+        });
+        return result.toString();
+    }
 
-        private static final class TracememListener implements MemoryCopyTracer.Listener {
-            @TruffleBoundary
-            @Override
-            public void reportCopying(RAbstractVector src, RAbstractVector dest) {
-                if (getTracedObjects().contains(src)) {
-                    printToStdout(String.format("tracemem[0x%x -> 0x%x]: %s", src.hashCode(), dest.hashCode(), getStackTrace()));
-                }
+    private static final class TracememListener implements MemoryCopyTracer.Listener {
+        @TruffleBoundary
+        @Override
+        public void reportCopying(RAbstractVector src, RAbstractVector dest) {
+            if (getTracedObjects().contains(src)) {
+                printToStdout(String.format("tracemem[0x%x -> 0x%x]: %s", src.hashCode(), dest.hashCode(), getStackTrace()));
             }
         }
     }
@@ -235,7 +234,7 @@ public class TraceFunctions {
      * temporary vector wrappers cannot be traced however.
      */
     @RBuiltin(name = "tracemem", kind = PRIMITIVE, parameterNames = "x", behavior = COMPLEX)
-    public abstract static class Tracemem extends TracememBase {
+    public abstract static class Tracemem extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Tracemem.class);
@@ -255,7 +254,7 @@ public class TraceFunctions {
      * unclear meaning.
      */
     @RBuiltin(name = "retracemem", kind = PRIMITIVE, visibility = CUSTOM, parameterNames = {"x", "previous"}, behavior = COMPLEX)
-    public abstract static class Retracemem extends TracememBase {
+    public abstract static class Retracemem extends RBuiltinNode.Arg2 {
 
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
@@ -297,7 +296,7 @@ public class TraceFunctions {
     }
 
     @RBuiltin(name = "untracemem", kind = PRIMITIVE, visibility = OFF, parameterNames = "x", behavior = COMPLEX)
-    public abstract static class Untracemem extends TracememBase {
+    public abstract static class Untracemem extends RBuiltinNode.Arg1 {
 
         static {
             Casts.noCasts(Untracemem.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java
index 4c75e21ae3..898c15fa68 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Traceback.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "traceback", kind = INTERNAL, parameterNames = {"x"}, behavior = COMPLEX)
-public abstract class Traceback extends RBuiltinNode {
+public abstract class Traceback extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Traceback.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index b75bd4453b..db4fa2a7fa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @RBuiltin(name = "t.default", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class Transpose extends RBuiltinNode {
+public abstract class Transpose extends RBuiltinNode.Arg1 {
 
     private final BranchProfile hasDimNamesProfile = BranchProfile.create();
     private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index e310690641..b7b963b1e9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -489,7 +489,7 @@ public class TrigExpFunctions {
      * the {@code int} forms to {@code double}.
      */
     @RBuiltin(name = "atan2", kind = INTERNAL, parameterNames = {"y", "x"}, behavior = PURE)
-    public abstract static class Atan2 extends RBuiltinNode {
+    public abstract static class Atan2 extends RBuiltinNode.Arg2 {
 
         private final NACheck yNACheck = NACheck.create();
         private final NACheck xNACheck = NACheck.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
index 759597b4bc..6f499ded2d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
 @RBuiltin(name = "trunc", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class Trunc extends RBuiltinNode {
+public abstract class Trunc extends RBuiltinNode.Arg1 {
 
     private static final UnaryArithmeticFactory TRUNC = TruncArithmetic::new;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
index 1366ac09fa..4a694e99a5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Typeof.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "typeof", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class Typeof extends RBuiltinNode {
+public abstract class Typeof extends RBuiltinNode.Arg1 {
 
     @Child private TypeofNode typeofNode = TypeofNodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
index 8090c363c0..54fcb5fded 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "unclass", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class UnClass extends RBuiltinNode {
+public abstract class UnClass extends RBuiltinNode.Arg1 {
     private final BranchProfile objectProfile = BranchProfile.create();
     private final BranchProfile shareableProfile = BranchProfile.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
index 8898ee1611..3ef308f8b1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
@@ -65,7 +65,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 // TODO A more efficient implementation is in order; GNU R uses hash tables so perhaps we should
 // consider using one of the existing libraries that offer hash table implementations for primitive
 // types
-public abstract class Unique extends RBuiltinNode {
+public abstract class Unique extends RBuiltinNode.Arg4 {
 
     private static final long BIG_THRESHOLD = 100;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
index 5bb9e1786c..aeee8fa4fe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "unlist", kind = INTERNAL, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE)
-public abstract class Unlist extends RBuiltinNode {
+public abstract class Unlist extends RBuiltinNode.Arg3 {
 
     // portions of the algorithm were transcribed from GNU R
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index 9cbeac74df..1487aa333f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -60,7 +60,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "attr<-", kind = PRIMITIVE, parameterNames = {"x", "which", "value"}, behavior = PURE)
-public abstract class UpdateAttr extends RBuiltinNode {
+public abstract class UpdateAttr extends RBuiltinNode.Arg3 {
 
     @Child private UpdateNames updateNames;
     @Child private UpdateDimNames updateDimNames;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 7bcf40f60e..70631ae526 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -59,7 +59,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "attributes<-", kind = PRIMITIVE, parameterNames = {"obj", "value"}, behavior = PURE)
-public abstract class UpdateAttributes extends RBuiltinNode {
+public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
     private final ConditionProfile numAttributesProfile = ConditionProfile.createBinaryProfile();
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index b579cd587c..b32345f7ff 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "class<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE)
-public abstract class UpdateClass extends RBuiltinNode {
+public abstract class UpdateClass extends RBuiltinNode.Arg2 {
 
     protected static final int CACHE_LIMIT = 2;
 
@@ -203,7 +203,7 @@ public abstract class UpdateClass extends RBuiltinNode {
     private void initCastTypeNode() {
         if (castTypeNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castTypeNode = insert(CastTypeNodeGen.create(null, null));
+            castTypeNode = insert(CastTypeNodeGen.create());
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
index c59b1b8d54..3e3c60210e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "dim<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE)
-public abstract class UpdateDim extends RBuiltinNode {
+public abstract class UpdateDim extends RBuiltinNode.Arg2 {
 
     @Child private ReuseNonSharedNode reuse = ReuseNonSharedNode.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index edaea94aab..d4b65ff604 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "dimnames<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateDimNames extends RBuiltinNode {
+public abstract class UpdateDimNames extends RBuiltinNode.Arg2 {
 
     protected static final String DIMNAMES_ATTR_KEY = RRuntime.DIMNAMES_ATTR_KEY;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
index 38199269d7..74ada40821 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
 @RBuiltin(name = "length<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateLength extends RBuiltinNode {
+public abstract class UpdateLength extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(UpdateLength.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
index 95f8752c97..3083e952de 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java
@@ -28,7 +28,7 @@ import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "levels<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateLevels extends RBuiltinNode {
+public abstract class UpdateLevels extends RBuiltinNode.Arg2 {
 
     static {
         Casts casts = new Casts(UpdateLevels.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
index d1ab1ea7f0..c58e054d13 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java
@@ -43,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 @RBuiltin(name = "names<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateNames extends RBuiltinNode {
+public abstract class UpdateNames extends RBuiltinNode.Arg2 {
 
     @Child private CastStringNode castStringNode;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index c0286bb860..d766b5077c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 // oldClass<- (as opposed to class<-), simply sets the attribute (without handling "implicit" attributes)
 @RBuiltin(name = "oldClass<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE)
-public abstract class UpdateOldClass extends RBuiltinNode {
+public abstract class UpdateOldClass extends RBuiltinNode.Arg2 {
 
     @Child private CastStringNode castStringNode;
     @Child private SetClassAttributeNode setClassAttributeNode = SetClassAttributeNode.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
index 684d9ce1e7..560b5fc442 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
@@ -45,7 +45,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "@<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, nonEvalArgs = 1, behavior = COMPLEX)
-public abstract class UpdateSlot extends RBuiltinNode {
+public abstract class UpdateSlot extends RBuiltinNode.Arg3 {
 
     @Child private UpdateSlotNode updateSlotNode = com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
index 0b45cc5ea9..c33d4ddb01 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
 @RBuiltin(name = "storage.mode<-", kind = PRIMITIVE, parameterNames = {"x", "value"}, behavior = PURE)
-public abstract class UpdateStorageMode extends RBuiltinNode {
+public abstract class UpdateStorageMode extends RBuiltinNode.Arg2 {
 
     @Child private TypeFromModeNode typeFromMode = TypeFromModeNodeGen.create();
     @Child private TypeofNode typeof;
@@ -109,7 +109,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode {
     private void initCastTypeNode() {
         if (castTypeNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castTypeNode = insert(CastTypeNodeGen.create(null, null));
+            castTypeNode = insert(CastTypeNodeGen.create());
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
index 21a620a4a8..42273c3a74 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSubstr.java
@@ -45,7 +45,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 @RBuiltin(name = "substr<-", kind = INTERNAL, parameterNames = {"x", "start", "stop", "value"}, behavior = PURE)
-public abstract class UpdateSubstr extends RBuiltinNode {
+public abstract class UpdateSubstr extends RBuiltinNode.Arg4 {
 
     private final NACheck na = NACheck.create();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
index 52001186a8..ae78e0c4be 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Utf8ToInt.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "utf8ToInt", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-public abstract class Utf8ToInt extends RBuiltinNode {
+public abstract class Utf8ToInt extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(Utf8ToInt.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index 48fae23d07..f7ca2e99fb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -79,7 +79,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * TODO Set dimnames on result if necessary.
  */
 @RBuiltin(name = "vapply", kind = INTERNAL, parameterNames = {"X", "FUN", "FUN.VALUE", "USE.NAMES"}, splitCaller = true, behavior = COMPLEX)
-public abstract class VApply extends RBuiltinNode {
+public abstract class VApply extends RBuiltinNode.Arg4 {
 
     private final ConditionProfile useNamesProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile dimsProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
index 001e65fd2c..cb883dd4d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Vector.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 
 @RBuiltin(name = "vector", kind = INTERNAL, parameterNames = {"mode", "length"}, behavior = PURE)
-public abstract class Vector extends RBuiltinNode {
+public abstract class Vector extends RBuiltinNode.Arg2 {
 
     private static final String CACHED_MODES_LIMIT = "3";
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
index 164019046f..fa420e5b0a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Warning.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "warning", visibility = OFF, kind = INTERNAL, parameterNames = {"call", "immediate", "nobreaks", "message"}, behavior = COMPLEX)
-public abstract class Warning extends RBuiltinNode {
+public abstract class Warning extends RBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(Warning.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
index 2345f49d0f..25a8810a9e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WhichFunctions.java
@@ -51,7 +51,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 public class WhichFunctions {
 
     @RBuiltin(name = "which", kind = INTERNAL, parameterNames = {"x"}, behavior = PURE)
-    public abstract static class Which extends RBuiltinNode {
+    public abstract static class Which extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Which.class);
@@ -102,7 +102,7 @@ public class WhichFunctions {
         }
     }
 
-    public abstract static class WhichMinMax extends RBuiltinNode {
+    public abstract static class WhichMinMax extends RBuiltinNode.Arg1 {
 
         private final boolean isMax;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
index 87accb1d72..6f2f5ce21b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/WithVisible.java
@@ -67,7 +67,7 @@ final class WithVisibleSpecial extends RNode {
 // gets the wrong result. I believe that the only way to handle it as a .Internal would be to
 // set noEvalArgs and evaluate the argument here and set the visibility explicitly.
 @RBuiltin(name = "withVisible", kind = PRIMITIVE, parameterNames = "x", behavior = COMPLEX, nonEvalArgs = {0})
-public abstract class WithVisible extends RBuiltinNode {
+public abstract class WithVisible extends RBuiltinNode.Arg1 {
 
     static final RStringVector LISTNAMES = (RStringVector) RDataFactory.createStringVector(new String[]{"value", "visible"}, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java
index 7d2c7fdfc6..abac7f57b8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Xtfrm.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "xtfrm", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
-public abstract class Xtfrm extends RBuiltinNode {
+public abstract class Xtfrm extends RBuiltinNode.Arg1 {
 
     @Child private GetFunctions.Get getNode;
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index b7bee9a581..a498b2d75c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -200,10 +200,6 @@ public class CallAndExternalFunctions {
         return list;
     }
 
-    abstract static class CallRFFIAdapter extends LookupAdapter {
-        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
-    }
-
     /**
      * Handles the generic case, but also many special case functions that are called from the
      * default packages.
@@ -221,7 +217,9 @@ public class CallAndExternalFunctions {
      * could be invoked by a string but experimentally that situation has never been encountered.
      */
     @RBuiltin(name = ".Call", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
-    public abstract static class DotCall extends CallRFFIAdapter {
+    public abstract static class DotCall extends LookupAdapter {
+
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotCall.class);
@@ -234,7 +232,7 @@ public class CallAndExternalFunctions {
 
         @Override
         @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
+        public RExternalBuiltinNode lookupBuiltin(RList symbol) {
             String name = lookupName(symbol);
             if (FastROptions.UseInternalGridGraphics.getBooleanValue() && name != null) {
                 RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotCall(name);
@@ -656,7 +654,7 @@ public class CallAndExternalFunctions {
         protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
                         @Cached("symbol") RList cached,
                         @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin,
-                        @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) {
+                        @Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) {
             return callRFFINode.execute(nativeCallInfo, args.getArguments());
         }
 
@@ -671,7 +669,7 @@ public class CallAndExternalFunctions {
             if (builtin != null) {
                 throw RInternalError.shouldNotReachHere("Cache for .Calls with FastR reimplementation (lookupBuiltin(...) != null) exceeded the limit");
             }
-            NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
+            NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
             return callRFFINode.execute(nativeCallInfo, args.getArguments());
         }
 
@@ -703,7 +701,7 @@ public class CallAndExternalFunctions {
         @SuppressWarnings("unused")
         @Fallback
         protected Object dotCallFallback(Object symbol, Object args, Object packageName) {
-            throw fallback(symbol);
+            throw fallback(this, symbol);
         }
     }
 
@@ -712,7 +710,9 @@ public class CallAndExternalFunctions {
      * {@link DotCall}.
      */
     @RBuiltin(name = ".External", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
-    public abstract static class DotExternal extends CallRFFIAdapter {
+    public abstract static class DotExternal extends LookupAdapter {
+
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotExternal.class);
@@ -720,7 +720,7 @@ public class CallAndExternalFunctions {
 
         @Override
         @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList f) {
+        public RExternalBuiltinNode lookupBuiltin(RList f) {
             String name = lookupName(f);
             if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
                 RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotExternal(name);
@@ -780,7 +780,7 @@ public class CallAndExternalFunctions {
         @Specialization(limit = "1", guards = {"cached == symbol"})
         protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
                         @Cached("symbol") RList cached,
-                        @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) {
+                        @Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) {
             Object list = encodeArgumentPairList(args, nativeCallInfo.name);
             return callRFFINode.execute(nativeCallInfo, new Object[]{list});
         }
@@ -806,12 +806,12 @@ public class CallAndExternalFunctions {
 
         @Fallback
         protected Object fallback(Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) {
-            throw fallback(f);
+            throw fallback(this, f);
         }
     }
 
     @RBuiltin(name = ".External2", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
-    public abstract static class DotExternal2 extends CallRFFIAdapter {
+    public abstract static class DotExternal2 extends LookupAdapter {
         private static final Object CALL = "call";
         private static final Object RHO = "rho";
         /**
@@ -824,6 +824,8 @@ public class CallAndExternalFunctions {
          */
         @CompilationFinal private static Object op = null;
 
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+
         static {
             Casts.noCasts(DotExternal2.class);
         }
@@ -838,7 +840,7 @@ public class CallAndExternalFunctions {
 
         @Override
         @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
+        public RExternalBuiltinNode lookupBuiltin(RList symbol) {
             String name = lookupName(symbol);
             if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
                 RExternalBuiltinNode gridExternal = FastRGridExternalLookup.lookupDotExternal2(name);
@@ -874,7 +876,7 @@ public class CallAndExternalFunctions {
         @Specialization(limit = "1", guards = {"cached == symbol"})
         protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
                         @Cached("symbol") RList cached,
-                        @Cached("extractSymbolInfo(frame, symbol)") NativeCallInfo nativeCallInfo) {
+                        @Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) {
             Object list = encodeArgumentPairList(args, nativeCallInfo.name);
             return callRFFINode.execute(nativeCallInfo, new Object[]{CALL, getOp(), list, RHO});
         }
@@ -900,12 +902,14 @@ public class CallAndExternalFunctions {
 
         @Fallback
         protected Object fallback(Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) {
-            throw fallback(f);
+            throw fallback(this, f);
         }
     }
 
     @RBuiltin(name = ".External.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
-    public abstract static class DotExternalGraphics extends CallRFFIAdapter {
+    public abstract static class DotExternalGraphics extends LookupAdapter {
+
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotExternalGraphics.class);
@@ -913,7 +917,7 @@ public class CallAndExternalFunctions {
 
         @Override
         @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList f) {
+        public RExternalBuiltinNode lookupBuiltin(RList f) {
             return null;
         }
 
@@ -927,7 +931,7 @@ public class CallAndExternalFunctions {
 
         @Specialization
         protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) {
-            NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
+            NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
             Object list = encodeArgumentPairList(args, nativeCallInfo.name);
             return callRFFINode.execute(nativeCallInfo, new Object[]{list});
         }
@@ -952,12 +956,14 @@ public class CallAndExternalFunctions {
 
         @Fallback
         protected Object fallback(Object f, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) {
-            throw fallback(f);
+            throw fallback(this, f);
         }
     }
 
     @RBuiltin(name = ".Call.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
-    public abstract static class DotCallGraphics extends CallRFFIAdapter {
+    public abstract static class DotCallGraphics extends LookupAdapter {
+
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotCallGraphics.class);
@@ -970,7 +976,7 @@ public class CallAndExternalFunctions {
 
         @Override
         @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList f) {
+        public RExternalBuiltinNode lookupBuiltin(RList f) {
             switch (lookupName(f)) {
                 default:
                     return null;
@@ -987,7 +993,7 @@ public class CallAndExternalFunctions {
 
         @Specialization
         protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) {
-            NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
+            NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
             return callRFFINode.execute(nativeCallInfo, args.getArguments());
         }
 
@@ -1011,7 +1017,7 @@ public class CallAndExternalFunctions {
 
         @Fallback
         protected Object dotCallFallback(Object fobj, @SuppressWarnings("unused") Object args, @SuppressWarnings("unused") Object packageName) {
-            throw fallback(fobj);
+            throw fallback(this, fobj);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
index 1bdbad5326..afdff5f5bc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
@@ -22,9 +22,10 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapter.ExtractNativeCallInfoNode;
+import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapterFactory.ExtractNativeCallInfoNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -51,7 +52,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
  */
 public class FortranAndCFunctions {
 
-    protected abstract static class CRFFIAdapter extends LookupAdapter {
+    protected abstract static class CRFFIAdapter extends RBuiltinNode.Arg6 {
         private static final int SCALAR_DOUBLE = 0;
         private static final int SCALAR_INT = 1;
         private static final int SCALAR_LOGICAL = 2;
@@ -61,6 +62,7 @@ public class FortranAndCFunctions {
         private static final int VECTOR_LOGICAL = 12;
         @SuppressWarnings("unused") private static final int VECTOR_STRING = 12;
 
+        @Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create();
         @Child private CRFFI.InvokeCNode invokeCNode = RFFIFactory.getRFFI().getCRFFI().createInvokeCNode();
 
         @Override
@@ -189,7 +191,7 @@ public class FortranAndCFunctions {
      * FastR, otherwise the .Fortran interface uses the machinery that implements the .C interface.
      */
     @RBuiltin(name = ".Fortran", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX)
-    public abstract static class Fortran extends CRFFIAdapter {
+    public abstract static class Fortran extends CRFFIAdapter implements Lookup {
 
         static {
             Casts.noCasts(Fortran.class);
@@ -197,8 +199,8 @@ public class FortranAndCFunctions {
 
         @Override
         @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
-            switch (lookupName(symbol)) {
+        public RExternalBuiltinNode lookupBuiltin(RList symbol) {
+            switch (LookupAdapter.lookupName(symbol)) {
                 case "dqrdc2":
                     return Dqrdc2.create();
                 case "dqrcf":
@@ -219,14 +221,14 @@ public class FortranAndCFunctions {
         @Specialization(guards = "lookupBuiltin(symbol) == null")
         protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage,
                         @SuppressWarnings("unused") RMissing encoding) {
-            NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
+            NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
             return dispatch(this, nativeCallInfo, naok, dup, args);
         }
 
         @Specialization
         protected RList c(RAbstractStringVector symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, @SuppressWarnings("unused") RMissing encoding,
                         @Cached("create()") DLL.RFindSymbolNode findSymbolNode) {
-            String libName = checkPackageArg(rPackage);
+            String libName = LookupAdapter.checkPackageArg(rPackage);
             DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Fortran, null, null);
             DLL.SymbolHandle func = findSymbolNode.execute(symbol.getDataAt(0), libName, rns);
             if (func == DLL.SYMBOL_NOT_FOUND) {
@@ -238,7 +240,7 @@ public class FortranAndCFunctions {
         @SuppressWarnings("unused")
         @Fallback
         protected Object fallback(Object symbol, Object args, Object naok, Object dup, Object rPackage, Object encoding) {
-            throw fallback(symbol);
+            throw LookupAdapter.fallback(this, symbol);
         }
     }
 
@@ -249,15 +251,9 @@ public class FortranAndCFunctions {
             Casts.noCasts(DotC.class);
         }
 
-        @Override
-        @TruffleBoundary
-        protected RExternalBuiltinNode lookupBuiltin(RList symbol) {
-            throw RInternalError.shouldNotReachHere();
-        }
-
         @Specialization
         protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding) {
-            NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol);
+            NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
             return dispatch(this, nativeCallInfo, naok, dup, args);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index 31f230f522..49bcba7882 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -50,6 +50,11 @@ import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+interface Lookup {
+    RExternalBuiltinNode lookupBuiltin(RList symbol);
+}
 
 /**
  * Locator for "builtin" package function implementations. The "builtin" packages contain many
@@ -58,8 +63,8 @@ import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
  * symbol, created when the package is loaded and stored in the namespace environment of the
  * package, that is a list-valued object. Evidently these "builtins" are somewhat similar to the
  * {@code .Primitive} and {@code .Internal} builtins and, similarly, most of these are
- * re-implemented in Java in FastR. The {@link #lookupBuiltin(RList)} method checks the name in the
- * list object and returns the {@link RExternalBuiltinNode} that implements the function, or
+ * re-implemented in Java in FastR. The {@link Lookup#lookupBuiltin(RList)} method checks the name
+ * in the list object and returns the {@link RExternalBuiltinNode} that implements the function, or
  * {@code null}. A {@code null} result implies that the builtin is not implemented in Java, but
  * called directly via the FFI interface, which is only possible for functions that use the FFI in a
  * way that FastR can handle.
@@ -67,8 +72,8 @@ import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
  * This class also handles the "lookup" of the {@link NativeCallInfo} data for builtins that are
  * still implemented by native code.
  */
-abstract class LookupAdapter extends RBuiltinNode {
-    @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create();
+abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup {
+    @Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create();
 
     protected static class UnimplementedExternal extends RExternalBuiltinNode {
         private final String name;
@@ -87,11 +92,9 @@ abstract class LookupAdapter extends RBuiltinNode {
         }
     }
 
-    protected abstract RExternalBuiltinNode lookupBuiltin(RList symbol);
-
     private static final String UNKNOWN_EXTERNAL_BUILTIN = "UNKNOWN_EXTERNAL_BUILTIN";
 
-    protected static String lookupName(RList symbol) {
+    public static String lookupName(RList symbol) {
         CompilerAsserts.neverPartOfCompilation();
         if (symbol.getNames() != null) {
             RAbstractStringVector names = symbol.getNames();
@@ -106,32 +109,28 @@ abstract class LookupAdapter extends RBuiltinNode {
     }
 
     @TruffleBoundary
-    protected RuntimeException fallback(Object symbol) {
+    protected static RuntimeException fallback(Lookup lookup, Object symbol) {
         String name = null;
         if (symbol instanceof RList) {
             name = lookupName((RList) symbol);
             name = name == UNKNOWN_EXTERNAL_BUILTIN ? null : name;
-            if (name != null && lookupBuiltin((RList) symbol) != null) {
+            if (name != null && lookup.lookupBuiltin((RList) symbol) != null) {
                 /*
                  * if we reach this point, then the cache saw a different value for f. the lists
                  * that contain the information about native calls are never expected to change.
                  */
-                throw RInternalError.shouldNotReachHere("fallback reached for " + getRBuiltin().name() + " " + name);
+                throw RInternalError.shouldNotReachHere("fallback reached for " + lookup + " " + name);
             }
         }
-        throw RError.nyi(this, getRBuiltin().name() + " specialization failure: " + (name == null ? "<unknown>" : name));
-    }
-
-    protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) {
-        return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol);
+        throw RError.nyi((RBaseNode) lookup, lookup + " specialization failure: " + (name == null ? "<unknown>" : name));
     }
 
-    protected String checkPackageArg(Object rPackage) {
+    public static String checkPackageArg(Object rPackage) {
         String libName = null;
         if (!(rPackage instanceof RMissing)) {
             libName = RRuntime.asString(rPackage);
             if (libName == null) {
-                throw error(RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
+                throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MUST_BE_STRING, "PACKAGE");
             }
         }
         return libName;
@@ -147,10 +146,10 @@ abstract class LookupAdapter extends RBuiltinNode {
         @Child private ExtractVectorNode packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
         @Child private ExtractVectorNode infoExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-        protected abstract Object execute(VirtualFrame frame, RList symbol);
+        protected abstract NativeCallInfo execute(VirtualFrame frame, RList symbol);
 
         @Specialization
-        protected Object extractNativeCallInfo(VirtualFrame frame, RList symbol) {
+        protected NativeCallInfo extractNativeCallInfo(VirtualFrame frame, RList symbol) {
             if (nameExtract == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 nameExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
index c1677176ce..f1c99a37f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
@@ -83,7 +83,7 @@ abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
 }
 
 @RBuiltin(name = "$", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class AccessField extends RBuiltinNode {
+public abstract class AccessField extends RBuiltinNode.Arg2 {
 
     @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java
index 0a795bc055..90d1260e9a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltin.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBehavior;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME)
-public abstract class AssignBuiltin extends RBuiltinNode {
+public abstract class AssignBuiltin extends RBuiltinNode.Arg2 {
 
     static {
         Casts.noCasts(AssignBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java
index bf68624ef5..f35dc6cff1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignBuiltinEq.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.builtins.RBehavior;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "=", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = RBehavior.MODIFIES_FRAME)
-public abstract class AssignBuiltinEq extends RBuiltinNode {
+public abstract class AssignBuiltinEq extends RBuiltinNode.Arg2 {
 
     static {
         Casts.noCasts(AssignBuiltinEq.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java
index 3ef3d4676c..35ccfe7cc3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AssignOuterBuiltin.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.RVisibility;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "<<-", visibility = RVisibility.OFF, kind = PRIMITIVE, parameterNames = {"x", "i"}, behavior = COMPLEX)
-public abstract class AssignOuterBuiltin extends RBuiltinNode {
+public abstract class AssignOuterBuiltin extends RBuiltinNode.Arg2 {
 
     static {
         Casts.noCasts(AssignOuterBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java
index 67c223259e..2db00345ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BraceBuiltin.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "{", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class BraceBuiltin extends RBuiltinNode {
+public abstract class BraceBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         noCasts(BraceBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java
index e1aab99445..aeea494ef8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/BreakBuiltin.java
@@ -31,7 +31,8 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "break", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
-public abstract class BreakBuiltin extends RBuiltinNode {
+public abstract class BreakBuiltin extends RBuiltinNode.Arg1 {
+
     static {
         Casts.noCasts(BreakBuiltin.class);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java
index cbb0e5ae48..c9309ab870 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ForBuiltin.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "for", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class ForBuiltin extends RBuiltinNode {
+public abstract class ForBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(ForBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
index c81176d2e3..3909ffbb92 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "function", kind = PRIMITIVE, parameterNames = {"x"}, behavior = READS_FRAME)
-public abstract class FunctionBuiltin extends RBuiltinNode {
+public abstract class FunctionBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(FunctionBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java
index 9920963799..0865d2a4e8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/IfBuiltin.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "if", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class IfBuiltin extends RBuiltinNode {
+public abstract class IfBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(IfBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java
index 16830767a1..0fc3d41274 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/NextBuiltin.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "next", kind = PRIMITIVE, parameterNames = {"x"}, behavior = COMPLEX)
-public abstract class NextBuiltin extends RBuiltinNode {
+public abstract class NextBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         noCasts(NextBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
index 08d6f1a624..dd90c743d3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ParenBuiltin.java
@@ -50,7 +50,7 @@ final class ParensSpecial extends RNode {
 }
 
 @RBuiltin(name = "(", kind = PRIMITIVE, parameterNames = {""}, visibility = ON, behavior = PURE)
-public final class ParenBuiltin extends RBuiltinNode {
+public final class ParenBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(ParenBuiltin.class);
@@ -64,7 +64,7 @@ public final class ParenBuiltin extends RBuiltinNode {
     }
 
     @Override
-    public Object executeBuiltin(VirtualFrame frame, Object... args) {
-        return args[0];
+    public Object execute(VirtualFrame frame, Object arg) {
+        return arg;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java
index 46239fcbf5..73ea958d48 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/RepeatBuiltin.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "repeat", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class RepeatBuiltin extends RBuiltinNode {
+public abstract class RepeatBuiltin extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(RepeatBuiltin.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index daf9a1dac7..6a4401c32b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -185,7 +185,7 @@ abstract class SubscriptSpecial2 extends SubscriptSpecial2Base {
 
 @RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 @TypeSystemReference(RTypes.class)
-public abstract class Subscript extends RBuiltinNode {
+public abstract class Subscript extends RBuiltinNode.Arg4 {
 
     @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE)
     public abstract class DefaultBuiltin {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index 0042a04609..18cafe6488 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
@@ -109,7 +109,7 @@ abstract class SubsetSpecial2 extends SubscriptSpecial2Base {
 }
 
 @RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class Subset extends RBuiltinNode {
+public abstract class Subset extends RBuiltinNode.Arg3 {
 
     @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE)
     public abstract class DefaultBuiltin {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
index 474cd495bb..14828d57c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java
@@ -48,7 +48,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * argument is missing, i.e. {@code ~ x} result in {@code `~`(x)}.
  */
 @RBuiltin(name = "~", kind = PRIMITIVE, parameterNames = {"x", "y"}, nonEvalArgs = {0, 1}, behavior = READS_FRAME)
-public abstract class Tilde extends RBuiltinNode {
+public abstract class Tilde extends RBuiltinNode.Arg2 {
 
     private static final RStringVector FORMULA_CLASS = RDataFactory.createStringVectorFromScalar(RRuntime.FORMULA_CLASS);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
index 5d55e54d97..3d1e5f2583 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
@@ -114,7 +114,7 @@ abstract class UpdateFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
 }
 
 @RBuiltin(name = "$<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateField extends RBuiltinNode {
+public abstract class UpdateField extends RBuiltinNode.Arg3 {
 
     @Child private ReplaceVectorNode update = ReplaceVectorNode.create(ElementAccessMode.FIELD_SUBSCRIPT, true);
     @Child private CastListNode castList;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index 3eb7a8278f..e9d5efbbd2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -161,7 +161,7 @@ abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
 }
 
 @RBuiltin(name = "[[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateSubscript extends RBuiltinNode {
+public abstract class UpdateSubscript extends RBuiltinNode.Arg2 {
 
     @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 445e8417ca..450506ba10 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 @RBuiltin(name = "[<-", kind = PRIMITIVE, parameterNames = {"..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
-public abstract class UpdateSubset extends RBuiltinNode {
+public abstract class UpdateSubset extends RBuiltinNode.Arg1 {
 
     @Child private ReplaceVectorNode replaceNode = ReplaceVectorNode.create(ElementAccessMode.SUBSET, false);
     private final ConditionProfile argsLengthLargerThanOneProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java
index 405853e771..680ad83d25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/WhileBuiltin.java
@@ -33,7 +33,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "while", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class WhileBuiltin extends RBuiltinNode {
+public abstract class WhileBuiltin extends RBuiltinNode.Arg1 {
     static {
         noCasts(WhileBuiltin.class);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
index 5d0ab412d0..3fbbfa5090 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/system/SystemFunction.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = "system", visibility = CUSTOM, kind = INTERNAL, parameterNames = {"command", "intern"}, behavior = COMPLEX)
-public abstract class SystemFunction extends RBuiltinNode {
+public abstract class SystemFunction extends RBuiltinNode.Arg2 {
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 097b1660ef..25883797ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -87,7 +87,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.context.get", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE)
-    public abstract static class Get extends RBuiltinNode {
+    public abstract static class Get extends RBuiltinNode.Arg0 {
         @Specialization
         @TruffleBoundary
         protected TruffleObject get() {
@@ -102,7 +102,7 @@ public class FastRContext {
      *
      */
     @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX)
-    public abstract static class Spawn extends RBuiltinNode {
+    public abstract static class Spawn extends RBuiltinNode.Arg3 {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"};
@@ -134,7 +134,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.context.join", visibility = OFF, kind = PRIMITIVE, parameterNames = {"handle"}, behavior = COMPLEX)
-    public abstract static class Join extends RBuiltinNode {
+    public abstract static class Join extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Join.class);
@@ -174,7 +174,7 @@ public class FastRContext {
      * attribute "error" if the evaluation threw an exception, in which case the result will be NA.
      */
     @RBuiltin(name = ".fastr.context.eval", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX)
-    public abstract static class Eval extends RBuiltinNode {
+    public abstract static class Eval extends RBuiltinNode.Arg3 {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"};
@@ -225,7 +225,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.context.r", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX)
-    public abstract static class R extends RBuiltinNode {
+    public abstract static class R extends RBuiltinNode.Arg3 {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{RMissing.instance, RMissing.instance, RRuntime.LOGICAL_FALSE};
@@ -260,7 +260,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.context.rscript", kind = PRIMITIVE, visibility = OFF, parameterNames = {"args", "env", "intern"}, behavior = COMPLEX)
-    public abstract static class Rscript extends RBuiltinNode {
+    public abstract static class Rscript extends RBuiltinNode.Arg3 {
 
         public abstract Object execute(RAbstractStringVector args, RAbstractStringVector env, boolean intern);
 
@@ -294,7 +294,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX)
-    public abstract static class CreateChannel extends RBuiltinNode {
+    public abstract static class CreateChannel extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(CreateChannel.class);
@@ -309,7 +309,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.get", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX)
-    public abstract static class GetChannel extends RBuiltinNode {
+    public abstract static class GetChannel extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(GetChannel.class);
@@ -324,7 +324,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.close", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX)
-    public abstract static class CloseChannel extends RBuiltinNode {
+    public abstract static class CloseChannel extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(CloseChannel.class);
@@ -340,7 +340,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.send", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id", "data"}, behavior = COMPLEX)
-    public abstract static class ChannelSend extends RBuiltinNode {
+    public abstract static class ChannelSend extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(ChannelSend.class);
@@ -356,7 +356,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.receive", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX)
-    public abstract static class ChannelReceive extends RBuiltinNode {
+    public abstract static class ChannelReceive extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(ChannelReceive.class);
@@ -371,7 +371,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.poll", kind = PRIMITIVE, parameterNames = {"id"}, behavior = COMPLEX)
-    public abstract static class ChannelPoll extends RBuiltinNode {
+    public abstract static class ChannelPoll extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(ChannelPoll.class);
@@ -386,7 +386,7 @@ public class FastRContext {
     }
 
     @RBuiltin(name = ".fastr.channel.select", kind = PRIMITIVE, parameterNames = {"ids"}, behavior = COMPLEX)
-    public abstract static class ChannelSelect extends RBuiltinNode {
+    public abstract static class ChannelSelect extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(ChannelSelect.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
index 6c4ea7922d..2ab883be50 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRDebug.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = ".fastr.debug", visibility = OFF, kind = PRIMITIVE, parameterNames = {"values"}, behavior = COMPLEX)
-public abstract class FastRDebug extends RBuiltinNode {
+public abstract class FastRDebug extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(FastRDebug.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java
index 5b76a6ac96..5f3b6b3a2a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRIdentity.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
 @RBuiltin(name = ".fastr.identity", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX)
-public abstract class FastRIdentity extends RBuiltinNode {
+public abstract class FastRIdentity extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(FastRIdentity.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java
index 39cb3d17be..5454bf483e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInspect.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
  * Just a convenient way to inspect values in the Java debugger from the R shell.
  */
 @RBuiltin(name = ".fastr.inspect", visibility = OFF, kind = PRIMITIVE, parameterNames = {"..."}, behavior = COMPLEX)
-public abstract class FastRInspect extends RBuiltinNode {
+public abstract class FastRInspect extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(FastRInspect.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index fcc48d956d..912beabdbf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -73,7 +73,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public class FastRInterop {
 
     @RBuiltin(name = ".fastr.interop.eval", visibility = OFF, kind = PRIMITIVE, parameterNames = {"mimeType", "source"}, behavior = COMPLEX)
-    public abstract static class Eval extends RBuiltinNode {
+    public abstract static class Eval extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(Eval.class);
@@ -113,7 +113,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.evalFile", visibility = OFF, kind = PRIMITIVE, parameterNames = {"path", "mimeType"}, behavior = COMPLEX)
-    public abstract static class EvalFile extends RBuiltinNode {
+    public abstract static class EvalFile extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(EvalFile.class);
@@ -153,7 +153,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX)
-    public abstract static class Export extends RBuiltinNode {
+    public abstract static class Export extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(Export.class);
@@ -185,7 +185,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
-    public abstract static class Import extends RBuiltinNode {
+    public abstract static class Import extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(Import.class);
@@ -204,7 +204,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.hasSize", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
-    public abstract static class HasSize extends RBuiltinNode {
+    public abstract static class HasSize extends RBuiltinNode.Arg1 {
 
         @Child private Node node = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode();
 
@@ -219,7 +219,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.isNull", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
-    public abstract static class IsNull extends RBuiltinNode {
+    public abstract static class IsNull extends RBuiltinNode.Arg1 {
 
         @Child private Node node = com.oracle.truffle.api.interop.Message.IS_NULL.createNode();
 
@@ -234,7 +234,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.isExecutable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
-    public abstract static class IsExecutable extends RBuiltinNode {
+    public abstract static class IsExecutable extends RBuiltinNode.Arg1 {
 
         @Child private Node node = com.oracle.truffle.api.interop.Message.IS_EXECUTABLE.createNode();
 
@@ -249,7 +249,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.interop.toBoolean", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
-    public abstract static class ToBoolean extends RBuiltinNode {
+    public abstract static class ToBoolean extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(ToBoolean.class);
@@ -263,7 +263,7 @@ public class FastRInterop {
     }
 
     @RBuiltin(name = ".fastr.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX)
-    public abstract static class JavaClass extends RBuiltinNode {
+    public abstract static class JavaClass extends RBuiltinNode.Arg1 {
 
         static {
             Casts casts = new Casts(JavaClass.class);
@@ -283,7 +283,7 @@ public class FastRInterop {
 
     @ImportStatic({com.oracle.truffle.api.interop.Message.class, RRuntime.class})
     @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
-    public abstract static class InteropNew extends RBuiltinNode {
+    public abstract static class InteropNew extends RBuiltinNode.Arg2 {
 
         static {
             Casts.noCasts(InteropNew.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
index b0a67b019a..ebb579bb12 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRPkgSource.java
@@ -61,7 +61,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  * {@code Rpkgsource} directory., for use by e.g., a source-level debugger.
  */
 @RBuiltin(name = ".fastr.pkgsource", kind = PRIMITIVE, visibility = OFF, parameterNames = {"pkgs", "verbose"}, behavior = COMPLEX)
-public abstract class FastRPkgSource extends RBuiltinNode {
+public abstract class FastRPkgSource extends RBuiltinNode.Arg2 {
     public static final String PKGSOURCE_PROJECT = "Rpkgsource";
     private static final String SLASH_SWAP = "_slash_";
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java
index a9e8cee05e..b6634b88c3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRRefCountInfo.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.RShareable;
  * for permanent shared
  */
 @RBuiltin(name = ".fastr.refcountinfo", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX)
-public abstract class FastRRefCountInfo extends RBuiltinNode {
+public abstract class FastRRefCountInfo extends RBuiltinNode.Arg1 {
 
     static {
         Casts.noCasts(FastRRefCountInfo.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java
index 4bf687e14f..a4bdf0126e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSlotAssign.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RMissing;
 
 @RBuiltin(name = ".fastr.methods.slotassign", visibility = ON, kind = PRIMITIVE, parameterNames = {"object", "name", "check", "value"}, behavior = COMPLEX)
-public abstract class FastRSlotAssign extends RBuiltinNode {
+public abstract class FastRSlotAssign extends RBuiltinNode.Arg4 {
 
     static {
         Casts casts = new Casts(FastRSlotAssign.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
index f2b4d2b4d5..b7179ade00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = ".fastr.stacktrace", visibility = OFF, kind = PRIMITIVE, parameterNames = {"print.frame.contents"}, behavior = COMPLEX)
-public abstract class FastRStackTrace extends RBuiltinNode {
+public abstract class FastRStackTrace extends RBuiltinNode.Arg1 {
 
     @Override
     public Object[] getDefaultParameterValues() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
index fd22a2f70e..458fa6ebef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
@@ -73,7 +73,7 @@ public class FastRStats {
     }
 
     @RBuiltin(name = ".fastr.prof.attr", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX)
-    public abstract static class FastRProfAttr extends RBuiltinNode implements AttributeTracer.Listener {
+    public abstract static class FastRProfAttr extends RBuiltinNode.Arg2 implements AttributeTracer.Listener {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{"Rprofattr.out", RRuntime.LOGICAL_FALSE};
@@ -158,7 +158,7 @@ public class FastRStats {
     }
 
     @RBuiltin(name = ".fastr.stats.typecounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX)
-    public abstract static class FastRProfTypecounts extends RBuiltinNode implements RDataFactory.Listener {
+    public abstract static class FastRProfTypecounts extends RBuiltinNode.Arg2 implements RDataFactory.Listener {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{"Rproftypecounts.out", RRuntime.LOGICAL_FALSE};
@@ -289,7 +289,7 @@ public class FastRStats {
     }
 
     @RBuiltin(name = ".fastr.stats.funcounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append", "timing", "threshold", "histograms"}, behavior = COMPLEX)
-    public abstract static class FastRProfFuncounts extends RBuiltinNode {
+    public abstract static class FastRProfFuncounts extends RBuiltinNode.Arg5 {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{"Rproffuncounts.out", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, 0, RRuntime.LOGICAL_FALSE};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
index 5e1c4403e3..41e42f0a13 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
@@ -66,7 +66,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
  *
  */
 @RBuiltin(name = ".fastr.syntaxtree", visibility = OFF, kind = PRIMITIVE, parameterNames = {"func", "visitMode", "printSource", "printTags"}, behavior = IO)
-public abstract class FastRSyntaxTree extends RBuiltinNode {
+public abstract class FastRSyntaxTree extends RBuiltinNode.Arg4 {
 
     @Override
     public Object[] getDefaultParameterValues() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
index f1a6f7d4cc..648bb944fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRThrowIt.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 @RBuiltin(name = ".fastr.throw", kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
-public abstract class FastRThrowIt extends RBuiltinNode {
+public abstract class FastRThrowIt extends RBuiltinNode.Arg1 {
 
     static {
         Casts casts = new Casts(FastRThrowIt.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index 240f7c85d2..5d3d479fc4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -56,6 +56,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * This a FastR-specific version of the standard {@code trace} function which uses the
@@ -66,7 +67,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
  */
 public class FastRTrace {
 
-    protected abstract static class Helper extends RBuiltinNode {
+    static final class Helper extends RBaseNode {
         @Child private GetFunctions.Get getNode;
         @Child private EnvFunctions.TopEnv topEnv;
         @Child private FrameFunctions.ParentFrame parentFrame;
@@ -109,11 +110,12 @@ public class FastRTrace {
     }
 
     @RBuiltin(name = ".fastr.trace", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"what", "tracer", "exit", "at", "print", "signature", "where"}, behavior = COMPLEX)
-    public abstract static class Trace extends Helper {
+    public abstract static class Trace extends RBuiltinNode.Arg7 {
 
         @Child private TraceFunctions.PrimTrace primTrace;
         @Child private CastLogicalNode castLogical;
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
+        @Child private Helper helper = new Helper();
 
         static {
             Casts.noCasts(Trace.class);
@@ -122,16 +124,16 @@ public class FastRTrace {
         @Specialization
         protected Object trace(VirtualFrame frame, Object whatObj, Object tracer, Object exit, Object at, Object printObj, Object signature, Object whereObj) {
             Object what = whatObj;
-            checkWhat(what);
+            helper.checkWhat(what);
             Object where = whereObj;
             if (where == RMissing.instance) {
-                where = getWhere(frame);
+                where = helper.getWhere(frame);
             }
             String funcName = RRuntime.asString(what);
             if (funcName != null) {
-                what = getFunction(frame, what, where);
+                what = helper.getFunction(frame, what, where);
             }
-            RFunction func = checkFunction(what);
+            RFunction func = helper.checkFunction(what);
 
             if (tracer == RMissing.instance && exit == RMissing.instance && at == RMissing.instance && printObj == RMissing.instance && signature == RMissing.instance) {
                 // simple case, nargs() == 1, corresponds to .primTrace that has invisible output
@@ -178,9 +180,10 @@ public class FastRTrace {
     }
 
     @RBuiltin(name = ".fastr.untrace", visibility = OFF, kind = PRIMITIVE, parameterNames = {"what", "signature", "where"}, behavior = COMPLEX)
-    public abstract static class Untrace extends Helper {
+    public abstract static class Untrace extends RBuiltinNode.Arg3 {
 
         @Child private TraceFunctions.PrimUnTrace primUnTrace;
+        @Child private Helper helper = new Helper();
 
         static {
             Casts.noCasts(Untrace.class);
@@ -189,16 +192,16 @@ public class FastRTrace {
         @Specialization
         protected Object untrace(VirtualFrame frame, Object whatObj, Object signature, Object whereObj) {
             Object what = whatObj;
-            checkWhat(what);
+            helper.checkWhat(what);
             Object where = whereObj;
             if (where == RMissing.instance) {
-                where = getWhere(frame);
+                where = helper.getWhere(frame);
             }
             String funcName = RRuntime.asString(what);
             if (funcName != null) {
-                what = getFunction(frame, what, where);
+                what = helper.getFunction(frame, what, where);
             }
-            RFunction func = checkFunction(what);
+            RFunction func = helper.checkFunction(what);
             if (signature == RMissing.instance) {
                 if (primUnTrace == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java
index 7071bb26a0..85284f52cd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTree.java
@@ -39,7 +39,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RMissing;
 
 @RBuiltin(name = ".fastr.tree", visibility = OFF, kind = PRIMITIVE, parameterNames = {"func", "verbose"}, behavior = IO)
-public abstract class FastRTree extends RBuiltinNode {
+public abstract class FastRTree extends RBuiltinNode.Arg2 {
     @Override
     public Object[] getDefaultParameterValues() {
         return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE};
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java
index e40645a046..75a82d6766 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTreeStats.java
@@ -46,7 +46,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @RBuiltin(name = ".fastr.treestats", kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
-public abstract class FastRTreeStats extends RBuiltinNode {
+public abstract class FastRTreeStats extends RBuiltinNode.Arg1 {
 
     private static final RStringVector COLNAMES = RDataFactory.createStringVector(new String[]{"Total", "Syntax", "Non-Syntax"}, RDataFactory.COMPLETE_VECTOR);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java
index 45a57b1932..53cf1f0e42 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java
@@ -41,7 +41,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
  * message.
  */
 @RBuiltin(name = ".fastr.try", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX)
-public abstract class FastRTry extends RBuiltinNode {
+public abstract class FastRTry extends RBuiltinNode.Arg1 {
     @Child private RExplicitCallNode call = RExplicitCallNode.create();
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
index badecba152..d7d7701f67 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
@@ -36,7 +36,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
  * directly this Fortran routine.
  */
 @RBuiltin(name = ".fastr.dqrls", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x", "n", "p", "y", "ny", "tol", "coeff"}, behavior = PURE)
-public abstract class FastrDqrls extends RBuiltinNode {
+public abstract class FastrDqrls extends RBuiltinNode.Arg7 {
     @Child private RApplRFFI.DqrlsNode dqrlsNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode();
 
     private static final String[] NAMES = new String[]{"qr", "coefficients", "residuals", "effects", "rank", "pivot", "qraux", "tol", "pivoted"};
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
index 929e539386..a6d5f4a3da 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
-import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.HasSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
@@ -46,16 +45,10 @@ public abstract class RRootNode extends RootNode implements HasSignature {
 
     private final ConditionProfile irregularFrameProfile = ConditionProfile.createBinaryProfile();
 
-    /**
-     * The formal arguments this function is supposed to take.
-     */
-    private final FormalArguments formalArguments;
-
     private FastPathFactory fastPath;
 
-    protected RRootNode(FormalArguments formalArguments, FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
+    protected RRootNode(FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
         super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.SOURCE_UNAVAILABLE, frameDescriptor);
-        this.formalArguments = formalArguments;
         this.fastPath = fastPath;
     }
 
@@ -66,25 +59,6 @@ public abstract class RRootNode extends RootNode implements HasSignature {
         RArguments.setIsIrregular(vf, irregularFrameProfile.profile(RArguments.getIsIrregular(vf)));
     }
 
-    /**
-     * @return The number of parameters this functions expects
-     */
-    public final int getParameterCount() {
-        return formalArguments.getSignature().getLength();
-    }
-
-    /**
-     * @return {@link #formalArguments}
-     */
-    public final FormalArguments getFormalArguments() {
-        return formalArguments;
-    }
-
-    @Override
-    public final ArgumentsSignature getSignature() {
-        return formalArguments.getSignature();
-    }
-
     public final FastPathFactory getFastPath() {
         return fastPath;
     }
@@ -93,6 +67,8 @@ public abstract class RRootNode extends RootNode implements HasSignature {
         this.fastPath = fastPath;
     }
 
+    public abstract FormalArguments getFormalArguments();
+
     public abstract boolean needsSplitting();
 
     public abstract boolean containsDispatch();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index 20656b1d9d..56f24c6840 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -55,7 +55,7 @@ import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
  * operation is implemented by factory object given as a constructor parameter, e.g.
  * {@link com.oracle.truffle.r.runtime.ops.BinaryArithmetic.Add}
  */
-public abstract class BinaryArithmeticNode extends RBuiltinNode {
+public abstract class BinaryArithmeticNode extends RBuiltinNode.Arg2 {
 
     protected static final int CACHE_LIMIT = 5;
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index 21088940da..1f31766857 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -57,7 +57,7 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory;
  * operation is implemented by factory object given as a constructor parameter, e.g.
  * {@link com.oracle.truffle.r.runtime.ops.BinaryLogic.And}.
  */
-public abstract class BinaryBooleanNode extends RBuiltinNode {
+public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 {
 
     protected static final int CACHE_LIMIT = 5;
 
@@ -86,6 +86,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode {
         return factory == BinaryLogic.AND || factory == BinaryLogic.OR;
     }
 
+    @Override
     public abstract Object execute(VirtualFrame frame, Object left, Object right);
 
     public static BinaryBooleanNode create(BooleanOperationFactory factory) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
index 3026310ff2..444696a3f7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.ops.BooleanOperation;
 import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-public abstract class BinaryBooleanScalarNode extends RBuiltinNode {
+public abstract class BinaryBooleanScalarNode extends RBuiltinNode.Arg2 {
 
     /*
      * As the execution of right depends on the left value and the right node might be arbitrarily
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
deleted file mode 100644
index 36f9c1ca75..0000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.binary;
-
-import com.oracle.truffle.api.dsl.NodeChild;
-import com.oracle.truffle.r.runtime.nodes.RNode;
-
-@NodeChild(value = "left", type = RNode.class)
-@NodeChild(value = "right", type = RNode.class)
-abstract class BinaryNode extends RNode {
-
-    protected abstract RNode getLeft();
-
-    protected abstract RNode getRight();
-
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
index 3b823312a6..4181bfc59c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
@@ -14,6 +14,7 @@ package com.oracle.truffle.r.nodes.binary;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
@@ -25,9 +26,12 @@ import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNodeGen;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-public abstract class CastTypeNode extends BinaryNode {
+@TypeSystemReference(RTypes.class)
+public abstract class CastTypeNode extends RBaseNode {
 
     protected static final int NUMBER_OF_TYPES = RType.values().length;
 
@@ -63,7 +67,7 @@ public abstract class CastTypeNode extends BinaryNode {
     }
 
     public static CastTypeNode create() {
-        return CastTypeNodeGen.create(null, null);
+        return CastTypeNodeGen.create();
     }
 
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
index 6b29fde993..7fceec433d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
@@ -33,7 +33,6 @@ import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.control.OperatorNode;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -194,7 +193,6 @@ public abstract class InternalNode extends OperatorNode {
         protected final int varArgIndex;
 
         @Children protected final RNode[] arguments;
-        @Children protected final CastNode[] casts;
         @Child private RBuiltinNode builtin;
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
@@ -202,15 +200,11 @@ public abstract class InternalNode extends OperatorNode {
             super(src, operator, outerSignature, outerArgs);
             this.factory = factory;
             this.builtin = factory.getConstructor().get();
-            this.casts = builtin.getCasts();
             this.arguments = new RNode[args.length];
             for (int i = 0; i < args.length; i++) {
                 arguments[i] = ((RSyntaxNode) args[i]).asRNode();
             }
             this.varArgIndex = factory.getSignature().getVarArgIndex();
-            if (varArgIndex != ArgumentsSignature.NO_VARARG) {
-                assert casts.length <= varArgIndex || casts[varArgIndex] == null : "no casts on '...' arguments to .Internals";
-            }
         }
 
         @Override
@@ -222,7 +216,7 @@ public abstract class InternalNode extends OperatorNode {
 
         @Override
         public Object execute(VirtualFrame frame) {
-            Object result = builtin.executeBuiltin(frame, prepareArgs(frame));
+            Object result = builtin.call(frame, prepareArgs(frame));
             assert result != null : "builtins cannot return 'null': " + factory.getName();
             assert !(result instanceof RConnection) : "builtins cannot return connection': " + factory.getName();
             visibility.execute(frame, factory.getVisibility());
@@ -231,7 +225,7 @@ public abstract class InternalNode extends OperatorNode {
 
         @Override
         public void voidExecute(VirtualFrame frame) {
-            builtin.executeBuiltin(frame, prepareArgs(frame));
+            builtin.call(frame, prepareArgs(frame));
         }
     }
 
@@ -250,11 +244,7 @@ public abstract class InternalNode extends OperatorNode {
         protected Object[] prepareArgs(VirtualFrame frame) {
             Object[] args = new Object[arguments.length];
             for (int i = 0; i < args.length; i++) {
-                Object value = arguments[i].execute(frame);
-                if (i < casts.length && casts[i] != null) {
-                    value = casts[i].execute(value);
-                }
-                args[i] = value;
+                args[i] = arguments[i].execute(frame);
             }
             return args;
         }
@@ -281,10 +271,6 @@ public abstract class InternalNode extends OperatorNode {
                 Object value = arguments[i].execute(frame);
                 if (i == varArgIndex) {
                     value = forcePromises(frame, (RArgsValuesAndNames) value);
-                } else {
-                    if (i < casts.length && casts[i] != null) {
-                        value = casts[i].execute(value);
-                    }
                 }
                 args[i] = value;
             }
@@ -316,11 +302,7 @@ public abstract class InternalNode extends OperatorNode {
             Object[] args = new Object[factory.getSignature().getLength()];
 
             for (int i = 0; i < args.length - 1; i++) {
-                Object value = arguments[i].execute(frame);
-                if (i < casts.length && casts[i] != null) {
-                    value = casts[i].execute(value);
-                }
-                args[i] = value;
+                args[i] = arguments[i].execute(frame);
             }
             Object[] varArgs = new Object[arguments.length - (factory.getSignature().getLength() - 1)];
             for (int i = 0; i < varArgs.length; i++) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
index f133a299b7..152b5258dc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
@@ -48,7 +48,7 @@ public interface NodeWithArgumentCasts {
         return casts;
     }
 
-    final class Casts {
+    public final class Casts {
         private static final ConcurrentHashMap<Class<?>, Casts> castsMap = new ConcurrentHashMap<>();
         private static final Casts empty = new Casts();
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index f3c4cc292e..13cd8bbff0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -22,11 +22,14 @@
  */
 package com.oracle.truffle.r.nodes.builtin;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.function.RCallNode;
+import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.ErrorContext;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -45,7 +48,7 @@ import com.oracle.truffle.r.runtime.nodes.builtin.RBuiltinBaseNode;
 @TypeSystemReference(RTypes.class)
 public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithArgumentCasts {
 
-    public abstract Object executeBuiltin(VirtualFrame frame, Object... args);
+    public abstract Object call(VirtualFrame frame, Object... args);
 
     /**
      * Return the default values of the builtin's formal arguments. This is only valid for builtins
@@ -108,4 +111,212 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
         ErrorContext context = RError.contextForBuiltin(getRBuiltin());
         return context == null ? this : context;
     }
+
+    @Children private final CastNode[] argumentCasts;
+    @CompilationFinal(dimensions = 1) private final Class<?>[] argumentClasses;
+
+    protected RBuiltinNode(int argCount) {
+        argumentCasts = getCasts();
+        argumentClasses = new Class<?>[argCount];
+    }
+
+    protected Object castArg(Object[] args, int index) {
+        Object value = index < argumentCasts.length && argumentCasts[index] != null ? argumentCasts[index].execute(args[index]) : args[index];
+        Class<?> clazz = argumentClasses[index];
+        if (clazz == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            argumentClasses[index] = clazz = value.getClass();
+            return value;
+        } else if (clazz == Object.class) {
+            return value;
+        } else if (value.getClass() == clazz) {
+            return clazz.cast(value);
+        } else {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            argumentClasses[index] = Object.class;
+            return value;
+        }
+    }
+
+    public abstract static class Arg0 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame);
+
+        protected Arg0() {
+            super(0);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame);
+        }
+    }
+
+    public abstract static class Arg1 extends RBuiltinNode {
+        public abstract Object execute(VirtualFrame frame, Object arg);
+
+        protected Arg1() {
+            super(1);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0));
+        }
+    }
+
+    public abstract static class Arg2 extends RBuiltinNode {
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2);
+
+        protected Arg2() {
+            super(2);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1));
+        }
+    }
+
+    public abstract static class Arg3 extends RBuiltinNode {
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3);
+
+        protected Arg3() {
+            super(3);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2));
+        }
+    }
+
+    public abstract static class Arg4 extends RBuiltinNode {
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4);
+
+        protected Arg4() {
+            super(4);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3));
+        }
+    }
+
+    public abstract static class Arg5 extends RBuiltinNode {
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5);
+
+        protected Arg5() {
+            super(5);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4));
+        }
+    }
+
+    public abstract static class Arg6 extends RBuiltinNode {
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6);
+
+        protected Arg6() {
+            super(6);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5));
+        }
+    }
+
+    public abstract static class Arg7 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7);
+
+        protected Arg7() {
+            super(7);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6));
+        }
+    }
+
+    public abstract static class Arg8 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8);
+
+        protected Arg8() {
+            super(8);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7));
+        }
+    }
+
+    public abstract static class Arg9 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9);
+
+        protected Arg9() {
+            super(9);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8));
+        }
+    }
+
+    public abstract static class Arg10 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10);
+
+        protected Arg10() {
+            super(10);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8),
+                            castArg(args, 9));
+        }
+    }
+
+    public abstract static class Arg11 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10,
+                        Object arg11);
+
+        protected Arg11() {
+            super(11);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8),
+                            castArg(args, 9), castArg(args, 10));
+        }
+    }
+
+    public abstract static class Arg19 extends RBuiltinNode {
+
+        public abstract Object execute(VirtualFrame frame, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10,
+                        Object arg11, Object arg12, Object arg13, Object arg14, Object arg15, Object arg16, Object arg17, Object arg18, Object arg19);
+
+        protected Arg19() {
+            super(19);
+        }
+
+        @Override
+        public final Object call(VirtualFrame frame, Object... args) {
+            return execute(frame, castArg(args, 0), castArg(args, 1), castArg(args, 2), castArg(args, 3), castArg(args, 4), castArg(args, 5), castArg(args, 6), castArg(args, 7), castArg(args, 8),
+                            castArg(args, 9), castArg(args, 10), castArg(args, 11), castArg(args, 12), castArg(args, 13), castArg(args, 14), castArg(args, 15), castArg(args, 16), castArg(args, 17),
+                            castArg(args, 18));
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
index 88652dcff5..665593df50 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
@@ -33,8 +33,10 @@ import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.RCallNode.BuiltinCallNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
+import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
@@ -44,21 +46,31 @@ public final class RBuiltinRootNode extends RRootNode {
     @Children private final AccessArgumentNode[] args;
     @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
-    private final RBuiltinNode builtin;
     private final RBuiltinFactory factory;
 
-    RBuiltinRootNode(RBuiltinFactory factory, RBuiltinNode builtin, FormalArguments formalArguments, FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
-        super(formalArguments, frameDescriptor, fastPath);
+    RBuiltinRootNode(RBuiltinFactory factory, FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
+        super(frameDescriptor, fastPath);
         this.factory = factory;
-        this.builtin = builtin;
         this.args = new AccessArgumentNode[factory.getSignature().getLength()];
     }
 
+    @Override
+    public final FormalArguments getFormalArguments() {
+        initialize();
+        return call.getFormals();
+    }
+
+    @Override
+    public final ArgumentsSignature getSignature() {
+        initialize();
+        return call.getFormals().getSignature();
+    }
+
     @Override
     public RootCallTarget duplicateWithNewFrameDescriptor() {
         FrameDescriptor frameDescriptor = new FrameDescriptor();
         FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("builtin", frameDescriptor);
-        return Truffle.getRuntime().createCallTarget(new RBuiltinRootNode(factory, (RBuiltinNode) builtin.deepCopy(), getFormalArguments(), frameDescriptor, getFastPath()));
+        return Truffle.getRuntime().createCallTarget(new RBuiltinRootNode(factory, frameDescriptor, getFastPath()));
     }
 
     @Override
@@ -71,14 +83,7 @@ public final class RBuiltinRootNode extends RRootNode {
     public Object execute(VirtualFrame frame) {
         verifyEnclosingAssumptions(frame);
         try {
-            if (call == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                this.call = insert(new BuiltinCallNode(builtin, factory, getFormalArguments(), null, true));
-                for (int i = 0; i < args.length; i++) {
-                    args[i] = insert(AccessArgumentNode.create(i));
-                    args[i].setFormals(getFormalArguments());
-                }
-            }
+            initialize();
             Object[] arguments = new Object[args.length];
             for (int i = 0; i < args.length; i++) {
                 arguments[i] = args[i].execute(frame);
@@ -93,8 +98,26 @@ public final class RBuiltinRootNode extends RRootNode {
         }
     }
 
+    private void initialize() {
+        if (call == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            RBuiltinNode builtin = factory.getConstructor().get();
+            FormalArguments formalArguments = FormalArguments.createForBuiltin(builtin.getDefaultParameterValues(), factory.getSignature());
+            if (factory.getKind() == RBuiltinKind.INTERNAL) {
+                assert builtin.getDefaultParameterValues().length == 0 : "INTERNAL builtins do not need default values";
+                assert factory.getSignature().getVarArgCount() == 0 || factory.getSignature().getVarArgIndex() == factory.getSignature().getLength() - 1 : "only last argument can be vararg";
+            }
+            call = insert(new BuiltinCallNode(builtin, factory, formalArguments, null, true));
+            for (int i = 0; i < args.length; i++) {
+                args[i] = insert(AccessArgumentNode.create(i));
+                args[i].setFormals(formalArguments);
+            }
+        }
+    }
+
     public RBuiltinNode getBuiltinNode() {
-        return builtin;
+        initialize();
+        return call.getBuiltin();
     }
 
     @Override
@@ -119,6 +142,6 @@ public final class RBuiltinRootNode extends RRootNode {
 
     @Override
     public String getName() {
-        return "RBuiltin(" + builtin + ")";
+        return "RBuiltin(" + factory.getName() + ")";
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java
deleted file mode 100644
index 0577e23b3a..0000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RInvisibleBuiltinNode.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.builtin;
-
-public abstract class RInvisibleBuiltinNode extends RBuiltinNode {
-
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java
index aa07294e97..b37d8f06ac 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.nodes.unary.PrecedenceNode;
 import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 
-public abstract class RPrecedenceBuiltinNode extends RBuiltinNode {
+public abstract class RPrecedenceBuiltinNode extends RBuiltinNode.Arg3 {
 
     @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create();
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
index d735d29331..0e77db678e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java
@@ -29,7 +29,6 @@ import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNodeGen;
 import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode;
 import com.oracle.truffle.r.nodes.function.signature.VarArgsHelper;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RArguments.DispatchArgs;
@@ -187,7 +186,6 @@ public abstract class CallMatcherNode extends RBaseNode {
         @Child private CallMatcherNode next;
         @Child private CallRFunctionNode call;
         @Child private RBuiltinNode builtin;
-        @Children private final CastNode[] builtinArgumentCasts;
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
         private final RBuiltinDescriptor builtinDescriptor;
@@ -218,12 +216,10 @@ public abstract class CallMatcherNode extends RBaseNode {
             if (function.isBuiltin()) {
                 this.builtinDescriptor = function.getRBuiltin();
                 this.builtin = RBuiltinNode.inline(builtinDescriptor);
-                this.builtinArgumentCasts = builtin.getCasts();
                 this.fastPath = null;
                 this.fastPathVisibility = null;
             } else {
                 this.call = CallRFunctionNode.create(function.getTarget());
-                this.builtinArgumentCasts = null;
                 this.builtinDescriptor = null;
                 FastPathFactory fastPathFactory = root.getFastPath();
                 this.fastPath = fastPathFactory == null ? null : fastPathFactory.create();
@@ -273,8 +269,7 @@ public abstract class CallMatcherNode extends RBaseNode {
                         visibility.executeAfterCall(frame, caller);
                     }
                 } else {
-                    applyCasts(reorderedArgs);
-                    Object result = builtin.executeBuiltin(frame, reorderedArgs);
+                    Object result = builtin.call(frame, reorderedArgs);
                     visibility.execute(frame, builtinDescriptor.getVisibility());
                     return result;
                 }
@@ -283,16 +278,6 @@ public abstract class CallMatcherNode extends RBaseNode {
             }
         }
 
-        @ExplodeLoop
-        private void applyCasts(Object[] reorderedArgs) {
-            for (int i = 0; i < builtinArgumentCasts.length; i++) {
-                CastNode cast = builtinArgumentCasts[i];
-                if (cast != null) {
-                    reorderedArgs[i] = cast.execute(reorderedArgs[i]);
-                }
-            }
-        }
-
         @Override
         @ExplodeLoop
         protected void replaceMissingArguments(RFunction function, Object[] args) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 984dce3f21..3ff7095907 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -82,7 +82,10 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
 
 public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNode, RSyntaxFunction {
 
-    @Child private RNode body; // typed as RNode to avoid custom instrument wrapper
+    private final FormalArguments formalArguments;
+
+    @Child private RNode body;
+
     /**
      * This exists for debugging purposes. It is set initially when the function is defined to
      * either:
@@ -135,7 +138,8 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
 
     private FunctionDefinitionNode(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, RNode saveArguments, RSyntaxNode body, FormalArguments formals,
                     String name, PostProcessArgumentsNode argPostProcess) {
-        super(formals, frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature()));
+        super(frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature()));
+        this.formalArguments = formals;
         this.argSourceSections = argSourceSections;
         assert FrameSlotChangeMonitor.isValidFrameDescriptor(frameDesc);
         assert src != null;
@@ -149,6 +153,16 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         this.argPostProcess = argPostProcess;
     }
 
+    @Override
+    public final FormalArguments getFormalArguments() {
+        return formalArguments;
+    }
+
+    @Override
+    public final ArgumentsSignature getSignature() {
+        return formalArguments.getSignature();
+    }
+
     @Override
     public RootCallTarget duplicateWithNewFrameDescriptor() {
         RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index a921d98f18..19e58dc902 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -65,7 +65,6 @@ import com.oracle.truffle.r.nodes.function.call.PrepareArguments;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
-import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -777,7 +776,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         @Child private RBuiltinNode builtin;
         @Child private PromiseCheckHelperNode varArgsPromiseHelper;
         @Children private final PromiseHelperNode[] promiseHelpers;
-        @Children private final CastNode[] casts;
         @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
 
         // not using profiles to save overhead
@@ -795,7 +793,6 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
             this.builtin = builtin;
             this.builtinDescriptor = builtinDescriptor;
             this.explicitArgs = explicitArgs;
-            this.casts = builtin.getCasts();
             this.formals = formalArguments;
             promiseHelpers = new PromiseHelperNode[formals.getLength()];
             argEmptySeen = new boolean[formals.getLength()];
@@ -809,6 +806,14 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
             return builtin.getErrorContext();
         }
 
+        public RBuiltinNode getBuiltin() {
+            return builtin;
+        }
+
+        public FormalArguments getFormals() {
+            return formals;
+        }
+
         @ExplodeLoop
         public Object[] castArguments(VirtualFrame frame, Object[] args) {
             int argCount = formals.getLength();
@@ -843,12 +848,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                             }
                             arg = promiseHelpers[i].evaluate(frame, (RPromise) arg);
                         }
-                        if (i < casts.length && casts[i] != null) {
-                            assert builtinDescriptor.evaluatesArg(i);
-                            arg = casts[i].execute(arg);
-                        }
                     } else {
-                        assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments in builtin " + builtinDescriptor.getName();
                         if (arg instanceof RPromise || arg instanceof RMissing) {
                             if (!nonWrapSeen[i]) {
                                 CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -916,7 +916,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
 
         @Override
         public Object execute(VirtualFrame frame, RFunction currentFunction, RArgsValuesAndNames orderedArguments, S3Args s3Args) {
-            Object result = builtin.executeBuiltin(frame, castArguments(frame, orderedArguments.getArguments()));
+            Object result = builtin.call(frame, castArguments(frame, orderedArguments.getArguments()));
             assert result != null : "builtins cannot return 'null': " + builtinDescriptor.getName();
             assert !(result instanceof RConnection) : "builtins cannot return connection': " + builtinDescriptor.getName();
             visibility.execute(frame, builtinDescriptor.getVisibility());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
index ff0bab5975..cf9c38a6aa 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
@@ -85,4 +85,8 @@ public abstract class TypeofNode extends UnaryNode {
         CompilerAsserts.neverPartOfCompilation();
         return ((RTypedValue) RRuntime.asAbstractVector(operand)).getRType();
     }
+
+    public static TypeofNode create() {
+        return TypeofNodeGen.create();
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java
index 30a7366772..b251f47a84 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
-public abstract class UnaryArithmeticBuiltinNode extends RBuiltinNode implements UnaryArithmeticFactory {
+public abstract class UnaryArithmeticBuiltinNode extends RBuiltinNode.Arg1 implements UnaryArithmeticFactory {
 
     @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
     @Child private UnaryArithmeticNode unaryNode;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
index ab41637a83..29484784d2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
 @RBuiltin(name = "!", kind = PRIMITIVE, parameterNames = {""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
-public abstract class UnaryNotNode extends RBuiltinNode {
+public abstract class UnaryNotNode extends RBuiltinNode.Arg1 {
 
     private final NACheck na = NACheck.create();
     private final NAProfile naProfile = NAProfile.create();
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 75132c6fe4..6fe58f99a7 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
index 03d88811d9..425f866ead 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
@@ -30,7 +30,6 @@ import java.util.Comparator;
 
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
 import com.oracle.truffle.r.runtime.ffi.RFFICstring;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
  * Generates the entries for {@link RFFIUpCallMethod}.
-- 
GitLab


From 24ddd4429afd86678d2112c8102a01424f6f0444 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 7 Apr 2017 14:45:13 +0200
Subject: [PATCH 276/402] Added value profile for cast pipeline nodes.

---
 .../oracle/truffle/r/nodes/builtin/RBuiltinNode.java | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index 13cd8bbff0..d2ed7222a4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -114,6 +115,7 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
 
     @Children private final CastNode[] argumentCasts;
     @CompilationFinal(dimensions = 1) private final Class<?>[] argumentClasses;
+    private final ValueProfile castClassProfile = ValueProfile.createClassProfile();
 
     protected RBuiltinNode(int argCount) {
         argumentCasts = getCasts();
@@ -121,7 +123,12 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
     }
 
     protected Object castArg(Object[] args, int index) {
-        Object value = index < argumentCasts.length && argumentCasts[index] != null ? argumentCasts[index].execute(args[index]) : args[index];
+        Object value;
+        if (index < argumentCasts.length && argumentCasts[index] != null) {
+            value = argumentCasts[index].execute(castClassProfile.profile(args[index]));
+        } else {
+            value = args[index];
+        }
         Class<?> clazz = argumentClasses[index];
         if (clazz == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -130,6 +137,9 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
         } else if (clazz == Object.class) {
             return value;
         } else if (value.getClass() == clazz) {
+            if (CompilerDirectives.inInterpreter()) {
+                return value;
+            }
             return clazz.cast(value);
         } else {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-- 
GitLab


From e3dfa7e66952dae33cd67359f1cdc479c3764101 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 7 Apr 2017 16:20:26 +0200
Subject: [PATCH 277/402] Added value profile for type in MatrixFastPath.

---
 .../oracle/truffle/r/nodes/builtin/base/CommandArgs.java    | 2 +-
 .../src/com/oracle/truffle/r/nodes/builtin/base/Date.java   | 2 +-
 .../oracle/truffle/r/nodes/builtin/base/Interactive.java    | 2 +-
 .../truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java   | 2 +-
 .../src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java  | 2 +-
 .../com/oracle/truffle/r/nodes/builtin/base/ProcTime.java   | 2 +-
 .../com/oracle/truffle/r/nodes/builtin/base/RVersion.java   | 2 +-
 .../src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java  | 2 +-
 .../com/oracle/truffle/r/nodes/builtin/base/TempDir.java    | 2 +-
 .../r/nodes/builtin/base/fastpaths/AssignFastPath.java      | 2 +-
 .../r/nodes/builtin/base/fastpaths/MatrixFastPath.java      | 6 ++++--
 .../src/com/oracle/truffle/r/nodes/RRootNode.java           | 2 +-
 .../truffle/r/nodes/builtin/NodeWithArgumentCasts.java      | 2 +-
 .../oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java    | 4 ++--
 .../truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java     | 2 +-
 .../truffle/r/nodes/function/FunctionDefinitionNode.java    | 4 ++--
 16 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
index 5ff3ba65a5..9c6f24083b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java
index 963c5131f0..cbf8371eec 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Date.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
index 424889c116..ef734b838b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java
index 6785523853..0318822491 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsMethodsDispatchOn.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java
index 4298b5e9ca..06edb6da08 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NArgs.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java
index 2afa720a9e..2492d86ee9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java
index 14acdea47a..5deeb4662e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RVersion.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java
index b5f44e9c07..e538405b68 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rhome.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java
index c707b09584..d54dbc9845 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TempDir.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java
index 7912423f9b..ae1586c95a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/AssignFastPath.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
index 056af9a7e5..0baf7029f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.base.Matrix;
 import com.oracle.truffle.r.nodes.builtin.base.MatrixNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
@@ -55,13 +56,14 @@ public abstract class MatrixFastPath extends RFastPathNode {
                     @Cached("createBinaryProfile()") ConditionProfile rowMissingProfile,
                     @Cached("createBinaryProfile()") ConditionProfile colMissingProfile,
                     @Cached("createBinaryProfile()") ConditionProfile dimMissingProfile,
-                    @Cached("createMatrix()") Matrix matrix) {
+                    @Cached("createMatrix()") Matrix matrix,
+                    @Cached("createClassProfile()") ValueProfile classProfile) {
         boolean rowMissing = rowMissingProfile.profile(nrow == RMissing.instance);
         boolean colMissing = colMissingProfile.profile(ncol == RMissing.instance);
         int row = rowMissing ? 1 : firstRow.executeInt(castRow.execute(nrow));
         int col = colMissing ? 1 : firstCol.executeInt(castCol.execute(ncol));
         Object dim = dimMissingProfile.profile(dimnames == RMissing.instance) ? RNull.instance : dimnames;
-        return matrix.execute(data, row, col, false, dim, rowMissing, colMissing);
+        return matrix.execute(classProfile.profile(data), row, col, false, dim, rowMissing, colMissing);
     }
 
     @Fallback
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
index a6d5f4a3da..d04204e0e3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
index 152b5258dc..f133a299b7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/NodeWithArgumentCasts.java
@@ -48,7 +48,7 @@ public interface NodeWithArgumentCasts {
         return casts;
     }
 
-    public final class Casts {
+    final class Casts {
         private static final ConcurrentHashMap<Class<?>, Casts> castsMap = new ConcurrentHashMap<>();
         private static final Casts empty = new Casts();
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
index 665593df50..32eb510cc7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
@@ -55,13 +55,13 @@ public final class RBuiltinRootNode extends RRootNode {
     }
 
     @Override
-    public final FormalArguments getFormalArguments() {
+    public FormalArguments getFormalArguments() {
         initialize();
         return call.getFormals();
     }
 
     @Override
-    public final ArgumentsSignature getSignature() {
+    public ArgumentsSignature getSignature() {
         initialize();
         return call.getFormals().getSignature();
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java
index b37d8f06ac..fd3d5d3106 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RPrecedenceBuiltinNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 3ff7095907..39fe992344 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -154,12 +154,12 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
     }
 
     @Override
-    public final FormalArguments getFormalArguments() {
+    public FormalArguments getFormalArguments() {
         return formalArguments;
     }
 
     @Override
-    public final ArgumentsSignature getSignature() {
+    public ArgumentsSignature getSignature() {
         return formalArguments.getSignature();
     }
 
-- 
GitLab


From 18946b48deb3b9182aa53bef6bc33ccd7b71a4e5 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 7 Apr 2017 12:00:11 +0200
Subject: [PATCH 278/402] =?UTF-8?q?use=20frame=20slots=20directly=20in=20A?=
 =?UTF-8?q?rgumentStatePush/PostProcessArguments=20and=20remove=20?=
 =?UTF-8?q?=E2=80=9CObject=E2=80=9D=20case=20in=20WriteVariableNode?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../r/nodes/access/BaseWriteVariableNode.java |  2 +-
 .../access/WriteLocalFrameVariableNode.java   |  6 ++---
 .../access/WriteSuperFrameVariableNode.java   |  8 +++---
 .../r/nodes/access/WriteVariableNode.java     |  6 ++---
 .../r/nodes/function/ArgumentStatePush.java   | 12 +++++----
 .../function/PostProcessArgumentsNode.java    | 27 ++++++++++++-------
 6 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index 2cb9365d10..d534173f4d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  */
 abstract class BaseWriteVariableNode extends WriteVariableNode {
 
-    protected BaseWriteVariableNode(Object name) {
+    protected BaseWriteVariableNode(String name) {
         super(name);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
index 8e953b8420..56acae1d73 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java
@@ -45,11 +45,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 @ImportStatic(FrameSlotKind.class)
 public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode {
 
-    public static WriteLocalFrameVariableNode create(Object name, Mode mode, RNode rhs) {
+    public static WriteLocalFrameVariableNode create(String name, Mode mode, RNode rhs) {
         return WriteLocalFrameVariableNodeGen.create(name, mode, rhs);
     }
 
-    public static WriteLocalFrameVariableNode createForRefCount(Object name) {
+    public static WriteLocalFrameVariableNode createForRefCount(String name) {
         return WriteLocalFrameVariableNodeGen.create(name, Mode.INVISIBLE, null);
     }
 
@@ -60,7 +60,7 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode
     private final ConditionProfile isActiveBindingProfile = ConditionProfile.createBinaryProfile();
     @CompilationFinal private Assumption containsNoActiveBinding;
 
-    protected WriteLocalFrameVariableNode(Object name, Mode mode) {
+    protected WriteLocalFrameVariableNode(String name, Mode mode) {
         super(name);
         this.mode = mode;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
index bbc7d82a5b..6d215ddd2a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  */
 abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
 
-    protected WriteSuperFrameVariableNode(Object name) {
+    protected WriteSuperFrameVariableNode(String name) {
         super(name);
     }
 
@@ -78,7 +78,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         private final Mode mode;
         @CompilationFinal private Assumption containsNoActiveBinding;
 
-        public ResolvedWriteSuperFrameVariableNode(Object name, Mode mode) {
+        public ResolvedWriteSuperFrameVariableNode(String name, Mode mode) {
             super(name);
             this.mode = mode;
         }
@@ -122,7 +122,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
 
         private final Mode mode;
 
-        UnresolvedWriteSuperFrameVariableNode(Object name, Mode mode, RNode rhs) {
+        UnresolvedWriteSuperFrameVariableNode(String name, Mode mode, RNode rhs) {
             super(name);
             this.mode = mode;
             this.rhs = rhs;
@@ -175,7 +175,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
         private final ConditionProfile hasValueProfile = ConditionProfile.createBinaryProfile();
         private final ConditionProfile nullSuperFrameProfile = ConditionProfile.createBinaryProfile();
 
-        WriteSuperFrameVariableConditionalNode(Object name, ResolvedWriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNode nextNode, RNode rhs) {
+        WriteSuperFrameVariableConditionalNode(String name, ResolvedWriteSuperFrameVariableNode writeNode, WriteSuperFrameVariableNode nextNode, RNode rhs) {
             super(name);
             this.writeNode = writeNode;
             this.nextNode = nextNode;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
index 9416b60d27..2490221a60 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
@@ -43,13 +43,13 @@ public abstract class WriteVariableNode extends RNode {
         INVISIBLE
     }
 
-    private final Object name;
+    private final String name;
 
-    protected WriteVariableNode(Object name) {
+    protected WriteVariableNode(String name) {
         this.name = name;
     }
 
-    public final Object getName() {
+    public final String getName() {
         return name;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index fe657055d9..605d628d4f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -23,12 +23,14 @@
 package com.oracle.truffle.r.nodes.function;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -44,7 +46,7 @@ public abstract class ArgumentStatePush extends Node {
 
     public abstract void executeObject(VirtualFrame frame, Object shareable);
 
-    @Child private WriteLocalFrameVariableNode write;
+    @CompilationFinal private FrameSlot frameSlot;
 
     private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile();
 
@@ -94,11 +96,11 @@ public abstract class ArgumentStatePush extends Node {
         if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) {
             shareable.incRefCount();
             if (writeArgMask != -1 && !FastROptions.RefCountIncrementOnly.getBooleanValue()) {
-                if (write == null) {
+                if (frameSlot == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    write = insert(WriteLocalFrameVariableNode.createForRefCount(Integer.valueOf(writeArgMask)));
+                    frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(writeArgMask, FrameSlotKind.Object);
                 }
-                write.execute(frame, shareable);
+                frame.setObject(frameSlot, shareable);
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
index e808377fef..d32cd3d80d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
@@ -23,11 +23,15 @@
 package com.oracle.truffle.r.nodes.function;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
+import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.utilities.AssumedValue;
-import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -38,7 +42,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  */
 public final class PostProcessArgumentsNode extends RNode {
 
-    @Children private final LocalReadVariableNode[] sequence;
+    @CompilationFinal private final FrameSlot[] frameSlots;
 
     // stays the same during cloning
     private final AssumedValue<Integer> transArgsBitSet;
@@ -47,7 +51,7 @@ public final class PostProcessArgumentsNode extends RNode {
     private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile();
 
     private PostProcessArgumentsNode(int length) {
-        this.sequence = new LocalReadVariableNode[Math.min(length, ArgumentStatePush.MAX_COUNTED_ARGS)];
+        this.frameSlots = new FrameSlot[Math.min(length, ArgumentStatePush.MAX_COUNTED_ARGS)];
         this.transArgsBitSet = new AssumedValue<>("PostProcessArgumentsNode.transArgsBitSet", 0);
     }
 
@@ -56,7 +60,7 @@ public final class PostProcessArgumentsNode extends RNode {
     }
 
     public int getLength() {
-        return sequence.length;
+        return frameSlots.length;
     }
 
     @Override
@@ -64,14 +68,19 @@ public final class PostProcessArgumentsNode extends RNode {
     public Object execute(VirtualFrame frame) {
         int bits = transArgsBitSet.get();
         if (bits != 0) {
-            for (int i = 0; i < sequence.length; i++) {
+            for (int i = 0; i < frameSlots.length; i++) {
                 int mask = 1 << i;
                 if ((bits & mask) != 0) {
-                    if (sequence[i] == null) {
+                    if (frameSlots[i] == null) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
-                        sequence[i] = insert(LocalReadVariableNode.create(Integer.valueOf(mask), false));
+                        frameSlots[i] = frame.getFrameDescriptor().findOrAddFrameSlot(mask, FrameSlotKind.Object);
+                    }
+                    RShareable s;
+                    try {
+                        s = (RShareable) frame.getObject(frameSlots[i]);
+                    } catch (FrameSlotTypeException e) {
+                        throw RInternalError.shouldNotReachHere();
                     }
-                    RShareable s = (RShareable) sequence[i].execute(frame);
                     if (isNonNull.profile(s != null)) {
                         if (isRefCountUpdateable.profile(!s.isSharedPermanent())) {
                             s.decRefCount();
@@ -84,7 +93,7 @@ public final class PostProcessArgumentsNode extends RNode {
     }
 
     public boolean updateBits(int index) {
-        if (index < sequence.length) {
+        if (index < frameSlots.length) {
             int bits = transArgsBitSet.get();
             int newBits = bits | (1 << index);
             if (newBits != bits) {
-- 
GitLab


From aa237f83a62986cd8bbb8b4845779122e427681e Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 7 Apr 2017 11:57:52 +0200
Subject: [PATCH 279/402] channel all frame accesses through
 FrameSlotChangeMonitor

---
 .../truffle/r/engine/interop/RFunctionMR.java | 11 +--
 .../library/methods/MethodsListDispatch.java  |  3 +-
 .../r/nodes/builtin/base/FrameFunctions.java  |  3 +-
 .../truffle/r/nodes/builtin/base/Lapply.java  |  9 ++-
 .../r/nodes/builtin/base/MatchFun.java        |  3 +-
 .../truffle/r/nodes/builtin/base/OnExit.java  | 81 ++++++++-----------
 .../r/nodes/access/BaseWriteVariableNode.java |  2 +-
 .../truffle/r/nodes/access/FrameSlotNode.java | 24 +++---
 .../r/nodes/access/RemoveAndAnswerNode.java   |  2 +-
 .../access/WriteSuperFrameVariableNode.java   |  2 +-
 .../access/variables/ReadVariableNode.java    | 13 +--
 .../r/nodes/function/ArgumentMatcher.java     |  5 +-
 .../function/FunctionDefinitionNode.java      |  2 +-
 .../r/nodes/function/GetMissingValueNode.java |  5 +-
 .../function/PostProcessArgumentsNode.java    |  4 +-
 .../r/nodes/function/PromiseHelperNode.java   |  3 +-
 .../truffle/r/nodes/function/RCallNode.java   |  3 +-
 .../r/nodes/function/RMissingHelper.java      |  3 +-
 .../nodes/function/S3FunctionLookupNode.java  |  3 +-
 .../r/nodes/function/TemporarySlotNode.java   | 18 +++--
 .../function/call/RExplicitCallNode.java      | 34 ++++----
 .../signature/CollectArgumentsNode.java       |  3 +-
 .../objects/CollectGenericArgumentsNode.java  |  3 +-
 .../com/oracle/truffle/r/runtime/Utils.java   |  1 +
 .../env/frame/FrameSlotChangeMonitor.java     | 17 +++-
 .../env/frame/REnvTruffleFrameAccess.java     |  5 +-
 .../r/runtime/env/frame/RFrameSlot.java       | 41 ++++++++--
 .../truffle/r/test/tck/FastRDebugTest.java    |  2 +-
 28 files changed, 181 insertions(+), 124 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index a7210d6a77..c0e648cc3a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -42,6 +42,7 @@ import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 @MessageResolution(receiverType = RFunction.class, language = TruffleRLanguage.class)
 public class RFunctionMR {
@@ -54,9 +55,9 @@ public class RFunctionMR {
 
     @Resolve(message = "EXECUTE")
     public abstract static class RFunctionExecuteNode extends Node {
-        private static final FrameDescriptor emptyFrameDescriptor = new FrameDescriptor("R interop frame");
-        private static final Object argsIdentifier = new Object();
-        private static final FrameSlot slot = emptyFrameDescriptor.addFrameSlot(argsIdentifier, FrameSlotKind.Object);
+        private static final FrameDescriptor emptyFrameDescriptor = FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<interop>", new FrameDescriptor("R interop frame"));
+        private static final RFrameSlot argsIdentifier = RFrameSlot.createTemp(false);
+        private static final FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(emptyFrameDescriptor, argsIdentifier, FrameSlotKind.Object);
 
         static {
             FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<function>", emptyFrameDescriptor);
@@ -72,10 +73,10 @@ public class RFunctionMR {
 
             RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments, ArgumentsSignature.empty(arguments.length));
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                dummyFrame.setObject(slot, actualArgs);
+                FrameSlotChangeMonitor.setObject(dummyFrame, slot, actualArgs);
                 return call.execute(dummyFrame, receiver);
             } finally {
-                dummyFrame.setObject(slot, null);
+                FrameSlotChangeMonitor.setObject(dummyFrame, slot, null);
             }
         }
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 461f4feb45..29e34173b7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -59,6 +59,7 @@ import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -419,7 +420,7 @@ public class MethodsListDispatch {
         private static Object slotRead(MaterializedFrame currentFrame, FrameDescriptor desc, String name) {
             FrameSlot slot = desc.findFrameSlot(name);
             if (slot != null) {
-                Object res = currentFrame.getValue(slot);
+                Object res = FrameSlotChangeMonitor.getValue(slot, currentFrame);
                 if (res != null) {
                     if (res instanceof RPromise) {
                         res = PromiseHelperNode.evaluateSlowPath(null, (RPromise) res);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
index 19e877dcd4..5902eeab4d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
@@ -77,6 +77,7 @@ import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -274,7 +275,7 @@ public class FrameFunctions {
             ArrayList<String> names = new ArrayList<>();
 
             FrameSlot varArgSlot = cframe.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME);
-            RArgsValuesAndNames varArgParameter = varArgSlot == null ? null : (RArgsValuesAndNames) cframe.getValue(varArgSlot);
+            RArgsValuesAndNames varArgParameter = varArgSlot == null ? null : (RArgsValuesAndNames) FrameSlotChangeMonitor.getValue(varArgSlot, cframe);
 
             for (int i = 0; i < sig.getLength(); i++) {
                 RNode arg = matchedArgNodes[i];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index f9e0d535c6..c03cc95d03 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -47,6 +47,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
@@ -107,7 +108,7 @@ public abstract class Lapply extends RBuiltinNode {
         @Override
         public Object execute(VirtualFrame frame) {
             try {
-                return extractElementNode.apply(frame, frame.getObject(vectorSlot), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
+                return extractElementNode.apply(frame, FrameSlotChangeMonitor.getObject(vectorSlot, frame), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
             } catch (FrameSlotTypeException e) {
                 CompilerDirectives.transferToInterpreter();
                 throw RInternalError.shouldNotReachHere("frame type mismatch in lapply");
@@ -138,11 +139,11 @@ public abstract class Lapply extends RBuiltinNode {
         public abstract Object[] execute(VirtualFrame frame, Object vector, RFunction function);
 
         protected static FrameSlot createIndexSlot(Frame frame) {
-            return frame.getFrameDescriptor().findOrAddFrameSlot(INDEX_NAME, FrameSlotKind.Int);
+            return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), INDEX_NAME, FrameSlotKind.Int);
         }
 
         protected static FrameSlot createVectorSlot(Frame frame) {
-            return frame.getFrameDescriptor().findOrAddFrameSlot(VECTOR_NAME, FrameSlotKind.Object);
+            return FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), VECTOR_NAME, FrameSlotKind.Object);
         }
 
         @Specialization
@@ -154,7 +155,7 @@ public abstract class Lapply extends RBuiltinNode {
                         @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode firstCallNode,
                         @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode callNode) {
             // TODO: R switches to double if x.getLength() is greater than 2^31-1
-            frame.setObject(vectorSlot, vector);
+            FrameSlotChangeMonitor.setObject(frame, vectorSlot, vector);
             int length = lengthNode.executeInteger(frame, vector);
             Object[] result = new Object[length];
             if (length > 0) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
index 552a480a2c..5c0d083ede 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
@@ -51,6 +51,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -194,7 +195,7 @@ public abstract class MatchFun extends RBuiltinNode {
             if (slot == null) {
                 return null;
             } else {
-                return frame.getValue(slot);
+                return FrameSlotChangeMonitor.getValue(slot, frame);
             }
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index 993863cf59..2eb897b4f8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -22,52 +22,42 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.util.ArrayList;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.FrameSlotNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
-import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
-import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
-/**
- * Placeholder. {@code on.exit} is special (cf {@code .Internal} in that {@code expr} is not
- * evaluated, but {@code add} is. TODO arrange for the {@code expr} be stored with the currently
- * evaluating function using a new slot in {@link RArguments} and run it on function exit.
- */
 @RBuiltin(name = "on.exit", visibility = OFF, kind = PRIMITIVE, parameterNames = {"expr", "add"}, nonEvalArgs = 0, behavior = COMPLEX)
 public abstract class OnExit extends RBuiltinNode {
 
-    @Child private FrameSlotNode onExitSlot = FrameSlotNode.create(RFrameSlot.OnExit, true);
+    @CompilationFinal private FrameSlot onExitSlot;
 
     private final ConditionProfile addProfile = ConditionProfile.createBinaryProfile();
-    private final ConditionProfile existingProfile = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile newProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile emptyPromiseProfile = ConditionProfile.createBinaryProfile();
-    private final NAProfile na = NAProfile.create();
-
-    private final BranchProfile invalidateProfile = BranchProfile.create();
 
     static {
         Casts casts = new Casts(OnExit.class);
-        casts.arg("add").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE);
+        casts.arg("add").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
     }
 
     @Override
@@ -75,43 +65,40 @@ public abstract class OnExit extends RBuiltinNode {
         return new Object[]{RNull.instance, RRuntime.LOGICAL_FALSE};
     }
 
+    @SuppressWarnings("unchecked")
     @Specialization
-    protected Object onExit(VirtualFrame frame, RPromise expr, byte add) {
+    protected Object onExit(VirtualFrame frame, RPromise expr, boolean add) {
 
-        if (na.isNA(add)) {
-            throw error(RError.Message.INVALID_ARGUMENT, "add");
+        if (onExitSlot == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            onExitSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.OnExit, FrameSlotKind.Object);
         }
 
         // the empty (RNull.instance) expression is used to clear on.exit
-        boolean empty = emptyPromiseProfile.profile(expr.isDefaultArgument());
-
-        assert !empty || expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise";
-        assert empty || !expr.isEvaluated() : "promise cannot already be evaluated";
-
-        ArrayList<Object> current;
-        FrameSlot slot = onExitSlot.executeFrameSlot(frame);
-        if (existingProfile.profile(onExitSlot.hasValue(frame))) {
-            current = getCurrentList(frame, slot);
-            if (addProfile.profile(!RRuntime.fromLogical(add))) {
-                // add is false, so clear the existing
-                current.clear();
-            }
+        if (emptyPromiseProfile.profile(expr.isDefaultArgument())) {
+            assert expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise";
+            frame.setObject(onExitSlot, new ArrayList<>());
         } else {
-            // initialize the list of exit handlers
-            FrameSlotChangeMonitor.setObjectAndInvalidate(frame, slot, current = new ArrayList<>(), false, invalidateProfile);
-        }
-        if (!empty) {
-            current.add(expr.getRep());
+            assert !expr.isEvaluated() : "promise cannot already be evaluated";
+            Object value;
+            try {
+                value = frame.getObject(onExitSlot);
+            } catch (FrameSlotTypeException e) {
+                throw RInternalError.shouldNotReachHere();
+            }
+            ArrayList<Object> list;
+            if (newProfile.profile(value == null)) {
+                // initialize the list of exit handlers
+                frame.setObject(onExitSlot, list = new ArrayList<>());
+            } else {
+                list = (ArrayList<Object>) value;
+                if (addProfile.profile(!add)) {
+                    // add is false, so clear the existing list
+                    list.clear();
+                }
+            }
+            list.add(expr.getRep());
         }
         return RNull.instance;
     }
-
-    @SuppressWarnings("unchecked")
-    private static ArrayList<Object> getCurrentList(VirtualFrame frame, FrameSlot slot) {
-        try {
-            return (ArrayList<Object>) frame.getObject(slot);
-        } catch (FrameSlotTypeException e) {
-            throw RInternalError.shouldNotReachHere();
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
index d534173f4d..e699b28a72 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java
@@ -118,7 +118,7 @@ abstract class BaseWriteVariableNode extends WriteVariableNode {
 
     private boolean isCurrentValue(Frame frame, FrameSlot frameSlot, Object value) {
         try {
-            return isObjectProfile.profile(frame.isObject(frameSlot)) && isCurrentProfile.profile(frame.getObject(frameSlot) == value);
+            return isObjectProfile.profile(frame.isObject(frameSlot)) && isCurrentProfile.profile(FrameSlotChangeMonitor.getObject(frameSlot, frame) == value);
         } catch (FrameSlotTypeException ex) {
             throw RInternalError.shouldNotReachHere();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
index e9ec3546f2..c54c9f419a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.access;
 
-import static com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.findOrAddFrameSlot;
-
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -37,6 +35,7 @@ import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -58,19 +57,23 @@ public abstract class FrameSlotNode extends RBaseNode {
         return new UnresolvedFrameSlotNode(name, createIfAbsent);
     }
 
-    public static FrameSlotNode createTemp(Object name, boolean createIfAbsent) {
-        return new UnresolvedFrameSlotNode(name, createIfAbsent);
-    }
-
     public static FrameSlotNode create(RFrameSlot slot, boolean createIfAbsent) {
         return new UnresolvedFrameSlotNode(slot, createIfAbsent);
     }
 
-    public static FrameSlotNode createInitialized(FrameDescriptor frameDescriptor, Object identifier, boolean createIfAbsent) {
+    public static FrameSlotNode createInitialized(FrameDescriptor frameDescriptor, RFrameSlot identifier, boolean createIfAbsent) {
+        return createInitializedInternal(frameDescriptor, identifier, createIfAbsent);
+    }
+
+    private static FrameSlotNode createInitializedInternal(FrameDescriptor frameDescriptor, Object identifier, boolean createIfAbsent) {
         FrameSlotNode newNode;
         FrameSlot frameSlot;
         if (createIfAbsent) {
-            frameSlot = findOrAddFrameSlot(frameDescriptor, identifier, FrameSlotKind.Illegal);
+            if (identifier instanceof String) {
+                frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, (String) identifier, FrameSlotKind.Illegal);
+            } else {
+                frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frameDescriptor, (RFrameSlot) identifier, FrameSlotKind.Illegal);
+            }
         } else {
             frameSlot = frameDescriptor.findFrameSlot(identifier);
         }
@@ -112,7 +115,7 @@ public abstract class FrameSlotNode extends RBaseNode {
         private FrameSlotNode resolveFrameSlot(Frame frame) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             FrameDescriptor frameDescriptor = frame.getFrameDescriptor();
-            FrameSlotNode newNode = createInitialized(frameDescriptor, identifier, createIfAbsent);
+            FrameSlotNode newNode = createInitializedInternal(frameDescriptor, identifier, createIfAbsent);
             return replace(newNode);
         }
     }
@@ -174,7 +177,8 @@ public abstract class FrameSlotNode extends RBaseNode {
         public boolean hasValue(Frame frame) {
             try {
                 Frame typedFrame = frameTypeProfile.profile(frame);
-                return !isObjectProfile.profile(typedFrame.isObject(frameSlot)) || isNullProfile.profile(typedFrame.getObject(frameSlot) != null);
+                return !isObjectProfile.profile(typedFrame.isObject(frameSlot)) ||
+                                isNullProfile.profile(FrameSlotChangeMonitor.getObject(frameSlot, typedFrame) != null);
             } catch (FrameSlotTypeException e) {
                 throw new IllegalStateException();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
index d019c7e235..de421491f5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
@@ -104,7 +104,7 @@ public abstract class RemoveAndAnswerNode extends RNode {
         protected Object doObject(VirtualFrame frame) {
             Object result;
             try {
-                result = frame.getObject(slot);
+                result = FrameSlotChangeMonitor.getObject(slot, frame);
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
index 6d215ddd2a..a389e83a42 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java
@@ -146,7 +146,7 @@ abstract class WriteSuperFrameVariableNode extends BaseWriteVariableNode {
                 writeNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, rhs, enclosingFrameNode,
                                 FrameSlotNode.create(findOrAddFrameSlot(enclosingFrame.getFrameDescriptor(), getName(), FrameSlotKind.Illegal)));
             } else {
-                ResolvedWriteSuperFrameVariableNode actualWriteNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, null, null, FrameSlotNode.createTemp(getName(), false));
+                ResolvedWriteSuperFrameVariableNode actualWriteNode = ResolvedWriteSuperFrameVariableNodeGen.create(getName(), mode, null, null, FrameSlotNode.create(getName(), false));
                 writeNode = new WriteSuperFrameVariableConditionalNode(getName(), actualWriteNode, new UnresolvedWriteSuperFrameVariableNode(getName(), mode, null), rhs);
             }
             replace(writeNode).execute(frame, value, enclosingFrame);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index 2820805cbd..f9e15b0a6b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -466,7 +466,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
                 }
             }
             if (frameSlot != null) {
-                Object value = variableFrame.getValue(frameSlot);
+                Object value = FrameSlotChangeMonitor.getObject(frameSlot, variableFrame);
                 if (checkType(frame, value, isNullProfile)) {
                     return value;
                 }
@@ -490,7 +490,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         @TruffleBoundary
         private Object getValue(MaterializedFrame current) {
             FrameSlot slot = current.getFrameDescriptor().findFrameSlot(identifier);
-            return slot == null ? null : current.getValue(slot);
+            return slot == null ? null : FrameSlotChangeMonitor.getValue(slot, current);
         }
 
         @Override
@@ -700,7 +700,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
             // see if the current frame has a value of the given name
             FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(identifier);
             if (frameSlot != null) {
-                Object value = current.getValue(frameSlot);
+                Object value = FrameSlotChangeMonitor.getValue(frameSlot, current);
 
                 if (value != null) {
                     if (value == RMissing.instance) {
@@ -739,7 +739,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
             // see if the current frame has a value of the given name
             FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(identifier);
             if (frameSlot != null) {
-                Object value = current.getValue(frameSlot);
+                Object value = FrameSlotChangeMonitor.getValue(frameSlot, current);
 
                 if (value != null) {
                     if (value == RMissing.instance) {
@@ -766,7 +766,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
             // see if the current frame has a value of the given name
             FrameSlot frameSlot = current.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME);
             if (frameSlot != null) {
-                Object value = current.getValue(frameSlot);
+                Object value = FrameSlotChangeMonitor.getValue(frameSlot, current);
 
                 if (value != null) {
                     if (value == RNull.instance) {
@@ -787,6 +787,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         assert variableFrame.getFrameDescriptor() == frameSlot.getFrameDescriptor();
         Object value = variableFrame.getValue(frameSlot);
         if (variableFrame.isObject(frameSlot)) {
+            value = FrameSlotChangeMonitor.getValue(frameSlot, variableFrame);
             seenValueKinds[FrameSlotKind.Object.ordinal()] = true;
         } else if (variableFrame.isByte(frameSlot)) {
             seenValueKinds[FrameSlotKind.Byte.ordinal()] = true;
@@ -802,7 +803,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         assert variableFrame.getFrameDescriptor() == frameSlot.getFrameDescriptor();
         try {
             if (seenValueKinds[FrameSlotKind.Object.ordinal()] && variableFrame.isObject(frameSlot)) {
-                return variableFrame.getObject(frameSlot);
+                return FrameSlotChangeMonitor.getObject(frameSlot, variableFrame);
             } else if (seenValueKinds[FrameSlotKind.Byte.ordinal()] && variableFrame.isByte(frameSlot)) {
                 return variableFrame.getByte(frameSlot);
             } else if (seenValueKinds[FrameSlotKind.Int.ordinal()] && variableFrame.isInt(frameSlot)) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index f03c7f17e1..67abd02ebd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
@@ -58,6 +59,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
@@ -285,7 +287,8 @@ public class ArgumentMatcher {
             Frame frame = Utils.getActualCurrentFrame();
             try {
                 // TODO: this error handling code takes many assumptions about the argument types
-                RArgsValuesAndNames varArg = (RArgsValuesAndNames) frame.getObject(frame.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME));
+                FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(ArgumentsSignature.VARARG_NAME);
+                RArgsValuesAndNames varArg = (RArgsValuesAndNames) FrameSlotChangeMonitor.getObject(frameSlot, frame);
                 RPromise promise = (RPromise) varArg.getArguments()[((VarArgNode) node).getIndex()];
                 return RDeparse.deparseSyntaxElement(promise.getRep().asRSyntaxNode());
             } catch (FrameSlotTypeException | ClassCastException e) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 984dce3f21..569f39f84f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -431,7 +431,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
     @SuppressWarnings("unchecked")
     private static ArrayList<Object> getCurrentOnExitList(VirtualFrame frame, FrameSlot slot) {
         try {
-            return (ArrayList<Object>) frame.getObject(slot);
+            return (ArrayList<Object>) FrameSlotChangeMonitor.getObject(slot, frame);
         } catch (FrameSlotTypeException e) {
             throw RInternalError.shouldNotReachHere();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java
index 96c960da3e..d8cffeb8f5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetMissingValueNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
@@ -78,7 +79,7 @@ public abstract class GetMissingValueNode extends RBaseNode {
             }
             if (isObjectProfile.profile(frame.isObject(slot))) {
                 try {
-                    return frame.getObject(slot);
+                    return FrameSlotChangeMonitor.getObject(slot, frame);
                 } catch (FrameSlotTypeException e) {
                     return null;
                 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
index d32cd3d80d..bb1d668a60 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  */
 public final class PostProcessArgumentsNode extends RNode {
 
-    @CompilationFinal private final FrameSlot[] frameSlots;
+    @CompilationFinal(dimensions = 1) private final FrameSlot[] frameSlots;
 
     // stays the same during cloning
     private final AssumedValue<Integer> transArgsBitSet;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index 303eef2165..f2407db524 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -51,6 +51,7 @@ import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
@@ -101,7 +102,7 @@ public class PromiseHelperNode extends RBaseNode {
 
                 // Try to read it...
                 try {
-                    Object value = frame.getObject(slot);
+                    Object value = FrameSlotChangeMonitor.getObject(slot, frame);
 
                     // If it's a promise, deoptimize it!
                     if (value instanceof RPromise) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index a921d98f18..1350b4bd2a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -96,6 +96,7 @@ import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RFastPathNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -640,7 +641,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         @Override
         public Object execute(VirtualFrame frame) {
             try {
-                return frame.getObject(slot);
+                return FrameSlotChangeMonitor.getObject(slot, frame);
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
index 5a6a72b6b0..9516238bf6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 /**
  * This class implements the behavior for {@link RMissing} which is needed inside this module, as it
@@ -91,7 +92,7 @@ public class RMissingHelper {
 
         // Read name's value
         try {
-            return frame.getObject(frameSlot);
+            return FrameSlotChangeMonitor.getObject(frameSlot, frame);
         } catch (FrameSlotTypeException e) {
             return null;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java
index bbce4bf49e..e7921cf9d3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class S3FunctionLookupNode extends RBaseNode {
@@ -437,7 +438,7 @@ public abstract class S3FunctionLookupNode extends RBaseNode {
                     return null;
                 }
                 try {
-                    return genericDefFrame.getObject(slot);
+                    return FrameSlotChangeMonitor.getObject(slot, genericDefFrame);
                 } catch (FrameSlotTypeException e) {
                     throw RInternalError.shouldNotReachHere();
                 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java
index 03e13b0d06..1d7589976a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,10 +30,12 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 public final class TemporarySlotNode extends Node {
 
-    private static final Object[] defaultTempIdentifiers = new Object[]{new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object()};
+    private static final RFrameSlot[] defaultTempIdentifiers = new RFrameSlot[]{RFrameSlot.createTemp(true), RFrameSlot.createTemp(true), RFrameSlot.createTemp(true), RFrameSlot.createTemp(true)};
 
     @CompilationFinal private FrameSlot tempSlot;
     private int tempIdentifier;
@@ -41,7 +43,7 @@ public final class TemporarySlotNode extends Node {
     public FrameSlot initialize(VirtualFrame frame, Object value) {
         if (tempSlot == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            tempSlot = frame.getFrameDescriptor().findOrAddFrameSlot(defaultTempIdentifiers[0], FrameSlotKind.Object);
+            tempSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), defaultTempIdentifiers[0], FrameSlotKind.Object);
         }
         FrameSlot slot = tempSlot;
         try {
@@ -50,8 +52,8 @@ public final class TemporarySlotNode extends Node {
                 // keep the complete loop in the slow path
                 do {
                     tempIdentifier++;
-                    Object identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object();
-                    tempSlot = slot = frame.getFrameDescriptor().findOrAddFrameSlot(identifier, FrameSlotKind.Object);
+                    RFrameSlot identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : RFrameSlot.createTemp(true);
+                    tempSlot = slot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), identifier, FrameSlotKind.Object);
                     if (frame.getObject(slot) == null) {
                         break;
                     }
@@ -61,16 +63,16 @@ public final class TemporarySlotNode extends Node {
             CompilerDirectives.transferToInterpreter();
             throw RInternalError.shouldNotReachHere();
         }
-        frame.setObject(slot, value);
+        FrameSlotChangeMonitor.setObject(frame, slot, value);
         return slot;
     }
 
     public static void cleanup(VirtualFrame frame, Object object, FrameSlot tempSlot) {
         try {
-            assert frame.getObject(tempSlot) == object;
+            assert FrameSlotChangeMonitor.getObject(tempSlot, frame) == object;
         } catch (FrameSlotTypeException e) {
             throw RInternalError.shouldNotReachHere();
         }
-        frame.setObject(tempSlot, null);
+        FrameSlotChangeMonitor.setObject(frame, tempSlot, null);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java
index 7f6354db2f..b856c58620 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java
@@ -22,50 +22,52 @@
  */
 package com.oracle.truffle.r.nodes.function.call;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.FrameSlot;
+import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.access.FrameSlotNode;
 import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 /**
  * Helper node that allows to call a given function with explicit arguments.
  */
 public abstract class RExplicitCallNode extends Node {
+
     public static RExplicitCallNode create() {
         return RExplicitCallNodeGen.create();
     }
 
     public abstract Object execute(VirtualFrame frame, RFunction function, RArgsValuesAndNames args);
 
+    private final RFrameSlot argsIdentifier = RFrameSlot.createTemp(true);
+    @CompilationFinal private FrameSlot argsFrameSlot;
+
     @Specialization
-    Object doCall(VirtualFrame frame, RFunction function, RArgsValuesAndNames args,
-                    @SuppressWarnings("unused") @Cached("createArgsIdentifier()") Object argsIdentifier,
-                    @Cached("createExplicitCall(argsIdentifier)") RCallBaseNode call,
-                    @Cached("createFrameSlotNode(argsIdentifier)") FrameSlotNode argumentsSlot) {
-        FrameSlot argsFrameSlot = argumentsSlot.executeFrameSlot(frame);
+    protected Object doCall(VirtualFrame frame, RFunction function, RArgsValuesAndNames args,
+                    @Cached("createExplicitCall()") RCallBaseNode call) {
+        if (argsFrameSlot == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            argsFrameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), argsIdentifier, FrameSlotKind.Object);
+        }
         try {
             frame.setObject(argsFrameSlot, args);
+            FrameSlotChangeMonitor.setObject(frame, argsFrameSlot, args);
             return call.execute(frame, function);
         } finally {
-            frame.setObject(argsFrameSlot, null);
+            FrameSlotChangeMonitor.setObject(frame, argsFrameSlot, null);
         }
     }
 
-    static Object createArgsIdentifier() {
-        return new Object();
-    }
-
-    static RCallBaseNode createExplicitCall(Object argsIdentifier) {
+    protected RCallBaseNode createExplicitCall() {
         return RCallNode.createExplicitCall(argsIdentifier);
     }
-
-    static FrameSlotNode createFrameSlotNode(Object argsIdentifier) {
-        return FrameSlotNode.createTemp(argsIdentifier, true);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java
index 0be21e8e3d..9b7f425210 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public abstract class CollectArgumentsNode extends RBaseNode {
@@ -88,7 +89,7 @@ public abstract class CollectArgumentsNode extends RBaseNode {
             if (slot == null) {
                 result[i] = RMissing.instance;
             } else {
-                result[i] = frame.getValue(slot);
+                result[i] = FrameSlotChangeMonitor.getValue(slot, frame);
             }
         }
         return result;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java
index 6b57fd298b..f8b51386ac 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 // transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function)
@@ -117,7 +118,7 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode {
             if (slot == null) {
                 result[i] = "missing";
             } else {
-                Object value = frame.getValue(slot);
+                Object value = FrameSlotChangeMonitor.getValue(slot, frame);
                 if (value instanceof RPromise) {
                     value = PromiseHelperNode.evaluateSlowPath(null, (RPromise) value);
                 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index 19bb59be13..d533301e92 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -565,6 +565,7 @@ public final class Utils {
     }
 
     private static void dumpFrame(StringBuilder str, CallTarget callTarget, Frame frame, boolean printFrameSlots, boolean isVirtual) {
+        CompilerAsserts.neverPartOfCompilation();
         try {
             CompilerAsserts.neverPartOfCompilation();
             if (str.length() > 0) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 0f4f3a09ad..323f4d154d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotKind;
+import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.profiles.BranchProfile;
@@ -621,6 +622,10 @@ public final class FrameSlotChangeMonitor {
         checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
     }
 
+    public static void setObject(Frame frame, FrameSlot frameSlot, Object newValue) {
+        frame.setObject(frameSlot, newValue);
+    }
+
     public static void setActiveBinding(Frame frame, FrameSlot frameSlot, ActiveBinding newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
         frame.setObject(frameSlot, newValue);
         FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
@@ -639,8 +644,10 @@ public final class FrameSlotChangeMonitor {
         frameDescriptors.put(handleBaseNamespaceEnv(frame), new FrameDescriptorMetaData(name, frame));
     }
 
-    public static synchronized void initializeFunctionFrameDescriptor(String name, FrameDescriptor frameDescriptor) {
+    public static synchronized FrameDescriptor initializeFunctionFrameDescriptor(String name, FrameDescriptor frameDescriptor) {
+        CompilerAsserts.neverPartOfCompilation();
         frameDescriptors.put(frameDescriptor, new FrameDescriptorMetaData(name, null));
+        return frameDescriptor;
     }
 
     public static synchronized Assumption getEnclosingFrameDescriptorAssumption(FrameDescriptor descriptor) {
@@ -672,4 +679,12 @@ public final class FrameSlotChangeMonitor {
     public static boolean isValidFrameDescriptor(FrameDescriptor frameDesc) {
         return getMetaData(frameDesc) != null;
     }
+
+    public static Object getObject(FrameSlot slot, Frame frame) throws FrameSlotTypeException {
+        return frame.getObject(slot);
+    }
+
+    public static Object getValue(FrameSlot slot, Frame frame) {
+        return frame.getValue(slot);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
index 2c62896ff5..cd23e990be 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
@@ -71,7 +71,7 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
         if (slot == null) {
             return null;
         } else {
-            Object value = frame.getValue(slot);
+            Object value = FrameSlotChangeMonitor.getValue(slot, frame);
             // special treatment for active binding: call bound function
             if (ActiveBinding.isActiveBinding(value)) {
                 return ((ActiveBinding) value).readValue();
@@ -159,7 +159,8 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
         ArrayList<String> matchedNamesList = new ArrayList<>(names.length);
         for (int i = 0; i < names.length; i++) {
             String name = names[i];
-            if (frame.getValue(fd.findFrameSlot(name)) == null) {
+            FrameSlot frameSlot = fd.findFrameSlot(name);
+            if (FrameSlotChangeMonitor.getValue(frameSlot, frame) == null) {
                 continue;
             }
             if (REnvironment.includeName(name, allNames, pattern)) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java
index e303fac170..9b407b1536 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,37 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  * Description of different internal frame slots used by FastR. This enum is used as an identifier,
  * so that these internal frame slots have non-string names.
  */
-public enum RFrameSlot {
+public final class RFrameSlot {
+    private final String name;
+    private final boolean multiSlot;
+
+    private RFrameSlot(String name, boolean multiSlot) {
+        this.name = name;
+        this.multiSlot = multiSlot;
+    }
+
+    @Override
+    public String toString() {
+        return name == null ? "TempFrameSlot" : name;
+    }
+
+    public boolean isTemp() {
+        return name == null;
+    }
+
+    public boolean isMultiSlot() {
+        return multiSlot;
+    }
+
+    public static RFrameSlot createTemp(boolean multiSlot) {
+        return new RFrameSlot(null, multiSlot);
+    }
+
     /**
      * This frame slot is used to store expressions installed as function exit handlers via on.exit.
      * It contains an {@link ArrayList} with {@link RNode} elements.
      */
-    OnExit,
+    public static final RFrameSlot OnExit = new RFrameSlot("OnExit", false);
     /**
      * This frame slot is used to track result visibility. It can contain one of three values:
      * <ul>
@@ -51,13 +76,17 @@ public enum RFrameSlot {
      * each call site, the value of {@link RCaller#getVisibility()} is extracted and stored into the
      * frame slot.
      */
-    Visibility,
+    public static final RFrameSlot Visibility = new RFrameSlot("Visibility", false);
     /**
      * Used to save the handler stack in frames that modify it.
      */
-    HandlerStack,
+    public static final RFrameSlot HandlerStack = new RFrameSlot("HandlerStack", false);
     /**
      * Used to save the restart stack in frames that modify it.
      */
-    RestartStack
+    public static final RFrameSlot RestartStack = new RFrameSlot("RestartStack", false);
+
+    public static RFrameSlot[] values() {
+        return new RFrameSlot[]{OnExit, Visibility, HandlerStack, RestartStack};
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 02ccdb2128..131551f152 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -270,7 +270,7 @@ public class FastRDebugTest {
                 frame.forEach(var -> {
                     // skip synthetic slots
                     for (RFrameSlot slot : RFrameSlot.values()) {
-                        if (slot.name().equals(var.getName())) {
+                        if (slot.toString().equals(var.getName())) {
                             return;
                         }
                     }
-- 
GitLab


From 079b538e2fd04fb5e650e449622ed176a6c50687 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 7 Apr 2017 16:07:07 +0200
Subject: [PATCH 280/402] fix imports

---
 .../truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java | 1 -
 .../truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java     | 1 -
 .../src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java     | 1 -
 .../oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java    | 1 -
 4 files changed, 4 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
index 39eeb2a3ea..8a69a8d47b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 /**
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
index 0ec6f4d2ef..2621894a90 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 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.java.JavaInterop;
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 75132c6fe4..6fe58f99a7 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
index 03d88811d9..425f866ead 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
@@ -30,7 +30,6 @@ import java.util.Comparator;
 
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
 import com.oracle.truffle.r.runtime.ffi.RFFICstring;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
  * Generates the entries for {@link RFFIUpCallMethod}.
-- 
GitLab


From dce74700381839097e18e0e0b6f038cc0ac77f7b Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 7 Apr 2017 12:01:38 +0200
Subject: [PATCH 281/402] better handling of handler stack slots in
 FunctionDefinitionNode

---
 .../function/FunctionDefinitionNode.java      | 38 ++++++++++++-------
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 569f39f84f..37ff3d56af 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -299,18 +299,24 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
             }
             if (runOnExitHandlers) {
                 visibility.executeEndOfFunction(frame);
-                if (!noHandlerStackSlot.isValid() && frame.isObject(handlerStackSlot)) {
-                    try {
-                        RErrorHandling.restoreHandlerStack(frame.getObject(handlerStackSlot));
-                    } catch (FrameSlotTypeException e) {
-                        throw RInternalError.shouldNotReachHere();
+                if (!noHandlerStackSlot.isValid()) {
+                    FrameSlot slot = getHandlerFrameSlot(frame);
+                    if (frame.isObject(slot)) {
+                        try {
+                            RErrorHandling.restoreHandlerStack(frame.getObject(slot));
+                        } catch (FrameSlotTypeException e) {
+                            throw RInternalError.shouldNotReachHere();
+                        }
                     }
                 }
-                if (!noRestartStackSlot.isValid() && frame.isObject(restartStackSlot)) {
-                    try {
-                        RErrorHandling.restoreRestartStack(frame.getObject(restartStackSlot));
-                    } catch (FrameSlotTypeException e) {
-                        throw RInternalError.shouldNotReachHere();
+                if (!noRestartStackSlot.isValid()) {
+                    FrameSlot slot = getRestartFrameSlot(frame);
+                    if (frame.isObject(slot)) {
+                        try {
+                            RErrorHandling.restoreRestartStack(frame.getObject(slot));
+                        } catch (FrameSlotTypeException e) {
+                            throw RInternalError.shouldNotReachHere();
+                        }
                     }
                 }
 
@@ -491,20 +497,24 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
     public FrameSlot getRestartFrameSlot(VirtualFrame frame) {
         if (noRestartStackSlot.isValid()) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            restartStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.RestartStack);
             noRestartStackSlot.invalidate();
         }
-        assert restartStackSlot != null;
+        if (restartStackSlot == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            restartStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.RestartStack);
+        }
         return restartStackSlot;
     }
 
     public FrameSlot getHandlerFrameSlot(VirtualFrame frame) {
         if (noHandlerStackSlot.isValid()) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            handlerStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.HandlerStack);
             noHandlerStackSlot.invalidate();
         }
-        assert handlerStackSlot != null;
+        if (handlerStackSlot == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            handlerStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.HandlerStack);
+        }
         return handlerStackSlot;
     }
 }
-- 
GitLab


From f679811dcd83f132702aa994f57676ea329fc1d4 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 7 Apr 2017 12:01:06 +0200
Subject: [PATCH 282/402] add several assertions

---
 .../com/oracle/truffle/r/nodes/function/ArgumentMatcher.java    | 1 +
 .../src/com/oracle/truffle/r/nodes/function/RMissingHelper.java | 2 ++
 .../truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java     | 1 +
 3 files changed, 4 insertions(+)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index f03c7f17e1..c9ae35ee51 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -279,6 +279,7 @@ public class ArgumentMatcher {
     }
 
     private static String getErrorForArgument(RNode[] suppliedArgs, ArgumentsSignature suppliedSignature, int index) {
+        CompilerAsserts.neverPartOfCompilation();
         RNode node = suppliedArgs[index];
         if (node instanceof VarArgNode) {
             CompilerAsserts.neverPartOfCompilation();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
index 5a6a72b6b0..9632968f83 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.function;
 
+import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
@@ -83,6 +84,7 @@ public class RMissingHelper {
      *         type is not object.
      */
     public static Object getMissingValue(Frame frame, String name) {
+        CompilerAsserts.neverPartOfCompilation();
         // Check binding
         FrameSlot frameSlot = frame.getFrameDescriptor().findFrameSlot(name);
         if (frameSlot == null) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
index 2c62896ff5..b792b6ec4f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java
@@ -66,6 +66,7 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess {
 
     @Override
     public Object get(String key) {
+        CompilerAsserts.neverPartOfCompilation();
         FrameDescriptor fd = frame.getFrameDescriptor();
         FrameSlot slot = fd.findFrameSlot(key);
         if (slot == null) {
-- 
GitLab


From 2a6f34347b746a6d5e70ac1dc0d59801772c1b54 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 7 Apr 2017 12:02:01 +0200
Subject: [PATCH 283/402] read values only once in FastROptions

---
 .../truffle/r/runtime/FastROptions.java       | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 636cfb2009..688fd6c0e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -81,8 +81,9 @@ public enum FastROptions {
 
     public boolean getBooleanValue() {
         assert isBoolean;
-        if (value instanceof Boolean) {
-            return (Boolean) value;
+        Object v = value;
+        if (v instanceof Boolean) {
+            return (boolean) v;
         } else {
             CompilerDirectives.transferToInterpreter();
             System.out.println("boolean option value expected with " + name() + " - forgot +/- ?");
@@ -93,8 +94,9 @@ public enum FastROptions {
 
     public String getStringValue() {
         assert !isBoolean;
-        if (value == null || value instanceof String) {
-            return (String) value;
+        Object v = value;
+        if (v == null || v instanceof String) {
+            return (String) v;
         } else {
             CompilerDirectives.transferToInterpreter();
             System.out.println("string option value expected with " + name());
@@ -105,13 +107,14 @@ public enum FastROptions {
 
     public int getNonNegativeIntValue() {
         assert !isBoolean;
-        if (value instanceof Integer) {
-            return (Integer) value;
+        Object v = value;
+        if (v instanceof Integer) {
+            return (Integer) v;
         }
         CompilerDirectives.transferToInterpreterAndInvalidate();
-        if (value instanceof String) {
+        if (v instanceof String) {
             try {
-                int res = Integer.decode((String) value);
+                int res = Integer.decode((String) v);
                 if (res >= 0) {
                     value = res;
                     return res;
-- 
GitLab


From f7bba4eba26f968ebb842fe82af8ad77992aece9 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 10 Apr 2017 13:27:28 +0200
Subject: [PATCH 284/402] Inserted class profile for vector in bind functions.

---
 .../src/com/oracle/truffle/r/nodes/builtin/base/Bind.java     | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 5a783d9fc9..bf6d37a34c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -195,9 +195,9 @@ public abstract class Bind extends RBaseNode {
         boolean rowsAndColumnsNotEqual = getResultDimensions(vectors, resultDimensions, bindDims);
         RVector<?> resultVec;
         if (fromNotNullArgVector != null) {
-            resultVec = resultProfile.profile(fromNotNullArgVector.createEmptySameType(resultDimensions[0] * resultDimensions[1], complete));
+            resultVec = resultProfile.profile(vectorProfile.profile(fromNotNullArgVector).createEmptySameType(resultDimensions[0] * resultDimensions[1], complete));
         } else {
-            resultVec = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete));
+            resultVec = resultProfile.profile(vectorProfile.profile(vectors[0]).createEmptySameType(resultDimensions[0] * resultDimensions[1], complete));
         }
 
         if (type == BindType.cbind) {
-- 
GitLab


From d9e18431c7184655544c3e2a10fce545b929e1d5 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 3 Mar 2017 13:15:45 +0100
Subject: [PATCH 285/402] class cache in Unique

---
 .../truffle/r/nodes/builtin/base/Unique.java   | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
index 8898ee1611..88a1f1c89d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java
@@ -93,8 +93,11 @@ public abstract class Unique extends RBuiltinNode {
     }
 
     @SuppressWarnings("unused")
-    @Specialization
-    protected RStringVector doUnique(RAbstractStringVector vec, byte incomparables, byte fromLast, int nmax) {
+    @Specialization(guards = "vecIn.getClass() == vecClass")
+    protected RStringVector doUniqueCachedString(RAbstractStringVector vecIn, byte incomparables, byte fromLast, int nmax,
+                    @Cached("vecIn.getClass()") Class<? extends RAbstractStringVector> vecClass) {
+        RAbstractStringVector vec = vecClass.cast(vecIn);
+        reportWork(vec.getLength());
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSet<String> set = new NonRecursiveHashSet<>(vec.getLength());
             String[] data = new String[vec.getLength()];
@@ -120,6 +123,11 @@ public abstract class Unique extends RBuiltinNode {
         }
     }
 
+    @Specialization(replaces = "doUniqueCachedString")
+    protected RStringVector doUnique(RAbstractStringVector vec, byte incomparables, byte fromLast, int nmax) {
+        return doUniqueCachedString(vec, incomparables, fromLast, nmax, RAbstractStringVector.class);
+    }
+
     // these are intended to stay private as they will go away once we figure out which external
     // library to use
 
@@ -245,6 +253,7 @@ public abstract class Unique extends RBuiltinNode {
     protected RIntVector doUniqueCached(RAbstractIntVector vecIn, byte incomparables, byte fromLast, int nmax,
                     @Cached("vecIn.getClass()") Class<? extends RAbstractIntVector> vecClass) {
         RAbstractIntVector vec = vecClass.cast(vecIn);
+        reportWork(vec.getLength());
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSetInt set = new NonRecursiveHashSetInt();
             int[] data = new int[16];
@@ -296,6 +305,7 @@ public abstract class Unique extends RBuiltinNode {
     @Specialization(guards = "!lengthOne(list)")
     @TruffleBoundary
     protected RList doUnique(RList list, byte incomparables, byte fromLast, int nmax) {
+        reportWork(list.getLength());
         /*
          * Brute force, as manual says: Using this for lists is potentially slow, especially if the
          * elements are not atomic vectors (see vector) or differ only in their attributes. In the
@@ -375,6 +385,7 @@ public abstract class Unique extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization
     protected RDoubleVector doUnique(RAbstractDoubleVector vec, byte incomparables, byte fromLast, int nmax) {
+        reportWork(vec.getLength());
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSetDouble set = new NonRecursiveHashSetDouble(vec.getLength());
             double[] data = new double[vec.getLength()];
@@ -401,6 +412,7 @@ public abstract class Unique extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization
     protected RLogicalVector doUnique(RAbstractLogicalVector vec, byte incomparables, byte fromLast, int nmax) {
+        reportWork(vec.getLength());
         ByteArray dataList = new ByteArray(vec.getLength());
         for (int i = 0; i < vec.getLength(); i++) {
             byte val = vec.getDataAt(i);
@@ -414,6 +426,7 @@ public abstract class Unique extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization
     protected RComplexVector doUnique(RAbstractComplexVector vec, byte incomparables, byte fromLast, int nmax) {
+        reportWork(vec.getLength());
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSet<RComplex> set = new NonRecursiveHashSet<>(vec.getLength());
             double[] data = new double[vec.getLength() * 2];
@@ -441,6 +454,7 @@ public abstract class Unique extends RBuiltinNode {
     @SuppressWarnings("unused")
     @Specialization
     protected RRawVector doUnique(RAbstractRawVector vec, byte incomparables, byte fromLast, int nmax) {
+        reportWork(vec.getLength());
         if (bigProfile.profile(vec.getLength() * (long) vec.getLength() > BIG_THRESHOLD)) {
             NonRecursiveHashSet<RRaw> set = new NonRecursiveHashSet<>(vec.getLength());
             byte[] data = new byte[vec.getLength()];
-- 
GitLab


From c2fa3e626571ba1a9efe6e2b1368b5c1c4013946 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 5 Apr 2017 17:40:32 +0200
Subject: [PATCH 286/402] fixes in LogFunctions, CastStringNode and Order

---
 .../r/nodes/builtin/base/LogFunctions.java    | 114 +++++-------------
 .../truffle/r/nodes/builtin/base/Order.java   |  19 ++-
 .../truffle/r/nodes/unary/CastStringNode.java |   5 +-
 3 files changed, 39 insertions(+), 99 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 3bce1da46d..7379a4c28d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -28,9 +28,13 @@ import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import java.util.Arrays;
+
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.CopyOfRegAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
@@ -49,14 +53,10 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
-import java.util.Arrays;
-import java.util.function.Function;
 
 public class LogFunctions {
     @RBuiltin(name = "log", kind = PRIMITIVE, parameterNames = {"x", "base"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
@@ -158,103 +158,47 @@ public class LogFunctions {
             return logb(x, base, divNode, naBase);
         }
 
-        @Specialization
-        protected RDoubleVector log(RAbstractIntVector vector, double base,
+        @Specialization(guards = "!isRAbstractComplexVector(vector)")
+        protected RDoubleVector log(RAbstractVector vector, double base,
+                        @Cached("createClassProfile()") ValueProfile vectorProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
                         @Cached("create()") GetNamesAttributeNode getNamesNode,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("create()") NACheck xNACheck,
                         @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> xNACheck.convertIntToDouble(vector.getDataAt(index)), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
-        }
-
-        @Specialization
-        protected RDoubleVector log(RAbstractDoubleVector vector, double base,
-                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
-                        @Cached("create()") NACheck xNACheck,
-                        @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> checkDouble(vector.getDataAt(index), xNACheck), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
-        }
-
-        private static double checkDouble(double d, NACheck na) {
-            na.check(d);
-            return d;
-        }
-
-        @Specialization
-        protected RDoubleVector log(RAbstractLogicalVector vector, double base,
-                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
-                        @Cached("create()") NACheck xNACheck,
-                        @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> xNACheck.convertLogicalToDouble(vector.getDataAt(index)), copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
+            RAbstractDoubleVector doubleVector = (RAbstractDoubleVector) vectorProfile.profile(vector).castSafe(RType.Double, isNAProfile);
+            return logInternal(doubleVector, base, copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
         }
 
         @Specialization
         protected RComplexVector log(RAbstractComplexVector vector, double base,
+                        @Cached("createClassProfile()") ValueProfile vectorProfile,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
                         @Cached("create()") GetNamesAttributeNode getNamesNode,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NACheck xNACheck,
                         @Cached("create()") NACheck baseNACheck) {
-            return log(vector, RComplex.valueOf(base, 0), copyAttrsNode, getNamesNode, getDimsNode, divNode, xNACheck, baseNACheck);
+            return logInternal(vectorProfile.profile(vector), RComplex.valueOf(base, 0), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
         }
 
         @Specialization
-        protected RAbstractComplexVector log(RAbstractIntVector vector, RComplex base,
+        protected RAbstractComplexVector log(RAbstractVector vector, RComplex base,
+                        @Cached("createClassProfile()") ValueProfile vectorProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
                         @Cached("create()") GetNamesAttributeNode getNamesNode,
                         @Cached("create()") GetDimAttributeNode getDimsNode,
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NACheck xNACheck,
                         @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> xNACheck.convertIntToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+            RAbstractComplexVector complexVector = (RAbstractComplexVector) vectorProfile.profile(vector).castSafe(RType.Complex, isNAProfile);
+            return logInternal(complexVector, base, divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
         }
 
-        @Specialization
-        protected RAbstractComplexVector log(RAbstractDoubleVector vector, RComplex base,
-                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
-                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
-                        @Cached("create()") NACheck xNACheck,
-                        @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> xNACheck.convertDoubleToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
-        }
-
-        @Specialization
-        protected RAbstractComplexVector log(RAbstractLogicalVector vector, RComplex base,
-                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
-                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
-                        @Cached("create()") NACheck xNACheck,
-                        @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> xNACheck.convertLogicalToComplex(vector.getDataAt(index)), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
-        }
-
-        @Specialization
-        protected RComplexVector log(RAbstractComplexVector vector, RComplex base,
-                        @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
-                        @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
-                        @Cached("create()") NACheck xNACheck,
-                        @Cached("create()") NACheck baseNACheck) {
-            return log(vector, base, index -> checkComplex(vector.getDataAt(index), xNACheck), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
-        }
-
-        private static RComplex checkComplex(RComplex rc, NACheck xNACheck) {
-            xNACheck.check(rc);
-            return rc;
-        }
-
-        private RDoubleVector log(RAbstractVector vector, double base, Function<Integer, Double> toDouble, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode,
-                        GetDimAttributeNode getDimsNode, NACheck xNACheck, NACheck baseNACheck) {
+        private RDoubleVector logInternal(RAbstractDoubleVector vector, double base, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, GetDimAttributeNode getDimsNode,
+                        NACheck xNACheck, NACheck baseNACheck) {
             baseNACheck.enable(base);
             double[] resultVector = new double[vector.getLength()];
             if (baseNACheck.check(base)) {
@@ -266,12 +210,8 @@ public class LogFunctions {
                 xNACheck.enable(vector);
                 Runnable[] warningResult = new Runnable[1];
                 for (int i = 0; i < vector.getLength(); i++) {
-                    double value = toDouble.apply(i);
-                    if (!naX.isNA(value)) {
-                        resultVector[i] = logb(value, base, warningResult);
-                    } else {
-                        resultVector[i] = value;
-                    }
+                    double value = vector.getDataAt(i);
+                    resultVector[i] = xNACheck.check(value) ? RRuntime.DOUBLE_NA : logb(value, base, warningResult);
                 }
                 if (warningResult[0] != null) {
                     warningResult[0].run();
@@ -315,8 +255,8 @@ public class LogFunctions {
             return result;
         }
 
-        private RComplexVector log(RAbstractVector vector, RComplex base, Function<Integer, RComplex> toComplex, BinaryMapArithmeticFunctionNode divNode, GetDimAttributeNode getDimsNode,
-                        GetNamesAttributeNode getNamesNode, CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) {
+        private RComplexVector logInternal(RAbstractComplexVector vector, RComplex base, BinaryMapArithmeticFunctionNode divNode, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode,
+                        CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) {
             baseNACheck.enable(base);
             double[] complexVector = new double[vector.getLength() * 2];
             if (baseNACheck.check(base)) {
@@ -328,13 +268,13 @@ public class LogFunctions {
                 xNACheck.enable(vector);
                 boolean seenNaN = false;
                 for (int i = 0; i < vector.getLength(); i++) {
-                    RComplex value = toComplex.apply(i);
-                    if (!naX.isNA(value)) {
+                    RComplex value = vector.getDataAt(i);
+                    if (xNACheck.check(value)) {
+                        fill(complexVector, i * 2, value);
+                    } else {
                         RComplex rc = logb(value, base, divNode, false);
                         seenNaN = isNaN(rc);
                         fill(complexVector, i * 2, rc);
-                    } else {
-                        fill(complexVector, i * 2, value);
                     }
                 }
                 if (seenNaN) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index d8aebe6acb..d13a708f19 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -67,6 +67,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
 
     private final BranchProfile error = BranchProfile.create();
     private final ConditionProfile notRemoveNAs = ConditionProfile.createBinaryProfile();
+    private final ValueProfile vectorProfile = ValueProfile.createClassProfile();
 
     /**
      * For use by {@link RadixSort}.
@@ -79,7 +80,8 @@ public abstract class Order extends RPrecedenceBuiltinNode {
         return executeOrderVector1(v, naLast, dec, false);
     }
 
-    private RIntVector executeOrderVector1(RAbstractVector v, byte naLast, boolean dec, boolean needsStringCollation) {
+    private RIntVector executeOrderVector1(RAbstractVector vIn, byte naLast, boolean dec, boolean needsStringCollation) {
+        RAbstractVector v = vectorProfile.profile(vIn);
         int n = v.getLength();
         reportWork(n);
 
@@ -170,31 +172,27 @@ public abstract class Order extends RPrecedenceBuiltinNode {
 
     @Specialization(guards = {"oneVec(args)", "isFirstIntegerPrecedence(args)"})
     Object orderInt(byte naLast, boolean decreasing, RArgsValuesAndNames args) {
-        Object[] vectors = args.getArguments();
-        RAbstractIntVector v = (RAbstractIntVector) castVector(vectors[0]);
+        RAbstractIntVector v = (RAbstractIntVector) castVector(args.getArgument(0));
         return executeOrderVector1(v, naLast, decreasing);
     }
 
     @Specialization(guards = {"oneVec(args)", "isFirstDoublePrecedence(args)"})
     Object orderDouble(byte naLast, boolean decreasing, RArgsValuesAndNames args) {
-        Object[] vectors = args.getArguments();
-        RAbstractDoubleVector v = (RAbstractDoubleVector) castVector(vectors[0]);
+        RAbstractDoubleVector v = (RAbstractDoubleVector) castVector(args.getArgument(0));
         return executeOrderVector1(v, naLast, decreasing);
     }
 
     @Specialization(guards = {"oneVec(args)", "isFirstLogicalPrecedence(args)"})
     Object orderLogical(byte naLast, boolean decreasing, RArgsValuesAndNames args,
                     @Cached("createBinaryProfile()") ConditionProfile isNAProfile) {
-        Object[] vectors = args.getArguments();
-        RAbstractIntVector v = (RAbstractIntVector) castVector(vectors[0]).castSafe(RType.Integer, isNAProfile);
+        RAbstractIntVector v = (RAbstractIntVector) castVector(args.getArgument(0)).castSafe(RType.Integer, isNAProfile);
         return executeOrderVector1(v, naLast, decreasing);
     }
 
     @Specialization(guards = {"oneVec(args)", "isFirstStringPrecedence(args)"})
     Object orderString(byte naLast, boolean decreasing, RArgsValuesAndNames args,
                     @Cached("create()") BranchProfile collationProfile) {
-        Object[] vectors = args.getArguments();
-        RAbstractStringVector v = (RAbstractStringVector) castVector(vectors[0]);
+        RAbstractStringVector v = (RAbstractStringVector) castVector(args.getArgument(0));
         int n = v.getLength();
         boolean needsCollation = false;
         outer: for (int i = 0; i < n; i++) {
@@ -214,8 +212,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
 
     @Specialization(guards = {"oneVec(args)", "isFirstComplexPrecedence( args)"})
     Object orderComplex(byte naLast, boolean decreasing, RArgsValuesAndNames args) {
-        Object[] vectors = args.getArguments();
-        RAbstractComplexVector v = (RAbstractComplexVector) castVector(vectors[0]);
+        RAbstractComplexVector v = (RAbstractComplexVector) castVector(args.getArgument(0));
         return executeOrderVector1(v, naLast, decreasing);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
index a59b45866a..66cc1de161 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -65,8 +66,10 @@ public abstract class CastStringNode extends CastStringBaseNode {
     }
 
     @Specialization
-    protected RStringVector doAbstractContainer(RAbstractContainer operand,
+    protected RStringVector doAbstractContainer(RAbstractContainer operandIn,
+                    @Cached("createClassProfile()") ValueProfile operandProfile,
                     @Cached("createBinaryProfile()") ConditionProfile isLanguageProfile) {
+        RAbstractContainer operand = operandProfile.profile(operandIn);
         String[] sdata = new String[operand.getLength()];
         // conversions to character will not introduce new NAs
         for (int i = 0; i < operand.getLength(); i++) {
-- 
GitLab


From 167248957647b7fc5707afbc3d184a97f75a70eb Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 11 Apr 2017 11:49:50 +0200
Subject: [PATCH 287/402] handle newlines in string literals

---
 .../truffle/r/parser/DefaultRParserFactory.java      |  2 +-
 .../oracle/truffle/r/test/ExpectedTestOutput.test    | 12 ++++++++++++
 .../com/oracle/truffle/r/test/parser/TestParser.java |  7 +++++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java
index 38f9cdc524..a058b86051 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java
@@ -90,7 +90,7 @@ public class DefaultRParserFactory extends RParserFactory {
             String line = e.line <= source.getLineCount() ? source.getCode(e.line) : "";
             String substring = line.substring(0, Math.min(line.length(), e.charPositionInLine + 1));
             String token = e.token == null ? (substring.length() == 0 ? "" : substring.substring(substring.length() - 1)) : e.token.getText();
-            if (e.token != null && e.token.getType() == Token.EOF && (e instanceof NoViableAltException || e instanceof MismatchedTokenException)) {
+            if (e.getUnexpectedType() == Token.EOF && (e instanceof NoViableAltException || e instanceof MismatchedTokenException)) {
                 // the parser got stuck at the eof, request another line
                 throw new IncompleteSourceException(e, source, token, substring, e.line);
             } else {
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 920e7100ae..b612947eda 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
@@ -144093,6 +144093,18 @@ Error: unexpected input in "%0"
 #10^2^2
 [1] 10000
 
+##com.oracle.truffle.r.test.parser.TestParser.testNewLinesInLiterals#
+#"foo<<<NEWLINE>>>baraz"
+[1] "foo\nbar\baz"
+
+##com.oracle.truffle.r.test.parser.TestParser.testNewLinesInLiterals#
+#'foo<<<NEWLINE>>>baraz'
+[1] "foo\nbar\baz"
+
+##com.oracle.truffle.r.test.parser.TestParser.testNewLinesInLiterals#
+#`asdf<<<NEWLINE>>>asdf` <- 1; `asdf<<<NEWLINE>>>asdf`
+[1] 1
+
 ##com.oracle.truffle.r.test.parser.TestParser.testNewLinesNesting#Output.IgnoreErrorMessage#
 #a <- 1:100; y <- 2; z <- 5; x <- (a[[{y <<<NEWLINE>>> * z}]])
 Error: unexpected '*' in:
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
index b68f29703a..9f4562761f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
@@ -105,6 +105,13 @@ public class TestParser extends TestBase {
         assertEval(Output.IgnoreErrorMessage, "a <- 1:100; y <- 2; z <- 5; x <- (a[[{y \n * z}]])");
     }
 
+    @Test
+    public void testNewLinesInLiterals() {
+        assertEval("`asdf\nasdf` <- 1; `asdf\nasdf`");
+        assertEval("'foo\nbar\baz'");
+        assertEval("\"foo\nbar\baz\"");
+    }
+
     @Test
     public void testEmptySymbols() {
         assertEval("names(e)");
-- 
GitLab


From 565cc29d38cc5495e08e09919d0f92dd53eb49f2 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 11 Apr 2017 12:04:52 +0200
Subject: [PATCH 288/402] various changes towards running Rcpp

---
 .../r/nodes/builtin/base/BasePackage.java     |   3 +-
 .../r/nodes/builtin/base/FileFunctions.java   |   2 +-
 .../r/nodes/builtin/base/GrepFunctions.java   | 120 ++++++++++++++++--
 .../truffle/r/nodes/builtin/CastBuilder.java  |  12 +-
 .../truffle/r/nodes/builtin/casts/Filter.java |   4 +-
 .../builtin/casts/PipelineToCastNode.java     |   4 +-
 .../com/oracle/truffle/r/runtime/ffi/DLL.java |   8 +-
 7 files changed, 128 insertions(+), 25 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 627bdb1bcf..170c7bb52a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -440,7 +440,8 @@ public class BasePackage extends RBuiltinPackage {
         add(GrepFunctions.Gregexpr.class, GrepFunctionsFactory.GregexprNodeGen::create);
         add(GrepFunctions.Grep.class, GrepFunctionsFactory.GrepNodeGen::create);
         add(GrepFunctions.GrepL.class, GrepFunctionsFactory.GrepLNodeGen::create);
-        add(GrepFunctions.Regexp.class, GrepFunctionsFactory.RegexpNodeGen::create);
+        add(GrepFunctions.Regexpr.class, GrepFunctionsFactory.RegexprNodeGen::create);
+        add(GrepFunctions.Regexec.class, GrepFunctionsFactory.RegexecNodeGen::create);
         add(GrepFunctions.Strsplit.class, GrepFunctionsFactory.StrsplitNodeGen::create);
         add(GrepFunctions.Sub.class, GrepFunctionsFactory.SubNodeGen::create);
         add(HiddenInternalFunctions.GetRegisteredRoutines.class, HiddenInternalFunctionsFactory.GetRegisteredRoutinesNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index 14493a1eeb..2b33757ec4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -580,7 +580,7 @@ public class FileFunctions {
             byte[] status = new byte[vec.getLength()];
             for (int i = 0; i < status.length; i++) {
                 String path = vec.getDataAt(i);
-                if (RRuntime.isNA(path)) {
+                if (RRuntime.isNA(path) || path.isEmpty()) {
                     status[i] = RRuntime.LOGICAL_FALSE;
                 } else {
                     File f = new File(Utils.tildeExpand(path));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index 250ccd5ed6..97a8bf4feb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -313,7 +313,7 @@ public class GrepFunctions {
         }
 
         protected static boolean findMatch(String pattern, String text, boolean ignoreCase) {
-            Matcher m = Regexp.getPatternMatcher(pattern, text, ignoreCase);
+            Matcher m = Regexpr.getPatternMatcher(pattern, text, ignoreCase);
             return m.find();
         }
     }
@@ -733,7 +733,7 @@ public class GrepFunctions {
 
     @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "regexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
-    public abstract static class Regexp extends RBuiltinNode.Arg6 {
+    public abstract static class Regexpr extends RBuiltinNode.Arg6 {
 
         @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length");
         @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes");
@@ -746,7 +746,7 @@ public class GrepFunctions {
         @Child PCRERFFI.GetCaptureCountNode getCaptureCountNode = RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureCountNode();
 
         static {
-            Casts casts = new Casts(Regexp.class);
+            Casts casts = new Casts(Regexpr.class);
             castPattern(casts);
             castText(casts, "text");
             castIgnoreCase(casts);
@@ -782,12 +782,9 @@ public class GrepFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL,
+        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean perl, boolean fixed, boolean useBytesL,
                         @Cached("createCommon()") CommonCodeNode common) {
             common.checkExtraArgs(false, false, false, useBytesL, false);
-            boolean ignoreCase = ignoreCaseL;
-            boolean fixed = fixedL;
-            boolean perl = perlL;
             if (patternArg.getLength() > 1) {
                 throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
             }
@@ -924,9 +921,116 @@ public class GrepFunctions {
         }
     }
 
+    @ImportStatic(GrepFunctions.class)
+    @RBuiltin(name = "regexec", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "fixed", "useBytes"}, behavior = PURE)
+    public abstract static class Regexec extends RBuiltinNode.Arg5 {
+
+        @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length");
+        @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes");
+        @Child SetFixedAttributeNode setDimNamesAttrNode = SetFixedAttributeNode.createDimNames();
+
+        static {
+            Casts casts = new Casts(Regexec.class);
+            castPattern(casts);
+            castText(casts, "text");
+            castIgnoreCase(casts);
+            castFixed(casts, RRuntime.LOGICAL_FALSE);
+            castUseBytes(casts);
+        }
+
+        protected static final class Info {
+            protected final int index;
+            protected final int size;
+            protected final int[] captureStart;
+            protected final int[] captureLength;
+            protected final String[] captureNames;
+            protected final boolean hasCapture;
+
+            public Info(int index, int size, int[] captureStart, int[] captureLength, String[] captureNames) {
+                this.index = index;
+                this.size = size;
+                this.captureStart = captureStart;
+                this.captureLength = captureLength;
+                this.captureNames = captureNames;
+                this.hasCapture = captureStart != null && captureLength != null;
+            }
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean fixed, boolean useBytes,
+                        @Cached("createCommon()") CommonCodeNode common) {
+            common.checkExtraArgs(false, false, false, useBytes, false);
+            if (patternArg.getLength() > 1) {
+                throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
+            }
+            RList ret = RDataFactory.createList(vector.getLength());
+            String pattern = patternArg.getDataAt(0);
+            pattern = RegExp.checkPreDefinedClasses(pattern);
+            // TODO: useBytes normally depends on the value of the parameter and (if false) on
+            // whether the string is ASCII
+            for (int i = 0; i < vector.getLength(); i++) {
+                int[] matchPos;
+                int[] matchLength;
+                if (pattern.length() == 0) {
+                    // emtpy pattern
+                    matchPos = new int[]{1};
+                    matchLength = new int[]{0};
+                } else {
+                    List<Info> res = getInfo(pattern, vector.getDataAt(i), ignoreCase, fixed);
+                    matchPos = new int[res.size()];
+                    matchLength = new int[res.size()];
+                    for (int j = 0; j < res.size(); j++) {
+                        matchPos[j] = res.get(j).index;
+                        matchLength[j] = res.get(j).size;
+                    }
+                }
+                RIntVector matches = RDataFactory.createIntVector(matchPos, RDataFactory.COMPLETE_VECTOR);
+                setMatchLengthAttrNode.execute(matches, RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR));
+                ret.setElement(i, matches);
+            }
+            if (useBytes) {
+                setUseBytesAttrNode.execute(ret, RRuntime.LOGICAL_TRUE);
+            }
+            return ret;
+        }
+
+        protected List<Info> getInfo(String pattern, String text, boolean ignoreCase, boolean fixed) {
+            List<Info> list = new ArrayList<>();
+            if (fixed) {
+                int index;
+                if (ignoreCase) {
+                    index = text.toLowerCase().indexOf(pattern.toLowerCase());
+                } else {
+                    index = text.indexOf(pattern);
+                }
+                if (index != -1) {
+                    list.add(new Info(index + 1, pattern.length(), null, null, null));
+                }
+            } else {
+                Matcher m = getPatternMatcher(pattern, text, ignoreCase);
+                if (m.find()) {
+                    for (int i = 0; i <= m.groupCount(); i++) {
+                        list.add(new Info(m.start(i) + 1, m.end(i) - m.start(i), null, null, null));
+                    }
+                }
+            }
+            if (list.size() > 0) {
+                return list;
+            }
+            list.add(new Info(-1, -1, null, null, null));
+            return list;
+        }
+
+        @TruffleBoundary
+        private static Matcher getPatternMatcher(String pattern, String text, boolean ignoreCase) {
+            return Pattern.compile(pattern, ignoreCase ? Pattern.CASE_INSENSITIVE : 0).matcher(text);
+        }
+    }
+
     @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "gregexpr", kind = INTERNAL, parameterNames = {"pattern", "text", "ignore.case", "perl", "fixed", "useBytes"}, behavior = PURE)
-    public abstract static class Gregexpr extends Regexp {
+    public abstract static class Gregexpr extends Regexpr {
 
         @Child SetFixedAttributeNode setMatchLengthAttrNode = SetFixedAttributeNode.create("match.length");
         @Child SetFixedAttributeNode setUseBytesAttrNode = SetFixedAttributeNode.create("useBytes");
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index e5c570b5d0..965ea3aa03 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -436,10 +436,6 @@ public final class CastBuilder {
             return MissingFilter.INSTANCE;
         }
 
-        public static <T> CompareFilter<T> sameAs(T x) {
-            return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Any));
-        }
-
         public static <T> CompareFilter<T> equalTo(T x) {
             return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Any));
         }
@@ -549,19 +545,19 @@ public final class CastBuilder {
         }
 
         public static CompareFilter<Integer> eq(int x) {
-            return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Integer));
+            return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Integer));
         }
 
         public static CompareFilter<Double> eq(double x) {
-            return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Double));
+            return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Double));
         }
 
         public static CompareFilter<Byte> eq(byte x) {
-            return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Logical));
+            return new CompareFilter<>(CompareFilter.EQ, new CompareFilter.ScalarValue(x, RType.Logical));
         }
 
         public static CompareFilter<String> eq(String x) {
-            return new CompareFilter<>(CompareFilter.SAME, new CompareFilter.ScalarValue(x, RType.Character));
+            return new CompareFilter<>(CompareFilter.STRING_EQ, new CompareFilter.ScalarValue(x, RType.Character));
         }
 
         public static NotFilter<Integer> neq(int x) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
index d9234e2354..ad1729b0ab 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
@@ -361,13 +361,13 @@ public abstract class Filter<T, R extends T> {
         public static final byte LT = 2;
         public static final byte GE = 3;
         public static final byte LE = 4;
-        public static final byte SAME = 5;
+        public static final byte STRING_EQ = 5;
 
         private final byte operation;
         private final Subject subject;
 
         public CompareFilter(byte operation, Subject subject) {
-            assert operation <= SAME : "wrong operation value";
+            assert operation <= STRING_EQ : "wrong operation value";
             this.operation = operation;
             this.subject = subject;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 3cb2e52310..79aa7369ff 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -495,8 +495,8 @@ public final class PipelineToCastNode {
                         default:
                             throw RInternalError.unimplemented("TODO: more types here");
                     }
-                case CompareFilter.SAME:
-                    return arg -> arg == scalarValue.value;
+                case CompareFilter.STRING_EQ:
+                    return arg -> ((String) scalarValue.value).equals(arg);
 
                 default:
                     throw RInternalError.unimplemented("TODO: more operations here");
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index c1d2879620..a536479f99 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -620,9 +620,11 @@ public class DLL {
                 return f;
             }
 
-            if (!dllInfo.dynamicLookup) {
-                return SYMBOL_NOT_FOUND;
-            }
+            // TODO: there is a weird interaction with namespace environments that makes this not
+            // true in all cases
+            // if (!dllInfo.dynamicLookup) {
+            // return SYMBOL_NOT_FOUND;
+            // }
 
             String mName = name;
             // assume Fortran underscore, although GnuR has cc code for this
-- 
GitLab


From e220e3aa7fe3b48c9e9f2c7ccceecc54e3ddf239 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 11 Apr 2017 13:48:27 +0200
Subject: [PATCH 289/402] FastR Grid: SVG support

---
 .../fastrGrid/FastRGridExternalLookup.java    |   3 +
 .../r/library/fastrGrid/GridContext.java      |   8 +
 .../fastrGrid/device/DrawingContext.java      |  25 +-
 .../library/fastrGrid/device/GridDevice.java  |   2 +-
 .../r/library/fastrGrid/device/SVGDevice.java | 267 ++++++++++++++++++
 .../library/fastrGrid/grDevices/DevCairo.java |  54 ++++
 .../r/library/fastrGrid/grDevices/DevOff.java |  22 +-
 .../fastrGrid/grDevices/R/fastrGridDevices.R  |   8 +
 8 files changed, 386 insertions(+), 3 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index daea6bc681..1f297581c4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 import com.oracle.truffle.r.library.fastrGrid.DisplayList.LGetDisplayListElement;
 import com.oracle.truffle.r.library.fastrGrid.DisplayList.LInitDisplayList;
 import com.oracle.truffle.r.library.fastrGrid.DisplayList.LSetDisplayListOn;
+import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCairo;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevOff;
@@ -59,6 +60,8 @@ public final class FastRGridExternalLookup {
                 return DevOff.create();
             case "PDF":
                 return new IgnoredGridExternal(RNull.instance);
+            case "devCairo":
+                return new DevCairo();
             default:
                 return null;
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index f00b510ec4..10f8a4d797 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -100,6 +100,10 @@ public final class GridContext {
     public void closeDevice(int which) throws DeviceCloseException {
         assert which >= 0 && which < devices.size();
         devices.get(which).device.close();
+        removeDevice(which);
+    }
+
+    public void removeDevice(int which) {
         RGridGraphicsAdapter.removeDevice(which);
         devices.remove(which);
         if (currentDeviceIdx >= which) {
@@ -107,6 +111,10 @@ public final class GridContext {
         }
     }
 
+    public GridDevice getDevice(int index) {
+        return devices.get(index).device;
+    }
+
     /**
      * Runs arbitrary function from 'fastrGrid.R' file and returns its result.
      */
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
index 2986d9ffba..dcfb747b4f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/DrawingContext.java
@@ -53,6 +53,14 @@ public interface DrawingContext {
             assert num > 0 && num <= SYMBOL.ordinal() + 1;
             return values()[num - 1];
         }
+
+        public boolean isBold() {
+            return this == BOLD || this == BOLDITALIC;
+        }
+
+        public boolean isItalic() {
+            return this == ITALIC || this == BOLDITALIC;
+        }
     }
 
     enum GridLineJoin {
@@ -132,7 +140,8 @@ public interface DrawingContext {
     String getFontFamily();
 
     /**
-     * Gets the height of a line in multiplies of the base line height.
+     * Gets the height of a text line in multiplies of the base line height. This is typically not a
+     * concern of devices, since they always receive single line strings for drawing.
      */
     double getLineHeight();
 
@@ -140,4 +149,18 @@ public interface DrawingContext {
      * The fill color of shapes.
      */
     GridColor getFillColor();
+
+    static boolean areSame(DrawingContext ctx1, DrawingContext ctx2) {
+        return ctx1 == ctx2 || (ctx1.getColor().equals(ctx2.getColor()) &&
+                        ctx1.getLineEnd() == ctx2.getLineEnd() &&
+                        ctx1.getLineJoin() == ctx2.getLineJoin() &&
+                        ctx1.getLineType() == ctx2.getLineType() &&
+                        ctx1.getLineHeight() == ctx2.getLineHeight() &&
+                        ctx1.getFontStyle() == ctx2.getFontStyle() &&
+                        ctx1.getFontSize() == ctx2.getFontSize() &&
+                        ctx1.getFontFamily().equals(ctx2.getFontFamily()) &&
+                        ctx1.getLineWidth() == ctx2.getLineWidth() &&
+                        ctx1.getLineMitre() == ctx2.getLineMitre() &&
+                        ctx1.getFillColor().equals(ctx2.getFillColor()));
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 2ea6e4468e..0515ded9b5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -81,7 +81,7 @@ public interface GridDevice {
     void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius);
 
     /**
-     * Prints a string with left bottom corner at given position rotates by given angle anti clock
+     * Prints a string with left bottom corner at given position rotated by given angle anti clock
      * wise, the centre of the rotation should be the bottom left corer.
      */
     void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
new file mode 100644
index 0000000000..702a586e3c
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.device;
+
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GRID_LINE_BLANK;
+import static com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.INCH_TO_POINTS_FACTOR;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.text.DecimalFormat;
+import java.util.Collections;
+
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+public class SVGDevice implements GridDevice {
+    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000");
+    private final StringBuilder data = new StringBuilder(1024);
+    private final String filename;
+    private final double width;
+    private final double height;
+
+    private DrawingContext cachedCtx;
+
+    public SVGDevice(String filename, double width, double height) {
+        this.filename = filename;
+        this.width = width;
+        this.height = height;
+    }
+
+    public String getContents() {
+        return data.toString();
+    }
+
+    @Override
+    public void openNewPage() {
+        // We stay compatible with GnuR: opening new page wipes out what has been drawn without
+        // saving it anywhere.
+        data.setLength(0);
+        cachedCtx = null;
+        append("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">");
+        // we could use real inches, but that makes the output different to GnuR and other formats
+        // (jpg, ...), which use conversion 70px ~ 1in
+        append("<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' width='%.3fpx' height='%.3fpx' viewBox='0 0 %.3f %.3f'>", width * 70d, height * 70d,
+                        width,
+                        height);
+    }
+
+    @Override
+    public void close() throws DeviceCloseException {
+        if (cachedCtx != null) {
+            // see #appendStyle
+            append("</g>");
+        }
+        append("</svg>");
+        try {
+            Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            throw new DeviceCloseException(e);
+        }
+    }
+
+    @Override
+    public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) {
+        appendStyle(ctx);
+        append("<rect vector-effect='non-scaling-stroke' x='%.3f' y='%.3f' width='%.3f' height='%.3f'", leftX, transY(bottomY + height), width, height);
+        if (rotationAnticlockWise != 0) {
+            append("transform='rotate(%.3f %.3f,%.3f)'", toDegrees(rotationAnticlockWise), (leftX + width / 2.), transY(bottomY + height / 2.));
+        }
+        data.append("/>"); // end of 'rect' tag
+    }
+
+    @Override
+    public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        drawPoly(ctx, x, y, startIndex, length, "style='fill:transparent'");
+    }
+
+    @Override
+    public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        drawPoly(ctx, x, y, startIndex, length, "");
+    }
+
+    @Override
+    public void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius) {
+        appendStyle(ctx);
+        append("<circle vector-effect='non-scaling-stroke' cx='%.3f' cy='%.3f' r='%.3f'/>", centerX, transY(centerY), radius);
+    }
+
+    @Override
+    public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
+        appendStyle(ctx);
+        append("<text x='%.3f' y='%.3f' textLength='%.3f' lengthAdjust='spacingAndGlyphs' ", leftX, transY(bottomY), getStringWidth(ctx, text));
+        // SVG interprets the "fill" as the color of the text
+        data.append("style='").append(getStyleColor("fill", ctx.getColor())).append(";stroke:transparent'");
+        if (rotationAnticlockWise != 0) {
+            append(" transform='rotate(%.3f %.3f,%.3f)'", toDegrees(rotationAnticlockWise), leftX, transY(bottomY));
+        }
+        data.append(">").append(text).append("</text>");
+    }
+
+    @Override
+    public double getWidth() {
+        return width;
+    }
+
+    @Override
+    public double getHeight() {
+        return height;
+    }
+
+    @Override
+    public double getStringWidth(DrawingContext ctx, String text) {
+        // The architecture of the GridDevice and grid package requires the devices be able to
+        // calculate the width of given string, this way one can e.g. create a box around text. SVG
+        // supports this by means of "textLength" attribute, which allows us to force text to have
+        // specified width. So we approximate the width of given text in the calculation below and
+        // then force the text to actually have such width if it ever gets displayed by #drawString.
+        double factor = 0.5;    // empirically chosen
+        if (ctx.getFontStyle() == GridFontStyle.BOLD || ctx.getFontStyle() == GridFontStyle.BOLDITALIC) {
+            factor = 0.62;
+        }
+        double letterWidth = (ctx.getFontSize() / INCH_TO_POINTS_FACTOR);
+        double result = factor * (double) text.length() * letterWidth;
+        for (int i = 0; i < text.length(); i++) {
+            char c = text.charAt(i);
+            if (c == 'w' || c == 'm') {
+                result += letterWidth * 0.2;
+            } else if (c == 'z') {
+                result += letterWidth * 0.1;
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public double getStringHeight(DrawingContext ctx, String text) {
+        // we need height without ascent/descent of letters that are not in the string, this is
+        // empirically tested calculation
+        return 0.8 * (ctx.getFontSize() / INCH_TO_POINTS_FACTOR);
+    }
+
+    private void drawPoly(DrawingContext ctx, double[] x, double[] y, int startIndex, int length, String attributes) {
+        appendStyle(ctx);
+        data.append("<polyline vector-effect='non-scaling-stroke' points='");
+        for (int i = 0; i < length; i++) {
+            data.append(DECIMAL_FORMAT.format(x[i + startIndex]));
+            data.append(',');
+            data.append(DECIMAL_FORMAT.format(transY(y[i + startIndex])));
+            data.append(' ');
+        }
+        data.append("' ").append(attributes).append(" />");
+    }
+
+    private void appendStyle(DrawingContext ctx) {
+        if (cachedCtx == null || !DrawingContext.areSame(cachedCtx, ctx)) {
+            if (cachedCtx != null) {
+                append("</g>"); // close the previous style definition
+            }
+            append("<g style='");
+            appendStyleUncached(ctx);
+            append("'>");
+        }
+        cachedCtx = ctx;
+    }
+
+    private void appendStyleUncached(DrawingContext ctx) {
+        byte[] lineType = ctx.getLineType();
+        if (lineType == GRID_LINE_BLANK) {
+            append("stroke:transparent");
+        } else {
+            append(getStyleColor("stroke", ctx.getColor()));
+        }
+        data.append(';').append(getStyleColor("fill", ctx.getFillColor()));
+        data.append(";stroke-width:").append(ctx.getLineWidth());
+        if (lineType != DrawingContext.GRID_LINE_SOLID && lineType != DrawingContext.GRID_LINE_BLANK) {
+            data.append(";stroke-dasharray:");
+            for (int i = 0; i < lineType.length; i++) {
+                data.append(lineType[i]);
+                if (i != lineType.length - 1) {
+                    data.append(',');
+                }
+            }
+        }
+        data.append(";stroke-linejoin:").append(getSVGLineJoin(ctx.getLineJoin()));
+        data.append(";stroke-linecap:").append(getSVGLineCap(ctx.getLineEnd()));
+        if (ctx.getLineJoin() == GridLineJoin.MITRE) {
+            data.append(";stroke-miterlimit:").append(ctx.getLineMitre());
+        }
+        data.append(";font-size:").append(ctx.getFontSize() / INCH_TO_POINTS_FACTOR).append("px");
+        if (!ctx.getFontFamily().isEmpty()) {
+            // Font-family strings 'mono', 'sans', and 'serif' are OK for us
+            data.append(";font-family:").append(ctx.getFontFamily());
+        }
+        if (ctx.getFontStyle().isBold()) {
+            data.append(";font-weight:bold");
+        }
+        if (ctx.getFontStyle().isItalic()) {
+            data.append(";font-style:italic");
+        }
+    }
+
+    private static String getSVGLineCap(GridLineEnd lineEnd) {
+        switch (lineEnd) {
+            case ROUND:
+                return "round";
+            case BUTT:
+                return "butt";
+            case SQUARE:
+                return "square";
+            default:
+                throw RInternalError.shouldNotReachHere("Unexpected value of GridLineEnd enum.");
+        }
+    }
+
+    private static String getSVGLineJoin(GridLineJoin lineJoin) {
+        switch (lineJoin) {
+            case ROUND:
+                return "round";
+            case MITRE:
+                return "miter";
+            case BEVEL:
+                return "bevel";
+            default:
+                throw RInternalError.shouldNotReachHere("Unexpected value of GridLineJoin enum.");
+        }
+    }
+
+    private static String getStyleColor(String prefix, GridColor color) {
+        return String.format("%s:rgb(%d,%d,%d);%s-opacity:%.3f", prefix, color.getRed(), color.getGreen(), color.getBlue(), prefix, (double) color.getAlpha() / 255d);
+    }
+
+    private void append(String fmt, Object... args) {
+        data.append(String.format(fmt + "\n", args));
+    }
+
+    private double transY(double y) {
+        return (height - y);
+    }
+
+    private static double toDegrees(double rotationAnticlockWise) {
+        return (180. / Math.PI) * -rotationAnticlockWise;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
new file mode 100644
index 0000000000..6ae4427041
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid.grDevices;
+
+import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class DevCairo extends RExternalBuiltinNode {
+    static {
+        Casts.noCasts(DevCairo.class);
+    }
+
+    @Override
+    protected Object call(RArgsValuesAndNames args) {
+        if (args.getLength() < 4) {
+            throw error(Message.ARGUMENTS_REQUIRED_COUNT, args.getLength(), "devCairo", 4);
+        }
+
+        String filename = RRuntime.asString(args.getArgument(0));
+        int witdh = RRuntime.asInteger(args.getArgument(2));
+        int height = RRuntime.asInteger(args.getArgument(2));
+        if (RRuntime.isNA(witdh) || RRuntime.isNA(height) || RRuntime.isNA(filename) || filename.isEmpty()) {
+            throw error(Message.INVALID_ARG_TYPE);
+        }
+
+        GridContext.getContext().setCurrentDevice("svg", new SVGDevice(filename, (double) witdh / 72., (double) height / 72.));
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
index e0d57b606a..87f99d3561 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
@@ -25,7 +25,9 @@ package com.oracle.truffle.r.library.fastrGrid.grDevices;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
+import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -45,10 +47,17 @@ public abstract class DevOff extends RExternalBuiltinNode.Arg1 {
     @TruffleBoundary
     public Object devOff(int whichR) {
         GridContext ctx = GridContext.getContext();
-        int which = whichR - 1; // convert to Java index
+        int which = Math.abs(whichR) - 1; // convert to Java index
         if (which < 0 || which >= ctx.getDevicesSize()) {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "Wrong device number.");
         }
+
+        // FastR specific special handling for SVG device, when the index is negative, return the
+        // SVG code
+        if (whichR < 0) {
+            return closeSvgDevice(ctx, which);
+        }
+
         try {
             ctx.closeDevice(which);
         } catch (DeviceCloseException e) {
@@ -56,4 +65,15 @@ public abstract class DevOff extends RExternalBuiltinNode.Arg1 {
         }
         return RNull.instance;
     }
+
+    private String closeSvgDevice(GridContext ctx, int which) {
+        GridDevice dev = ctx.getDevice(which);
+        ctx.removeDevice(which);
+        if ((dev instanceof SVGDevice)) {
+            return ((SVGDevice) dev).getContents();
+        } else {
+            warning(Message.GENERIC, "The device was not SVG device.");
+            return "";
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
index 2e551b4a1a..aad9c69ae6 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/R/fastrGridDevices.R
@@ -27,6 +27,14 @@ eval(expression({
     awt <- function(width = NULL, height = NULL, graphicsObj = NULL) {
         .External2(grDevices:::C_X11, ".FASTR.AWT", width, height, graphicsObj)
     }
+    # Allows to get the SVG code from SVG device, it also closes the device,
+    # but the contents are not saved to the given file.
+    svg.off <- function(which = dev.cur()) {
+        if (which == 1) {
+            stop("cannot shut down device 1 (the null device)")
+        }
+        .External(C_devoff, as.integer(-which))
+    }
     # GnuR version only works with "X11cairo" device. Our version of savePlot
     # works with "awt" device and "X11cairo", which is for us only alias for
     # "awt". Moreover, we only support formats that awt supports.
-- 
GitLab


From d3bb25eb3fa57f8b581f4e20ed32316957b2a0bf Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 12 Dec 2016 13:05:04 +0100
Subject: [PATCH 290/402] change R context initialization to store ContextInfo
 in configuration instead of symbol

---
 .../com/oracle/truffle/r/engine/REngine.java  | 23 +++++++++++++++----
 .../interop/ffi/nfi/TruffleNFI_DLL.java       |  8 +++----
 .../interop/ffi/nfi/TruffleNFI_Utils.java     |  8 +++----
 .../truffle/r/engine/shell/RCommand.java      | 11 +++++----
 .../truffle/r/engine/shell/REmbedded.java     |  5 ++--
 .../r/runtime/context/ContextInfo.java        | 13 ++++-------
 .../truffle/r/runtime/context/Engine.java     |  3 +++
 .../truffle/r/runtime/context/RContext.java   | 18 +++++++--------
 .../truffle/r/test/tck/FastRTckTest.java      |  5 ++--
 9 files changed, 53 insertions(+), 41 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index 5245ffc126..8798c06e69 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
@@ -142,8 +143,7 @@ final class REngine implements Engine, Engine.Timings {
     }
 
     static REngine create(RContext context) {
-        REngine engine = new REngine(context);
-        return engine;
+        return new REngine(context);
     }
 
     @Override
@@ -294,8 +294,21 @@ final class REngine implements Engine, Engine.Timings {
 
     @Override
     public CallTarget parseToCallTarget(Source source, MaterializedFrame executionFrame) throws ParseException {
-        List<RSyntaxNode> statements = parseImpl(source);
-        return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(source, statements), executionFrame));
+        if (source == Engine.GET_CONTEXT) {
+            /*
+             * The "get context" operations should be executed with as little influence on the
+             * actual engine as possible, therefore this special case takes care of it explicitly.
+             */
+            return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, source.createUnavailableSection(), new FrameDescriptor()) {
+                @Override
+                public Object execute(VirtualFrame frame) {
+                    return JavaInterop.asTruffleValue(context);
+                }
+            });
+        } else {
+            List<RSyntaxNode> statements = parseImpl(source);
+            return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(source, statements), executionFrame));
+        }
     }
 
     private static SourceSection createSourceSection(Source source, List<RSyntaxNode> statements) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
index 21ca2496f3..36cfaaa2d3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
@@ -30,7 +31,6 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL;
@@ -54,8 +54,8 @@ public class TruffleNFI_DLL implements DLLRFFI {
         @Override
         public Object execute(String path, boolean local, boolean now) {
             String libName = DLL.libName(path);
-            PolyglotEngine engine = RContext.getInstance().getVM();
-            TruffleObject libHandle = engine.eval(Source.newBuilder(prepareLibraryOpen(path, local, now)).name(path).mimeType("application/x-native").build()).as(TruffleObject.class);
+            Env env = RContext.getInstance().getEnv();
+            TruffleObject libHandle = (TruffleObject) env.parse(Source.newBuilder(prepareLibraryOpen(path, local, now)).name(path).mimeType("application/x-native").build()).call();
             return new NFIHandle(libName, libHandle);
         }
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
index df1edddf96..92a0e6dcb4 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,13 @@ package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 import java.nio.charset.StandardCharsets;
 
+import com.oracle.truffle.api.TruffleLanguage.Env;
 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.source.Source;
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.engine.interop.UnsafeAdapter;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -59,8 +59,8 @@ public class TruffleNFI_Utils {
 
     private static void initDefaultLibrary() {
         if (defaultLibrary == null) {
-            PolyglotEngine engine = RContext.getInstance().getVM();
-            defaultLibrary = engine.eval(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).as(TruffleObject.class);
+            Env env = RContext.getInstance().getEnv();
+            defaultLibrary = (TruffleObject) env.parse(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).call();
         }
 
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index 53d4271bb1..805e959e9a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,6 +53,7 @@ import com.oracle.truffle.r.runtime.Utils.DebugExitException;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
+import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -203,8 +204,8 @@ public class RCommand {
      */
     static int readEvalPrint(PolyglotEngine vm) {
         int lastStatus = 0;
-        ContextInfo contextInfo = ContextInfo.getContextInfo(vm);
-        ConsoleHandler consoleHandler = contextInfo.getConsoleHandler();
+        RContext context = vm.eval(Engine.GET_CONTEXT).as(RContext.class);
+        ConsoleHandler consoleHandler = context.getConsoleHandler();
         try {
             // console.println("initialize time: " + (System.currentTimeMillis() - start));
             REPL: for (;;) {
@@ -261,7 +262,7 @@ public class RCommand {
                         } catch (ExitException e) {
                             // usually from quit
                             int status = e.getStatus();
-                            if (contextInfo.getParent() == null) {
+                            if (context.getParent() == null) {
                                 vm.dispose();
                                 Utils.systemExit(status);
                             } else {
@@ -287,7 +288,7 @@ public class RCommand {
                 Utils.systemExit(0);
             } catch (ExitException e) {
                 // normal quit, but with exit code based on lastStatus
-                if (contextInfo.getParent() == null) {
+                if (context.getParent() == null) {
                     Utils.systemExit(lastStatus);
                 } else {
                     return lastStatus;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
index d0031dd9f6..9a6d8d9490 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.RSource.Internal;
 import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
@@ -105,7 +106,7 @@ public class REmbedded {
      */
     public static void main(String[] args) {
         PolyglotEngine vm = initializeR(args);
-        RStartParams startParams = ContextInfo.getContextInfo(vm).getStartParams();
+        RStartParams startParams = vm.eval(Engine.GET_CONTEXT).as(RContext.class).getStartParams();
         startParams.setEmbedded();
         startParams.setLoadInitFile(false);
         startParams.setNoRenviron(true);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index d048d22828..c1d39f9b1e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.context;
 import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
@@ -39,7 +38,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
  * instance (it will be stored in the "fastrContextInfo" global symbol).
  */
 public final class ContextInfo {
-    public static final String GLOBAL_SYMBOL = "fastrContextInfo";
+    static final String CONFIG_KEY = "fastrContextInfo";
 
     private static final AtomicInteger contextInfoIds = new AtomicInteger();
 
@@ -68,13 +67,13 @@ public final class ContextInfo {
     }
 
     public PolyglotEngine createVM() {
-        PolyglotEngine newVM = PolyglotEngine.newBuilder().globalSymbol(GLOBAL_SYMBOL, JavaInterop.asTruffleObject(this)).build();
+        PolyglotEngine newVM = PolyglotEngine.newBuilder().config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
         return newVM;
     }
 
     public PolyglotEngine createVM(PolyglotEngine.Builder builder) {
-        PolyglotEngine newVM = builder.globalSymbol(GLOBAL_SYMBOL, JavaInterop.asTruffleObject(this)).build();
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
         return newVM;
     }
@@ -114,10 +113,6 @@ public final class ContextInfo {
         return create(params, env, kind, parent, consoleHandler);
     }
 
-    public static ContextInfo getContextInfo(PolyglotEngine vm) {
-        return vm.findGlobalSymbol(ContextInfo.GLOBAL_SYMBOL).as(ContextInfo.class);
-    }
-
     public RStartParams getStartParams() {
         return startParams;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
index ac6079435a..6c7f7f692c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -39,6 +40,8 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 
 public interface Engine {
 
+    Source GET_CONTEXT = RSource.fromTextInternal("<<<get_context>>>", RSource.Internal.GET_CONTEXT);
+
     class ParseException extends RuntimeException {
         private static final long serialVersionUID = 1L;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 3e7f4875fc..64339a2fc5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,6 @@ import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ExitException;
@@ -58,7 +57,6 @@ import com.oracle.truffle.r.runtime.RProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSerialize;
-import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.TempPathName;
 import com.oracle.truffle.r.runtime.Utils;
@@ -71,6 +69,7 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL;
@@ -215,8 +214,6 @@ public final class RContext extends ExecutionContext {
      */
     public static class EvalThread extends ContextThread {
 
-        private static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT);
-
         private final Source source;
         private final ContextInfo info;
         private RList evalResult;
@@ -232,9 +229,9 @@ public final class RContext extends ExecutionContext {
 
         @Override
         public void run() {
-            PolyglotEngine vm = info.createVM();
+            PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder());
             try {
-                setContext(vm.eval(GET_CONTEXT).as(RContext.class));
+                setContext(vm.eval(Engine.GET_CONTEXT).as(RContext.class));
             } catch (Throwable t) {
                 throw new RInternalError(t, "error while initializing eval thread");
             }
@@ -260,6 +257,9 @@ public final class RContext extends ExecutionContext {
             } catch (ExitException e) {
                 // termination, treat this as "success"
                 evalResult = RDataFactory.createList(new Object[]{e.getStatus()});
+            } catch (RError e) {
+                // nothing to do
+                evalResult = RDataFactory.createList(new Object[]{RNull.instance});
             } catch (Throwable t) {
                 // some internal error
                 RInternalError.reportErrorAndConsoleLog(t, info.getConsoleHandler(), info.getId());
@@ -445,7 +445,7 @@ public final class RContext extends ExecutionContext {
      * @param isInitial {@code true} if this is the initial (primordial) context.
      */
     private RContext(Env env, Instrumenter instrumenter, boolean isInitial) {
-        Object initialInfo = env.importSymbol(ContextInfo.GLOBAL_SYMBOL);
+        Object initialInfo = env.getConfig().get(ContextInfo.CONFIG_KEY);
         if (initialInfo == null) {
             /*
              * This implies that FastR is being invoked initially from another Truffle language and
@@ -455,7 +455,7 @@ public final class RContext extends ExecutionContext {
             this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"--no-restore"}, false), false), null,
                             ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out()));
         } else {
-            this.info = JavaInterop.asJavaObject(ContextInfo.class, (TruffleObject) initialInfo);
+            this.info = (ContextInfo) initialInfo;
         }
 
         this.initial = isInitial;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 1d79ee857f..48193aea07 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,8 +40,7 @@ import com.oracle.truffle.tck.TruffleTCK;
 public class FastRTckTest extends TruffleTCK {
     @Test
     public void testVerifyPresence() {
-        PolyglotEngine vm = PolyglotEngine.newBuilder().globalSymbol(ContextInfo.GLOBAL_SYMBOL,
-                        null).build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         assertTrue("Our language is present", vm.getLanguages().containsKey("text/x-r"));
     }
 
-- 
GitLab


From 895e82cfe641d452829e8f25932319355be786ba Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 11 Apr 2017 15:41:34 +0200
Subject: [PATCH 291/402] minimize use of Java interop

---
 .../truffle/r/engine/shell/RCommand.java      | 20 +++++------
 .../truffle/r/engine/shell/REmbedded.java     | 34 +++++++++++--------
 .../r/engine/shell/RscriptCommand.java        |  6 ++--
 .../fficall/src/jni/Rembedded.c               | 14 ++++----
 4 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index 805e959e9a..44d6bba5c3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,6 @@ import com.oracle.truffle.r.runtime.Utils.DebugExitException;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
-import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -78,8 +77,8 @@ public class RCommand {
     public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) {
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
         options.printHelpAndVersion();
-        PolyglotEngine vm = createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env);
-        return readEvalPrint(vm);
+        ContextInfo info = createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
+        return readEvalPrint(info.createVM(), info);
     }
 
     /**
@@ -89,7 +88,7 @@ public class RCommand {
         return input.replace("~+~", " ");
     }
 
-    static PolyglotEngine createPolyglotEngineFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) {
+    static ContextInfo createContextInfoFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) {
         RStartParams rsp = new RStartParams(options, embedded);
 
         String fileArg = options.getString(FILE);
@@ -185,7 +184,7 @@ public class RCommand {
                 }
             }
         }
-        return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler).createVM();
+        return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler);
     }
 
     private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO);
@@ -202,10 +201,9 @@ public class RCommand {
      * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before
      * exiting. So,in either case, we never return.
      */
-    static int readEvalPrint(PolyglotEngine vm) {
+    static int readEvalPrint(PolyglotEngine vm, ContextInfo info) {
         int lastStatus = 0;
-        RContext context = vm.eval(Engine.GET_CONTEXT).as(RContext.class);
-        ConsoleHandler consoleHandler = context.getConsoleHandler();
+        ConsoleHandler consoleHandler = info.getConsoleHandler();
         try {
             // console.println("initialize time: " + (System.currentTimeMillis() - start));
             REPL: for (;;) {
@@ -262,7 +260,7 @@ public class RCommand {
                         } catch (ExitException e) {
                             // usually from quit
                             int status = e.getStatus();
-                            if (context.getParent() == null) {
+                            if (info.getParent() == null) {
                                 vm.dispose();
                                 Utils.systemExit(status);
                             } else {
@@ -288,7 +286,7 @@ public class RCommand {
                 Utils.systemExit(0);
             } catch (ExitException e) {
                 // normal quit, but with exit code based on lastStatus
-                if (context.getParent() == null) {
+                if (info.getParent() == null) {
                     Utils.systemExit(lastStatus);
                 } else {
                     return lastStatus;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
index 9a6d8d9490..d396a37419 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@ import com.oracle.truffle.r.runtime.RSource.Internal;
 import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
-import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
@@ -55,24 +54,28 @@ import com.oracle.truffle.r.runtime.context.RContext;
  * object which is itself stored as a global symbol in the associated {@link PolyglotEngine}
  * instance. The FastR {@link PolyglotEngine} is then partially initialized. The call to
  * {@code R_SetParams} will adjust the values stored in the {@link RStartParams} object and then
- * {@code Rf_mainloop}, which calls {@link #setupRmainloop(PolyglotEngine)} and then
- * {@link #runRmainloop(PolyglotEngine)}, which will complete the FastR initialization and enter the
- * read-eval-print loop.
+ * {@code Rf_mainloop}, which calls {@link #setupRmainloop()} and then {@link #runRmainloop()},
+ * which will complete the FastR initialization and enter the read-eval-print loop.
  */
 public class REmbedded {
 
+    private static ContextInfo info;
+    private static PolyglotEngine vm;
+
     /**
      * Creates the {@link PolyglotEngine} and initializes it. Called from native code when FastR is
      * embedded. Corresponds to FFI method {@code Rf_initialize_R}. N.B. This does not completely
      * initialize FastR as we cannot do that until the embedding system has had a chance to adjust
      * the {@link RStartParams}, which happens after this call returns.
      */
-    private static PolyglotEngine initializeR(String[] args) {
+    private static void initializeR(String[] args) {
+        assert vm == null;
+        assert info == null;
         RContext.setEmbedded();
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, true);
-        PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, true, true, System.in, System.out, null);
+        info = RCommand.createContextInfoFromCommandLine(options, true, true, System.in, System.out, null);
+        vm = info.createVM();
         vm.eval(INIT);
-        return vm;
     }
 
     /**
@@ -86,32 +89,33 @@ public class REmbedded {
      * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have
      * the equivalent separation in FastR.
      */
-    private static void setupRmainloop(@SuppressWarnings("unused") PolyglotEngine vm) {
+    private static void setupRmainloop() {
+        // nothing to do
     }
 
     /**
      * This is where we can complete the initialization based on what modifications were made by the
      * native code after {@link #initializeR} returned.
      */
-    private static void runRmainloop(PolyglotEngine vm) {
+    private static void runRmainloop() {
         RContext.getInstance().completeEmbeddedInitialization();
         if (!RContext.getInstance().getStartParams().getQuiet()) {
             RContext.getInstance().getConsoleHandler().println(RRuntime.WELCOME_MESSAGE);
         }
-        RCommand.readEvalPrint(vm);
+        RCommand.readEvalPrint(vm, info);
     }
 
     /**
      * Testing vehicle, emulates a native upcall.
      */
     public static void main(String[] args) {
-        PolyglotEngine vm = initializeR(args);
-        RStartParams startParams = vm.eval(Engine.GET_CONTEXT).as(RContext.class).getStartParams();
+        initializeR(args);
+        RStartParams startParams = info.getStartParams();
         startParams.setEmbedded();
         startParams.setLoadInitFile(false);
         startParams.setNoRenviron(true);
-        setupRmainloop(vm);
-        runRmainloop(vm);
+        setupRmainloop();
+        runRmainloop();
     }
 
     // Checkstyle: stop method name check
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
index 03ffb7af58..8e2be1e76a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
@@ -34,10 +34,10 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RVersionNumber;
+import com.oracle.truffle.r.runtime.context.ContextInfo;
 
 /**
  * Emulates the (Gnu)Rscript command as precisely as possible. in GnuR, Rscript is a genuine wrapper
@@ -117,8 +117,8 @@ public class RscriptCommand {
         // Handle --help and --version specially, as they exit.
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.RSCRIPT, args, false);
         preprocessRScriptOptions(options);
-        PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env);
-        return RCommand.readEvalPrint(vm);
+        ContextInfo info = RCommand.createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
+        return RCommand.readEvalPrint(info.createVM(), info);
 
     }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
index c9b70d1372..c38eab99ff 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
@@ -20,7 +20,6 @@
 extern char **environ;
 
 static JavaVM *javaVM;
-static jobject engine;
 static int initialized = 0;
 static char *java_home;
 
@@ -163,15 +162,14 @@ int Rf_initialize_R(int argc, char *argv[]) {
 	rembeddedClass = checkFindClass(jniEnv, "com/oracle/truffle/r/engine/shell/REmbedded");
 	rStartParamsClass = checkFindClass(jniEnv, "com/oracle/truffle/r/runtime/RStartParams");
 	jclass stringClass = checkFindClass(jniEnv, "java/lang/String");
-	jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR",
-			"([Ljava/lang/String;)Lcom/oracle/truffle/api/vm/PolyglotEngine;", 1);
+	jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR", "([Ljava/lang/String;)V", 1);
 	jobjectArray argsArray = (*jniEnv)->NewObjectArray(jniEnv, argc, stringClass, NULL);
 	for (int i = 0; i < argc; i++) {
 		jstring arg = (*jniEnv)->NewStringUTF(jniEnv, argv[i]);
 		(*jniEnv)->SetObjectArrayElement(jniEnv, argsArray, i, arg);
 	}
 	// Can't TRACE this upcall as system not initialized
-	engine = checkRef(jniEnv, (*jniEnv)->CallStaticObjectMethod(jniEnv, rembeddedClass, initializeMethod, argsArray));
+	(*jniEnv)->CallStaticObjectMethod(jniEnv, rembeddedClass, initializeMethod, argsArray);
 	initialized++;
 	return 0;
 }
@@ -250,15 +248,15 @@ static void setupOverrides(void);
 
 void setup_Rmainloop(void) {
 	JNIEnv *jniEnv = getEnv();
-	jmethodID setupMethod = checkGetMethodID(jniEnv, rembeddedClass, "setupRmainloop", "(Lcom/oracle/truffle/api/vm/PolyglotEngine;)V", 1);
-	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, setupMethod, engine);
+	jmethodID setupMethod = checkGetMethodID(jniEnv, rembeddedClass, "setupRmainloop", "()V", 1);
+	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, setupMethod);
 }
 
 void run_Rmainloop(void) {
 	JNIEnv *jniEnv = getEnv();
 	setupOverrides();
-	jmethodID mainloopMethod = checkGetMethodID(jniEnv, rembeddedClass, "runRmainloop", "(Lcom/oracle/truffle/api/vm/PolyglotEngine;)V", 1);
-	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, mainloopMethod, engine);
+	jmethodID mainloopMethod = checkGetMethodID(jniEnv, rembeddedClass, "runRmainloop", "()V", 1);
+	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, mainloopMethod);
 }
 
 void Rf_mainloop(void) {
-- 
GitLab


From ebc772321e811df18fc09febd26298481cabd97b Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 11 Apr 2017 18:55:55 +0200
Subject: [PATCH 292/402] Fix: Did not properly determine class hierarchy of
 attributables in upcalls.

---
 .../truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java       |  8 ++++----
 .../truffle/r/nodes/function/ClassHierarchyNode.java   | 10 +++++++---
 2 files changed, 11 insertions(+), 7 deletions(-)

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 c98d7398d3..a980e216b3 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
@@ -30,6 +30,8 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -41,7 +43,7 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.ffi.ParseResult.ParseStatus;
-import com.oracle.truffle.r.nodes.function.ImplicitClassHierarchyNode;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RCleanUp;
@@ -105,8 +107,6 @@ import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.rng.RRNG;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class provides a simple Java-based implementation of {@link UpCallsRFFI}, where all the
@@ -298,7 +298,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     public static RStringVector getClassHr(Object v) {
-        return ImplicitClassHierarchyNode.getImplicitClass(v);
+        return ClassHierarchyNode.getClassHierarchy(v);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index 8988230c91..1c830d94f3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -62,9 +62,13 @@ public abstract class ClassHierarchyNode extends UnaryNode {
      * attribute is not set.
      */
     @TruffleBoundary
-    public static RStringVector getClassHierarchy(RAttributable value) {
-        Object v = value.getAttr(RRuntime.CLASS_ATTR_KEY);
-        RStringVector result = v instanceof RStringVector ? (RStringVector) v : ImplicitClassHierarchyNode.getImplicitClass(value);
+    public static RStringVector getClassHierarchy(Object value) {
+        RStringVector result = null;
+        if (value instanceof RAttributable) {
+            Object v = ((RAttributable) value).getAttr(RRuntime.CLASS_ATTR_KEY);
+            result = v instanceof RStringVector ? (RStringVector) v : ImplicitClassHierarchyNode.getImplicitClass(value);
+        }
+
         return result != null ? result : RDataFactory.createEmptyStringVector();
     }
 
-- 
GitLab


From 7ca7a6276eb3131a3bd4dc6b5b451de43b92d286 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:22:32 +0200
Subject: [PATCH 293/402] add support for SHARE_ALL parallel execution contexts

---
 .../r/nodes/builtin/fastr/FastRContext.java   |  43 ++-
 .../parallel/R/forkcluster_overrides.R        |  57 +--
 .../access/variables/ReadVariableNode.java    |  13 +-
 .../truffle/r/runtime/FastROptions.java       |   2 +
 .../oracle/truffle/r/runtime/RArguments.java  |   6 +-
 .../oracle/truffle/r/runtime/RChannel.java    |  67 +++-
 .../truffle/r/runtime/RErrorHandling.java     |   5 +-
 .../oracle/truffle/r/runtime/RRuntime.java    |   7 +
 .../com/oracle/truffle/r/runtime/Utils.java   |  10 +-
 .../r/runtime/context/ContextInfo.java        |  34 +-
 .../truffle/r/runtime/context/RContext.java   |  45 ++-
 .../truffle/r/runtime/data/RDataFactory.java  |   6 +
 .../truffle/r/runtime/env/REnvironment.java   |  52 ++-
 .../env/frame/FrameSlotChangeMonitor.java     | 346 ++++++++++++++++--
 .../env/frame/NSBaseMaterializedFrame.java    |   2 +-
 .../truffle/r/test/ExpectedTestOutput.test    |  16 +
 .../truffle/r/test/channels/R/sharing1.R      |  14 +
 .../truffle/r/test/channels/R/sharing2.R      |  18 +
 .../truffle/r/test/channels/R/sharing3.R      |  15 +
 .../truffle/r/test/channels/R/sharing4.R      |  23 ++
 20 files changed, 690 insertions(+), 91 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 25883797ee..16744029f0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -42,6 +42,7 @@ import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RChannel;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RError;
@@ -50,6 +51,8 @@ import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
+import com.oracle.truffle.r.runtime.context.RContext.EvalThread;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -57,6 +60,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
  * The FastR builtins that allow multiple "virtual" R sessions potentially executing in parallel.
@@ -70,7 +74,8 @@ public class FastRContext {
 
         private static void kind(Casts casts) {
             casts.arg("kind").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst().mustNotBeNA().mustBe(
-                            equalTo(RContext.ContextKind.SHARE_NOTHING.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RW.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RO.name()))));
+                            equalTo(RContext.ContextKind.SHARE_NOTHING.name()).or(equalTo(RContext.ContextKind.SHARE_PARENT_RW.name()).or(
+                                            equalTo(RContext.ContextKind.SHARE_PARENT_RO.name()).or(equalTo(RContext.ContextKind.SHARE_ALL.name())))));
         }
 
         private static void pc(Casts casts) {
@@ -95,6 +100,17 @@ public class FastRContext {
         }
     }
 
+    private static void handleSharedContexts(ContextKind contextKind) {
+        if (contextKind == ContextKind.SHARE_ALL) {
+            RContext current = RContext.getInstance();
+            if (EvalThread.threads.size() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) {
+                ContextInfo.resetMultiSlotIndexGenerator();
+            } else {
+                throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist");
+            }
+        }
+    }
+
     /**
      * Similar to {@code .fastr.context.eval} but the invoking thread does not wait for completion,
      * which is done by {@code .fastr.context.join}. The result is a vector that should be passed to
@@ -105,7 +121,7 @@ public class FastRContext {
     public abstract static class Spawn extends RBuiltinNode.Arg3 {
         @Override
         public Object[] getDefaultParameterValues() {
-            return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"};
+            return new Object[]{RMissing.instance, 1, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"};
         }
 
         static {
@@ -119,6 +135,11 @@ public class FastRContext {
         @TruffleBoundary
         protected RIntVector spawn(RAbstractStringVector exprs, int pc, String kind) {
             RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind);
+            if (FastROptions.SharedContexts.getBooleanValue() && contextKind != ContextKind.SHARE_ALL) {
+                throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Only shared contexts are allowed");
+            }
+            handleSharedContexts(contextKind);
+
             RContext.EvalThread[] threads = new RContext.EvalThread[pc];
             int[] data = new int[pc];
             for (int i = 0; i < pc; i++) {
@@ -126,9 +147,15 @@ public class FastRContext {
                 threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
                 data[i] = info.getId();
             }
+            if (contextKind == ContextKind.SHARE_ALL) {
+                REnvironment.convertSearchpathToMultiSlot();
+            }
             for (int i = 0; i < pc; i++) {
                 threads[i].start();
             }
+            for (int i = 0; i < pc; i++) {
+                threads[i].waitForInit();
+            }
             return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
         }
     }
@@ -177,7 +204,7 @@ public class FastRContext {
     public abstract static class Eval extends RBuiltinNode.Arg3 {
         @Override
         public Object[] getDefaultParameterValues() {
-            return new Object[]{RMissing.instance, 1, "SHARE_NOTHING"};
+            return new Object[]{RMissing.instance, 1, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"};
         }
 
         static {
@@ -191,6 +218,10 @@ public class FastRContext {
         @TruffleBoundary
         protected Object eval(RAbstractStringVector exprs, int pc, String kind) {
             RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind);
+            if (FastROptions.SharedContexts.getBooleanValue() && contextKind != ContextKind.SHARE_ALL) {
+                throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Only shared contexts are allowed");
+            }
+            handleSharedContexts(contextKind);
 
             Object[] results = new Object[pc];
             if (pc == 1) {
@@ -208,9 +239,15 @@ public class FastRContext {
                     ContextInfo info = createContextInfo(contextKind);
                     threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
                 }
+                if (contextKind == ContextKind.SHARE_ALL) {
+                    REnvironment.convertSearchpathToMultiSlot();
+                }
                 for (int i = 0; i < pc; i++) {
                     threads[i].start();
                 }
+                for (int i = 0; i < pc; i++) {
+                    threads[i].waitForInit();
+                }
                 try {
                     for (int i = 0; i < pc; i++) {
                         threads[i].join();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
index 42d5c9ce8b..c9367588dd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
@@ -38,31 +38,31 @@ recvOneData.SHAREDcluster <- function(cl) {
 }), asNamespace("parallel"))
 
 eval(expression(
-fastr.newSHAREDnode <- function(rank, options = defaultClusterOptions)
+fastr.newSHAREDnodes <- function(nnodes, debug, options = defaultClusterOptions)
 {
-	# Add the "debug" option defaulted to FALSE, if the user didn't specify
-	# If the user gives TRUE, print extra stuff during cluster setup
-	debug <- FALSE
-	tryCatch(
-		debug <- parallel:::getClusterOption("debug", options),
-		error = function(e) { }
-	)
-	options <- parallel:::addClusterOptions(options, list(debug = debug))
-
-	# generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers)
-	port <- as.integer(parallel:::getClusterOption("port", options) + rank * 1000)
-	script <- file.path(R.home(), "com.oracle.truffle.r.native", "library", "parallel", "RSHAREDnode.R")
+	context_code <- vector("character", nnodes)
+	contexts <- vector("integer", nnodes)
+	channels <- vector("integer", nnodes)
+	for (i in 1:nnodes) {
+		# generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers)
+		port <- as.integer(parallel:::getClusterOption("port", options) + i * 1000)
+		script <- file.path(R.home(), "com.oracle.truffle.r.native", "library", "parallel", "RSHAREDnode.R")
 
-    context_code <- paste0("commandArgs<-function() c('--args', 'PORT=", port, "'); source('", script, "')")
-	if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", rank, context_code))
+    	context_code[[i]] <- paste0("commandArgs<-function() c('--args', 'PORT=", port, "'); source('", script, "')")
+		if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", i, context_code[[i]]))
 
-    cx <- .fastr.context.spawn(context_code)
-
-	## Need to return a list here, in the same form as the
-	## "cluster" data structure.
-    channel <- .fastr.channel.create(port)
-	if (isTRUE(debug)) cat(sprintf("Context %d started!\n", rank))
-	structure(list(channel = channel, context=cx, rank = rank), class = "SHAREDnode")
+		## Need to return a list here, in the same form as the
+		## "cluster" data structure.
+    	channels[[i]] <- .fastr.channel.create(port)
+		if (isTRUE(debug)) cat(sprintf("Context %d started!\n", i))
+	}
+    contexts <- .fastr.context.spawn(context_code, nnodes)
+    cl <- vector("list", nnodes)
+	for (i in 1:nnodes) {
+		cl[[i]] <- structure(list(channel = channels[[i]], context=contexts[[i]], rank = i), class = "SHAREDnode")
+	}
+	cl
+	
 }), asNamespace("parallel"))
 
 makeForkClusterExpr <- expression({
@@ -72,8 +72,17 @@ makeForkCluster <- function(nnodes = getOption("mc.cores", 2L), options = defaul
     if(is.na(nnodes) || nnodes < 1L) stop("'nnodes' must be >= 1")
     .check_ncores(nnodes)
 	options <- addClusterOptions(options, list(...))
-    cl <- vector("list", nnodes)
-    for (i in seq_along(cl)) cl[[i]] <- fastr.newSHAREDnode(rank=i, options=options)
+
+	# Add the "debug" option defaulted to FALSE, if the user didn't specify
+	# If the user gives TRUE, print extra stuff during cluster setup
+	debug <- FALSE
+	tryCatch(
+		debug <- parallel:::getClusterOption("debug", options),
+		error = function(e) { }
+	)
+	options <- parallel:::addClusterOptions(options, list(debug = debug))
+	
+    cl <- fastr.newSHAREDnodes(nnodes, debug = debug, options=options)
 	class(cl) <- c("SHAREDcluster", "cluster")
 	cl
 }; environment(makeForkCluster)<-asNamespace("parallel")})
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index f9e15b0a6b..5df1356f04 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -74,6 +74,7 @@ import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameAndSlotLookupResult;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.LookupResult;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
@@ -570,8 +571,16 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
          */
         FrameSlot localSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier);
         // non-local reads can only be handled in a simple way if they are successful
-        if (localSlot != null && checkTypeSlowPath(frame, getValue(seenValueKinds, variableFrame, localSlot))) {
-            return new Match(localSlot);
+        if (localSlot != null) {
+            Object val = getValue(seenValueKinds, variableFrame, localSlot);
+            if (checkTypeSlowPath(frame, val)) {
+                if (val instanceof MultiSlotData) {
+                    RError.performanceWarning("polymorphic (slow path) lookup of symbol \"" + identifier + "\" from a multi slot");
+                    return new Polymorphic(variableFrame);
+                } else {
+                    return new Match(localSlot);
+                }
+            }
         }
 
         /*
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 688fd6c0e2..ce53703800 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -54,6 +54,8 @@ public enum FastROptions {
     UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", true),
     UseSpecials("Whether the fast-path special call nodes should be created for simple enough arguments.", true),
     ForceSources("Generate source sections for unserialized code", false),
+    SharedContexts("Whether all child contexts are to be shared contexts", false),
+    SearchPathForcePromises("Whether all promises for frames on shared path are forced in presence of shared contexts", false),
 
     // Promises optimizations
     EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
index aeec614642..2f7f55abe4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
@@ -288,12 +288,14 @@ public final class RArguments {
         frame.getArguments()[INDEX_IS_IRREGULAR] = isIrregularFrame;
     }
 
-    public static void setEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame) {
+    public static void setEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame, boolean updateDescriptors) {
         CompilerAsserts.neverPartOfCompilation();
         Object[] arguments = frame.getArguments();
         MaterializedFrame oldEnclosingFrame = (MaterializedFrame) arguments[INDEX_ENCLOSING_FRAME];
         arguments[INDEX_ENCLOSING_FRAME] = newEnclosingFrame;
-        FrameSlotChangeMonitor.setEnclosingFrame(frame, newEnclosingFrame, oldEnclosingFrame);
+        if (updateDescriptors) {
+            FrameSlotChangeMonitor.setEnclosingFrame(frame, newEnclosingFrame, oldEnclosingFrame);
+        }
     }
 
     public static void initializeEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
index 595a9c69e2..bc1cb211f1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
@@ -28,8 +28,10 @@ import java.util.concurrent.Semaphore;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -242,11 +244,15 @@ public class RChannel {
             // parent can be SerializedEnv or byte[]
             private final Object parent;
             private final DynamicObject attributes;
+            private final String name;
+            private final FrameDescriptor desc;
 
-            SerializedEnv(Bindings bindings, Object parent, DynamicObject attributes) {
+            SerializedEnv(Bindings bindings, Object parent, DynamicObject attributes, String name, FrameDescriptor desc) {
                 this.bindings = bindings;
                 this.parent = parent;
                 this.attributes = attributes;
+                this.name = name;
+                this.desc = desc;
             }
 
             public String[] getNames() {
@@ -264,6 +270,14 @@ public class RChannel {
             public DynamicObject getAttributes() {
                 return attributes;
             }
+
+            public String getName() {
+                return name;
+            }
+
+            public FrameDescriptor getDesc() {
+                return desc;
+            }
         }
 
         protected static class SerializedPromise {
@@ -294,12 +308,18 @@ public class RChannel {
         protected static class SerializedFunction {
             private final DynamicObject attributes;
             private final Object env;
-            private final RFunction serializedDef;
+            private final String name;
+            private final String packageName;
+            private final RBuiltinDescriptor builtinDesc;
+            private final RootCallTarget callTarget;
 
-            public SerializedFunction(DynamicObject attributes, Object env, RFunction serializedDef) {
+            public SerializedFunction(DynamicObject attributes, Object env, String name, String packageName, RBuiltinDescriptor builtinDesc, RootCallTarget callTarget) {
                 this.attributes = attributes;
                 this.env = env;
-                this.serializedDef = serializedDef;
+                this.name = name;
+                this.packageName = packageName;
+                this.builtinDesc = builtinDesc;
+                this.callTarget = callTarget;
             }
 
             public DynamicObject getAttributes() {
@@ -310,8 +330,20 @@ public class RChannel {
                 return env;
             }
 
-            public RFunction getSerializedDef() {
-                return serializedDef;
+            public String getName() {
+                return name;
+            }
+
+            public RBuiltinDescriptor getRBuiltin() {
+                return builtinDesc;
+            }
+
+            public RootCallTarget getTarget() {
+                return callTarget;
+            }
+
+            public String getPackageName() {
+                return packageName;
             }
         }
 
@@ -394,6 +426,7 @@ public class RChannel {
             }
         }
 
+        @TruffleBoundary
         private Object convertPrivateEnv(Object msg) throws IOException {
             int refInd = getRefIndex(msg);
             if (refInd != -1) {
@@ -408,7 +441,7 @@ public class RChannel {
             }
             SerializedEnv.Bindings bindings = createShareable(env);
 
-            return new SerializedEnv(bindings, convertPrivateSlow(env.getParent()), attributes);
+            return new SerializedEnv(bindings, convertPrivateSlow(env.getParent()), attributes, env.getName(), env.getFrame().getFrameDescriptor());
         }
 
         private SerializedPromise convertPrivatePromise(Object msg) throws IOException {
@@ -425,7 +458,7 @@ public class RChannel {
             RFunction fn = (RFunction) msg;
             Object env = convertPrivate(REnvironment.frameToEnvironment(fn.getEnclosingFrame()));
             DynamicObject attributes = fn.getAttributes();
-            return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, fn);
+            return new SerializedFunction(attributes == null ? null : createShareableSlow(attributes, true), env, fn.getName(), fn.getPackageName(), fn.getRBuiltin(), fn.getTarget());
         }
 
         private Object convertPrivateAttributable(Object msg) throws IOException {
@@ -603,7 +636,7 @@ public class RChannel {
             Object[] values = e.getValues();
             String[] names = e.getNames();
             assert values.length == names.length;
-            REnvironment.NewEnv env = RDataFactory.createNewEnv(null);
+            REnvironment.NewEnv env = RDataFactory.createNewEnv(e.getDesc(), e.getName());
             addReadRef(env);
             int ind = 0;
             for (String n : names) {
@@ -611,7 +644,7 @@ public class RChannel {
                 env.safePut(n, newValue);
             }
             REnvironment parent = (REnvironment) unserializeObject(e.getParent());
-            RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame());
+            RArguments.setEnclosingFrame(env.getFrame(), parent.getFrame(), false);
             DynamicObject attributes = e.getAttributes();
             if (attributes != null) {
                 env.initAttributes(attributes);
@@ -636,13 +669,17 @@ public class RChannel {
 
         @TruffleBoundary
         private RFunction unserializeFunction(SerializedFunction f) throws IOException {
-            RFunction fun = f.getSerializedDef();
             REnvironment env = (REnvironment) unserializeObject(f.getEnv());
             MaterializedFrame enclosingFrame = env.getFrame();
-            HasSignature root = (HasSignature) fun.getTarget().getRootNode();
-            RootCallTarget target = root.duplicateWithNewFrameDescriptor();
-            FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame);
-            RFunction fn = RDataFactory.createFunction(fun.getName(), fun.getPackageName(), target, null, enclosingFrame);
+            RFunction fn;
+            if (FastROptions.SharedContexts.getBooleanValue()) {
+                fn = RDataFactory.createFunction(f.getName(), f.getPackageName(), f.getTarget(), f.getRBuiltin(), enclosingFrame);
+            } else {
+                HasSignature root = (HasSignature) f.getTarget().getRootNode();
+                RootCallTarget target = root.duplicateWithNewFrameDescriptor();
+                FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame);
+                fn = RDataFactory.createFunction(f.getName(), f.getPackageName(), target, null, enclosingFrame);
+            }
             DynamicObject attributes = f.getAttributes();
             if (attributes != null) {
                 assert fn.getAttributes() == null;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 412cd0b07e..6a5b182e76 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -597,7 +597,10 @@ public class RErrorHandling {
          */
         ContextStateImpl errorHandlingState = getRErrorHandlingState();
         RFunction f = errorHandlingState.getDotSignalSimpleWarning();
-        RContext.getRRuntimeASTAccess().callback(f, new Object[]{warningMessage, call});
+        if (f != null) {
+            RContext.getRRuntimeASTAccess().callback(f, new Object[]{warningMessage, call});
+        }
+        // otherwise the subsystem is not initialized yet - no warning
     }
 
     private static void warningcallDfltWithCall(Object call, Message msg, Object... args) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 8104d4e5a0..0f5b22a965 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -193,6 +193,13 @@ public class RRuntime {
         }
     }
 
+    /**
+     * Create a {@link MaterializedFrame} for functions shared between different contexts.
+     */
+    public static MaterializedFrame createNewFrame(FrameDescriptor frameDescriptor) {
+        return Truffle.getRuntime().createMaterializedFrame(RArguments.createUnitialized(), frameDescriptor);
+    }
+
     /**
      * Create an {@link VirtualFrame} for a non-function environment, e.g., a package frame or the
      * global environment.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index d533301e92..847c4a79e1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -60,6 +60,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -594,12 +595,9 @@ public final class Utils {
                     FrameDescriptor frameDescriptor = unwrapped.getFrameDescriptor();
                     for (FrameSlot s : frameDescriptor.getSlots()) {
                         str.append("\n      ").append(s.getIdentifier()).append(" = ");
-                        Object value;
-                        try {
-                            value = unwrapped.getValue(s);
-                        } catch (Throwable t) {
-                            str.append("<exception ").append(t.getClass().getSimpleName()).append(" while acquiring slot ").append(s.getIdentifier()).append(">");
-                            continue;
+                        Object value = unwrapped.getValue(s);
+                        if (value instanceof MultiSlotData) {
+                            value = ((MultiSlotData) value).get(RContext.getInstance().getMultiSlotInd());
                         }
                         try {
                             if (value instanceof RAbstractContainer && ((RAbstractContainer) value).getLength() > 32) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index c1d39f9b1e..84ee0da328 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 
@@ -41,6 +42,7 @@ public final class ContextInfo {
     static final String CONFIG_KEY = "fastrContextInfo";
 
     private static final AtomicInteger contextInfoIds = new AtomicInteger();
+    private static final AtomicInteger multiSlotInds = new AtomicInteger(-1);
 
     private final RStartParams startParams;
     private final String[] env;
@@ -54,18 +56,32 @@ public final class ContextInfo {
     private final RContext parent;
     private final ConsoleHandler consoleHandler;
     private final int id;
+    private final int multiSlotInd;
     private PolyglotEngine vm;
 
-    private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id) {
+    private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id, int multiSlotInd) {
         this.startParams = startParams;
         this.env = env;
         this.kind = kind;
         this.parent = parent;
         this.consoleHandler = consoleHandler;
         this.systemTimeZone = systemTimeZone;
+        this.multiSlotInd = multiSlotInd;
         this.id = id;
     }
 
+    /**
+     * Correctness of this method relies on the fact that parallel contexts are started only after
+     * all of them (and their info) is created (in FastRContext).
+     */
+    public static int contextNum() {
+        return multiSlotInds.get() + 1;
+    }
+
+    public static void resetMultiSlotIndexGenerator() {
+        multiSlotInds.set(0); // to account for primordial context
+    }
+
     public PolyglotEngine createVM() {
         PolyglotEngine newVM = PolyglotEngine.newBuilder().config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
@@ -91,7 +107,17 @@ public final class ContextInfo {
      */
     public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone) {
         int id = contextInfoIds.incrementAndGet();
-        return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id);
+        int multiSlotInd = multiSlotInds.get();
+        if (kind == ContextKind.SHARE_ALL || kind == ContextKind.SHARE_NOTHING) {
+            multiSlotInd = multiSlotInds.incrementAndGet();
+        }
+        // no increment for SHARE_PARENT_RW as it accesses the same data as its parent whose
+        // execution is suspended
+        if (kind == ContextKind.SHARE_PARENT_RO) {
+            throw RInternalError.shouldNotReachHere();
+        }
+        assert kind != ContextKind.SHARE_PARENT_RW || (kind == ContextKind.SHARE_PARENT_RW && parent.getKind() == ContextKind.SHARE_NOTHING && parent.getMultiSlotInd() == 0);
+        return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd);
     }
 
     public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) {
@@ -141,6 +167,10 @@ public final class ContextInfo {
         return id;
     }
 
+    public int getMultiSlotInd() {
+        return multiSlotInd;
+    }
+
     public PolyglotEngine getVM() {
         return vm;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 64339a2fc5..6b6a10a5fc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import java.util.TimeZone;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Semaphore;
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -134,7 +135,12 @@ public final class RContext extends ExecutionContext {
          * shallow copy of the environments associated with the default packages of the parent
          * context at the time the context is created.
          */
-        SHARE_PARENT_RO;
+        SHARE_PARENT_RO,
+
+        /**
+         * Shares all environments on the search path.
+         */
+        SHARE_ALL;
 
         public static final ContextKind[] VALUES = values();
     }
@@ -217,6 +223,7 @@ public final class RContext extends ExecutionContext {
         private final Source source;
         private final ContextInfo info;
         private RList evalResult;
+        private Semaphore init = new Semaphore(0);
 
         public static final Map<Integer, Thread> threads = new ConcurrentHashMap<>();
 
@@ -235,6 +242,7 @@ public final class RContext extends ExecutionContext {
             } catch (Throwable t) {
                 throw new RInternalError(t, "error while initializing eval thread");
             }
+            init.release();
             try {
                 evalResult = run(vm, info, source);
             } finally {
@@ -243,6 +251,19 @@ public final class RContext extends ExecutionContext {
             }
         }
 
+        /*
+         * Parent context uses this method to wait for initialization of the child to complete to
+         * prevent potential updates to runtime's meta data from interfering with program's
+         * execution.
+         */
+        public void waitForInit() {
+            try {
+                init.acquire();
+            } catch (InterruptedException x) {
+                throw new RInternalError(x, "error waiting to initialize eval thread");
+            }
+        }
+
         /**
          * Convenience method for {@code .fastr.context.eval} in same thread.
          */
@@ -387,6 +408,10 @@ public final class RContext extends ExecutionContext {
     private static final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("single RContext");
     @CompilationFinal private static RContext singleContext;
 
+    // need an additional flag as we don't want multi-slot processing to start until context
+    // initialization is fully complete - singleContext flag is not good enough for that
+    private static final Assumption isSingleContextAssumption = Truffle.getRuntime().createAssumption("is single RContext");
+
     private final Env env;
     private final HashMap<String, TruffleObject> exportedSymbols = new HashMap<>();
     private final boolean initial;
@@ -465,7 +490,7 @@ public final class RContext extends ExecutionContext {
         this.stateROptions = ROptions.ContextStateImpl.newContextState(stateREnvVars);
         this.stateRProfile = RProfile.newContextState(stateREnvVars);
         this.stateStdConnections = StdConnections.ContextStateImpl.newContextState();
-        this.stateREnvironment = REnvironment.ContextStateImpl.newContextState();
+        this.stateREnvironment = REnvironment.ContextStateImpl.newContextState(this);
         this.stateRErrorHandling = RErrorHandling.ContextStateImpl.newContextState();
         this.stateRConnection = ConnectionSupport.ContextStateImpl.newContextState();
         this.stateRNG = RRNG.ContextStateImpl.newContextState();
@@ -636,6 +661,14 @@ public final class RContext extends ExecutionContext {
         return info.getKind();
     }
 
+    public int getId() {
+        return info.getId();
+    }
+
+    public int getMultiSlotInd() {
+        return info.getMultiSlotInd();
+    }
+
     @TruffleBoundary
     public static RContext getThreadLocalInstance() {
         return threadLocalContext.get();
@@ -654,6 +687,14 @@ public final class RContext extends ExecutionContext {
         return result;
     }
 
+    public static boolean isSingle() {
+        return isSingleContextAssumption.isValid();
+    }
+
+    public static void markNonSingle() {
+        isSingleContextAssumption.invalidate();
+    }
+
     public static RContext getInstance() {
         RContext context = singleContext;
         if (singleContextAssumption.isValid() && context != null) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index ee8b17a277..2192e8f059 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.utilities.CyclicAssumption;
 import com.oracle.truffle.r.runtime.FastROptions;
@@ -499,6 +500,11 @@ public final class RDataFactory {
         return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<internal-env-" + environmentCount.incrementAndGet() + ">"), REnvironment.UNNAMED));
     }
 
+    @TruffleBoundary
+    public static REnvironment.NewEnv createNewEnv(FrameDescriptor desc, String name) {
+        return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNewFrame(desc), name));
+    }
+
     @TruffleBoundary
     public static REnvironment.NewEnv createNewEnv(String name) {
         return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<new-env-" + environmentCount.incrementAndGet() + ">"), name));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index 56100651dd..b8ba2fe1c7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.AnonymousFrameVariable;
@@ -41,6 +42,7 @@ import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.VirtualEvalFrame;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -48,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.NSBaseMaterializedFrame;
 import com.oracle.truffle.r.runtime.env.frame.REnvEmptyFrameAccess;
 import com.oracle.truffle.r.runtime.env.frame.REnvFrameAccess;
@@ -152,8 +155,15 @@ public abstract class REnvironment extends RAttributeStorage {
             beforeDestroyContext(context, this);
         }
 
-        public static ContextStateImpl newContextState() {
-            return new ContextStateImpl(RRuntime.createNonFunctionFrame("global"));
+        public static ContextStateImpl newContextState(RContext context) {
+            MaterializedFrame newGlobalFrame;
+            if (context.getKind() == ContextKind.SHARE_ALL) {
+                ContextStateImpl parentState = context.getParent().stateREnvironment;
+                newGlobalFrame = parentState.getGlobalFrame();
+            } else {
+                newGlobalFrame = RRuntime.createNonFunctionFrame("global");
+            }
+            return new ContextStateImpl(newGlobalFrame);
         }
 
         public void initialize(Base newBaseEnv, REnvironment newNamespaceRegistry, SearchPath newSearchPath) {
@@ -329,6 +339,7 @@ public abstract class REnvironment extends RAttributeStorage {
                 /* We make shallow copies of all the default package environments in the parent */
                 ContextStateImpl parentState = context.getParent().stateREnvironment;
                 SearchPath parentSearchPath = parentState.getSearchPath();
+                assert parentSearchPath.size() > 1;
                 // clone all the environments below global from the parent
                 REnvironment e = parentSearchPath.get(1).cloneEnv(globalFrame);
                 // create the new Global with clone top as parent
@@ -352,6 +363,15 @@ public abstract class REnvironment extends RAttributeStorage {
                 break;
             }
 
+            case SHARE_ALL: {
+                ContextStateImpl parentState = context.getParent().stateREnvironment;
+                // TODO: may be worthwhile to assert for all environments on the search path there
+                // is 1:1 descriptor:frame mapping (as they are all meant to be shared in we rely on
+                // the single descriptor information to identify accesses to shared frames)
+                contextState.initialize(parentState.getBaseEnv(), parentState.getNamespaceRegistry(), parentState.getSearchPath());
+                break;
+            }
+
             case SHARE_NOTHING: {
                 // SHARE_NOTHING: baseInitialize takes care of everything
                 break;
@@ -747,7 +767,7 @@ public abstract class REnvironment extends RAttributeStorage {
      */
     public void setParent(REnvironment env) {
         if (getParent() != env) {
-            RArguments.setEnclosingFrame(getFrame(), env.getFrame());
+            RArguments.setEnclosingFrame(getFrame(), env.getFrame(), true);
         }
     }
 
@@ -890,6 +910,32 @@ public abstract class REnvironment extends RAttributeStorage {
         return getPrintName();
     }
 
+    public static void convertSearchpathToMultiSlot() {
+        CompilerAsserts.neverPartOfCompilation();
+        RContext.markNonSingle();
+        ContextStateImpl parentState = RContext.getInstance().stateREnvironment;
+        SearchPath searchPath = parentState.getSearchPath();
+        assert searchPath.size() > 0 && searchPath.get(0).getSearchName() == Global.SEARCHNAME;
+        // for global space don't replicate entries as all contexts should see their own values
+        FrameSlotChangeMonitor.handleAllMultiSlots(searchPath.get(0).getFrame(), false);
+        for (int i = 1; i < searchPath.size(); i++) {
+            FrameSlotChangeMonitor.handleAllMultiSlots(searchPath.get(i).getFrame(), true);
+        }
+        REnvironment namespaces = parentState.namespaceRegistry;
+        Frame namespacesFrame = namespaces.getFrame();
+        // make a copy avoid potential updates to the array iterated over
+        FrameSlot[] slots = new FrameSlot[namespacesFrame.getFrameDescriptor().getSlots().size()];
+        slots = namespacesFrame.getFrameDescriptor().getSlots().toArray(slots);
+        for (int i = 0; i < slots.length; i++) {
+            REnvironment namespaceEnv = (REnvironment) namespacesFrame.getValue(slots[i]);
+            if (namespaceEnv != Base.baseNamespaceEnv()) {
+                // base namespace frame redirects all accesses to base frame and this would
+                // result in processing the slots twice
+                FrameSlotChangeMonitor.handleAllMultiSlots(namespaceEnv.getFrame(), true);
+            }
+        }
+    }
+
     private static final class BaseNamespace extends REnvironment {
         private BaseNamespace(String name, MaterializedFrame frame) {
             super(name, frame);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 323f4d154d..886f4922b6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameDescriptor;
@@ -44,9 +45,12 @@ import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.StableValue;
+import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
 /**
@@ -147,7 +151,7 @@ public final class FrameSlotChangeMonitor {
         public Object getValue() {
             // fast path execution should use getFrame / getSlot
             CompilerAsserts.neverPartOfCompilation("FrameAndSlotLookupResult.getValue() should not be used in fast path execution");
-            return frame.getValue(slot);
+            return FrameSlotChangeMonitor.getValue(slot, frame);
         }
 
         public MaterializedFrame getFrame() throws InvalidAssumptionException {
@@ -242,6 +246,7 @@ public final class FrameSlotChangeMonitor {
                 } else {
                     FrameDescriptorMetaData currentMetaData = getMetaData(current);
                     if (currentMetaData.singletonFrame == null) {
+                        // no stable value and no singleton frame
                         return null;
                     } else {
                         assert currentMetaData.singletonFrame.get() != null;
@@ -312,7 +317,8 @@ public final class FrameSlotChangeMonitor {
         return frame == null ? null : frame instanceof NSBaseMaterializedFrame ? ((NSBaseMaterializedFrame) frame).getMarkerFrameDescriptor() : frame.getFrameDescriptor();
     }
 
-    private static FrameDescriptorMetaData getMetaData(FrameDescriptor descriptor) {
+    private static synchronized FrameDescriptorMetaData getMetaData(FrameDescriptor descriptor) {
+        CompilerAsserts.neverPartOfCompilation();
         FrameDescriptorMetaData result = frameDescriptors.get(descriptor);
         assert result != null : "null metadata for " + descriptor;
         return result;
@@ -452,6 +458,24 @@ public final class FrameSlotChangeMonitor {
         // System.out.println(String.format(format, args));
     }
 
+    public static final class MultiSlotData {
+
+        private final Object[] data = new Object[ContextInfo.contextNum()];
+
+        public Object get(int ind) {
+            return data[ind];
+        }
+
+        public void set(int ind, Object val) {
+            data[ind] = val;
+        }
+
+        public void setAll(Object val) {
+            Arrays.fill(data, val);
+        }
+
+    }
+
     private static final class FrameSlotInfoImpl {
         /**
          * This is meant to monitor updates performed on {@link FrameSlot}. Each {@link FrameSlot}
@@ -464,11 +488,14 @@ public final class FrameSlotChangeMonitor {
          * comes into play.<br/>
          */
         private final Assumption nonLocalModifiedAssumption = Truffle.getRuntime().createAssumption();
+        private final Assumption noMultiSlot = Truffle.getRuntime().createAssumption();
 
-        @CompilationFinal private StableValue<Object> stableValue;
+        @CompilationFinal private volatile StableValue<Object> stableValue;
         private int invalidationCount;
+        private final boolean possibleMultiSlot;
 
-        FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier) {
+        FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier, boolean isNewEnv) {
+            this.possibleMultiSlot = isSingletonFrame && !isNewEnv;
             if (isSingletonFrame) {
                 stableValue = new StableValue<>(null, identifier.toString());
                 invalidationCount = isGlobalEnv ? MAX_GLOBAL_ENV_INVALIDATION_COUNT : MAX_INVALIDATION_COUNT;
@@ -481,29 +508,39 @@ public final class FrameSlotChangeMonitor {
             return stableValue != null;
         }
 
+        public boolean possibleMultiSlot() {
+            return possibleMultiSlot;
+        }
+
         /*
          * Special cases for primitive types to force value (instead of identity) comparison.
          */
 
-        public void setValue(byte value, FrameSlot slot) {
+        private void setValue(boolean value, FrameSlot slot) {
+            if (stableValue != null && (!(stableValue.getValue() instanceof Boolean) || ((boolean) stableValue.getValue()) != value)) {
+                invalidateStableValue(value, slot);
+            }
+        }
+
+        private void setValue(byte value, FrameSlot slot) {
             if (stableValue != null && (!(stableValue.getValue() instanceof Byte) || ((byte) stableValue.getValue()) != value)) {
                 invalidateStableValue(value, slot);
             }
         }
 
-        public void setValue(int value, FrameSlot slot) {
+        private void setValue(int value, FrameSlot slot) {
             if (stableValue != null && (!(stableValue.getValue() instanceof Integer) || ((int) stableValue.getValue()) != value)) {
                 invalidateStableValue(value, slot);
             }
         }
 
-        public void setValue(double value, FrameSlot slot) {
+        private void setValue(double value, FrameSlot slot) {
             if (stableValue != null && (!(stableValue.getValue() instanceof Double) || ((double) stableValue.getValue()) != value)) {
                 invalidateStableValue(value, slot);
             }
         }
 
-        public void setValue(Object value, FrameSlot slot) {
+        private void setValue(Object value, FrameSlot slot) {
             if (stableValue != null && stableValue.getValue() != value) {
                 invalidateStableValue(value, slot);
             }
@@ -525,6 +562,110 @@ public final class FrameSlotChangeMonitor {
         public StableValue<Object> getStableValue() {
             return stableValue;
         }
+
+        private static void setNewMultiValue(Frame frame, FrameSlot slot, MultiSlotData data, Object newValue) {
+            int ind = RContext.getInstance().getMultiSlotInd();
+            data.set(ind, newValue);
+            frame.setObject(slot, data);
+        }
+
+        private static boolean evalAndSetPromise(Frame frame, FrameSlot slot, FrameSlotInfoImpl info) {
+            Object prevValue = info.stableValue.getValue();
+            if (prevValue instanceof RPromise) {
+                prevValue = RContext.getRRuntimeASTAccess().forcePromise("searchPathPromiseForce", prevValue);
+                if (prevValue instanceof Boolean) {
+                    frame.setBoolean(slot, (boolean) prevValue);
+                    info.setValue((boolean) prevValue, slot);
+                } else if (prevValue instanceof Byte) {
+                    frame.setByte(slot, (byte) prevValue);
+                    info.setValue((byte) prevValue, slot);
+                } else if (prevValue instanceof Integer) {
+                    frame.setInt(slot, (int) prevValue);
+                    info.setValue((int) prevValue, slot);
+                } else if (prevValue instanceof Double) {
+                    frame.setDouble(slot, (double) prevValue);
+                    info.setValue((double) prevValue, slot);
+                } else {
+                    frame.setObject(slot, prevValue);
+                    info.setValue(prevValue, slot);
+                }
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        public static void handleSearchPathMultiSlot(Frame frame, FrameSlot slot, boolean replicate) {
+            CompilerAsserts.neverPartOfCompilation();
+            while (true) {
+                FrameSlotInfoImpl info = (FrameSlotInfoImpl) slot.getInfo();
+                if (info.stableValue == null || !replicate) {
+                    // create a multi slot for slots whose stableValue is null but also for all
+                    // slots of
+                    // the global frame (which are marked as !replicate)
+                    info.stableValue = null;
+                    info.nonLocalModifiedAssumption.invalidate();
+                    info.noMultiSlot.invalidate();
+                    info.invalidationCount = 0;
+                    MultiSlotData data = new MultiSlotData();
+                    Object prevValue = frame.getValue(slot);
+                    // TODO: do we have to worry that prevValue can be invalid?
+                    if (prevValue instanceof MultiSlotData) {
+                        // this handles the case when we create share contexts for the second time -
+                        // existing multi slots are an artifact of the previous executions and must
+                        // be
+                        // discarded
+                        // TOOD: consider re-using multi slots but since we don't expect many of
+                        // them,
+                        // perhaps it's too much work for too little gain
+                        prevValue = ((MultiSlotData) prevValue).get(0);
+                    } else if (FastROptions.SearchPathForcePromises.getBooleanValue()) {
+                        prevValue = RContext.getRRuntimeASTAccess().forcePromise("searchPathPromiseForce", prevValue);
+                    }
+                    if (replicate) {
+                        data.setAll(prevValue);
+                    } else {
+                        data.set(0, prevValue);
+                    }
+                    frame.setObject(slot, data);
+                    break;
+                } else {
+                    if (!FastROptions.SearchPathForcePromises.getBooleanValue() || !evalAndSetPromise(frame, slot, info)) {
+                        break;
+                    }
+                    // otherwise stable value may get nullified and slot turned into multi slot
+                }
+
+            }
+        }
+
+        @TruffleBoundary
+        public synchronized void setMultiSlot(Frame frame, FrameSlot slot, Object newValue) {
+            // TODO: perhaps putting the whole thing behind the Truffle boundary an overkill, but on
+            // the other hand it shouldn't happen often and not on the fast path
+            MultiSlotData data;
+            if (stableValue == null) {
+                // already a multi slot - should be visible to all threads
+                data = (MultiSlotData) frame.getValue(slot);
+                int ind = RContext.getInstance().getMultiSlotInd();
+                data.set(ind, newValue);
+            } else {
+                nonLocalModifiedAssumption.invalidate();
+                invalidationCount = 0;
+                // TODO: is it necessary since we nullify stable value?
+                stableValue.getAssumption().invalidate();
+                noMultiSlot.invalidate();
+                data = new MultiSlotData();
+                Object prevValue = frame.getValue(slot);
+                // value was stable so this slot is set by primordial context
+                data.set(0, prevValue);
+                setNewMultiValue(frame, slot, data, newValue);
+                // this should create happens-before with stable value reads during lookup, thus
+                // making preceding update to the actual frame OK to read without additional
+                // synchronization
+                stableValue = null;
+            }
+        }
     }
 
     /**
@@ -547,15 +688,29 @@ public final class FrameSlotChangeMonitor {
 
     // methods for creating new frame slots
 
-    public static synchronized FrameSlot findOrAddFrameSlot(FrameDescriptor fd, Object identifier, FrameSlotKind initialKind) {
+    public static FrameSlot findOrAddFrameSlot(FrameDescriptor fd, String identifier, FrameSlotKind initialKind) {
+        return findOrAddFrameSlot(fd, (Object) identifier, initialKind);
+    }
+
+    public static FrameSlot findOrAddFrameSlot(FrameDescriptor fd, RFrameSlot identifier, FrameSlotKind initialKind) {
+        return findOrAddFrameSlot(fd, (Object) identifier, initialKind);
+    }
+
+    private static synchronized FrameSlot findOrAddFrameSlot(FrameDescriptor fd, Object identifier, FrameSlotKind initialKind) {
         CompilerAsserts.neverPartOfCompilation();
+        assert identifier instanceof String || identifier instanceof RFrameSlot;
         FrameSlot frameSlot = fd.findFrameSlot(identifier);
         if (frameSlot != null) {
             return frameSlot;
         } else {
-            FrameDescriptorMetaData metaData = getMetaData(fd);
-            invalidateNames(metaData, Arrays.asList(identifier));
-            return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier), initialKind);
+            if (identifier instanceof String || ((RFrameSlot) identifier).isMultiSlot()) {
+                FrameDescriptorMetaData metaData = getMetaData(fd);
+                invalidateNames(metaData, Arrays.asList(identifier));
+                return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier, metaData.name.startsWith("<new-env-")),
+                                initialKind);
+            } else {
+                return fd.addFrameSlot(identifier, initialKind);
+            }
         }
     }
 
@@ -585,44 +740,124 @@ public final class FrameSlotChangeMonitor {
         }
     }
 
+    public static void setBooleanAndInvalidate(Frame frame, FrameSlot frameSlot, boolean newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
+        FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+        if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) {
+            info.setMultiSlot(frame, frameSlot, newValue);
+        } else {
+            frame.setBoolean(frameSlot, newValue);
+            if (info.needsInvalidation()) {
+                info.setValue(newValue, frameSlot);
+            }
+            checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
+        }
+    }
+
+    public static void setBoolean(Frame frame, FrameSlot frameSlot, boolean newValue) {
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+            if (info.possibleMultiSlot()) {
+                info.setMultiSlot(frame, frameSlot, newValue);
+                return;
+            }
+        }
+        frame.setBoolean(frameSlot, newValue);
+    }
+
     public static void setByteAndInvalidate(Frame frame, FrameSlot frameSlot, byte newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
-        frame.setByte(frameSlot, newValue);
         FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
-        if (info.needsInvalidation()) {
-            info.setValue(newValue, frameSlot);
+        if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) {
+            info.setMultiSlot(frame, frameSlot, newValue);
+        } else {
+            frame.setByte(frameSlot, newValue);
+            if (info.needsInvalidation()) {
+                info.setValue(newValue, frameSlot);
+            }
+            checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
         }
-        checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
+    }
+
+    public static void setByte(Frame frame, FrameSlot frameSlot, byte newValue) {
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+            if (info.possibleMultiSlot()) {
+                info.setMultiSlot(frame, frameSlot, newValue);
+                return;
+            }
+        }
+        frame.setByte(frameSlot, newValue);
     }
 
     public static void setIntAndInvalidate(Frame frame, FrameSlot frameSlot, int newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
-        frame.setInt(frameSlot, newValue);
         FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
-        if (info.needsInvalidation()) {
-            info.setValue(newValue, frameSlot);
+        if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) {
+            info.setMultiSlot(frame, frameSlot, newValue);
+        } else {
+            frame.setInt(frameSlot, newValue);
+            if (info.needsInvalidation()) {
+                info.setValue(newValue, frameSlot);
+            }
+            checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
         }
-        checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
+    }
+
+    public static void setInt(Frame frame, FrameSlot frameSlot, int newValue) {
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+            if (info.possibleMultiSlot()) {
+                info.setMultiSlot(frame, frameSlot, newValue);
+                return;
+            }
+        }
+        frame.setInt(frameSlot, newValue);
     }
 
     public static void setDoubleAndInvalidate(Frame frame, FrameSlot frameSlot, double newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
-        frame.setDouble(frameSlot, newValue);
         FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
-        if (info.needsInvalidation()) {
-            info.setValue(newValue, frameSlot);
+        if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) {
+            info.setMultiSlot(frame, frameSlot, newValue);
+        } else {
+            frame.setDouble(frameSlot, newValue);
+            if (info.needsInvalidation()) {
+                info.setValue(newValue, frameSlot);
+            }
+            checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
         }
-        checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
+    }
+
+    public static void setDouble(Frame frame, FrameSlot frameSlot, double newValue) {
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+            if (info.possibleMultiSlot()) {
+                info.setMultiSlot(frame, frameSlot, newValue);
+                return;
+            }
+        }
+        frame.setDouble(frameSlot, newValue);
     }
 
     public static void setObjectAndInvalidate(Frame frame, FrameSlot frameSlot, Object newValue, boolean isNonLocal, BranchProfile invalidateProfile) {
         assert !ActiveBinding.isActiveBinding(newValue);
-        frame.setObject(frameSlot, newValue);
         FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
-        if (info.needsInvalidation()) {
-            info.setValue(newValue, frameSlot);
+        if (FastROptions.SharedContexts.getBooleanValue() && info.possibleMultiSlot() && !RContext.isSingle()) {
+            info.setMultiSlot(frame, frameSlot, newValue);
+        } else {
+            frame.setObject(frameSlot, newValue);
+            if (info.needsInvalidation()) {
+                info.setValue(newValue, frameSlot);
+            }
+            checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
         }
-        checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile);
     }
 
     public static void setObject(Frame frame, FrameSlot frameSlot, Object newValue) {
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot);
+            if (info.possibleMultiSlot()) {
+                info.setMultiSlot(frame, frameSlot, newValue);
+                return;
+            }
+        }
         frame.setObject(frameSlot, newValue);
     }
 
@@ -641,6 +876,7 @@ public final class FrameSlotChangeMonitor {
      * intended to be used for a non-function frame (and thus will only ever be used for one frame).
      */
     public static synchronized void initializeNonFunctionFrameDescriptor(String name, MaterializedFrame frame) {
+        CompilerAsserts.neverPartOfCompilation();
         frameDescriptors.put(handleBaseNamespaceEnv(frame), new FrameDescriptorMetaData(name, frame));
     }
 
@@ -680,11 +916,61 @@ public final class FrameSlotChangeMonitor {
         return getMetaData(frameDesc) != null;
     }
 
+    /*
+     * This method should be called for frames of all environments on the search path.
+     */
+    public static void handleAllMultiSlots(Frame frame, boolean replicate) {
+        // make a copy avoid potential updates to the array iterated over
+        FrameSlot[] slots = new FrameSlot[frame.getFrameDescriptor().getSlots().size()];
+        slots = frame.getFrameDescriptor().getSlots().toArray(slots);
+        for (int i = 0; i < slots.length; i++) {
+            if (!(slots[i].getIdentifier() instanceof RFrameSlot)) {
+                FrameSlotInfoImpl.handleSearchPathMultiSlot(frame, slots[i], replicate);
+            }
+        }
+    }
+
     public static Object getObject(FrameSlot slot, Frame frame) throws FrameSlotTypeException {
-        return frame.getObject(slot);
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(slot);
+            if (info.noMultiSlot.isValid()) {
+                return frame.getObject(slot);
+            }
+            Object o;
+            try {
+                o = frame.getObject(slot);
+            } catch (FrameSlotTypeException e) {
+                CompilerDirectives.transferToInterpreter();
+                o = null;
+            }
+            if (!(o instanceof MultiSlotData)) {
+                CompilerDirectives.transferToInterpreter();
+                synchronized (info) {
+                    o = frame.getObject(slot);
+                }
+            }
+            return ((MultiSlotData) o).get(RContext.getInstance().getMultiSlotInd());
+        } else {
+            return frame.getObject(slot);
+        }
     }
 
     public static Object getValue(FrameSlot slot, Frame frame) {
-        return frame.getValue(slot);
+        if (FastROptions.SharedContexts.getBooleanValue() && !RContext.isSingle()) {
+            FrameSlotInfoImpl info = getFrameSlotInfo(slot);
+            if (info.noMultiSlot.isValid()) {
+                return frame.getValue(slot);
+            }
+            Object o = frame.getValue(slot);
+            if (!(o instanceof MultiSlotData)) {
+                CompilerDirectives.transferToInterpreter();
+                synchronized (info) {
+                    o = frame.getValue(slot);
+                }
+            }
+            return ((MultiSlotData) o).get(RContext.getInstance().getMultiSlotInd());
+        } else {
+            return frame.getValue(slot);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
index af7d7af6ec..c95c81051e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
@@ -60,7 +60,7 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
     }
 
     public void updateGlobalFrame(MaterializedFrame globalFrame) {
-        RArguments.setEnclosingFrame(this, globalFrame);
+        RArguments.setEnclosingFrame(this, globalFrame, true);
     }
 
     public FrameDescriptor getMarkerFrameDescriptor() {
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 b612947eda..492004a017 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
@@ -130402,6 +130402,22 @@ a b c d e
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels9.R") }
 [1]  TRUE FALSE
 
+##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing1.R") }
+[1] 42  7
+
+##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing2.R") }
+[1] "object 'x' not found"
+
+##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing3.R") }
+[1] 42  7
+
+##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
+#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing4.R") }
+[1] 24 42
+
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { .fastr.interop.eval('application/x-r', '1') }
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R
new file mode 100644
index 0000000000..5a96c59642
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R
@@ -0,0 +1,14 @@
+# test remote update in global space - values should remain distinct
+
+if (length(grep("FastR", R.Version()$version.string)) == 1) {
+    ch1 <- .fastr.channel.create(1L)
+    code <- "ch2 <- .fastr.channel.get(1L); x <- 7; .fastr.channel.send(ch2, x)"
+    x <- 42
+    cx <- .fastr.context.spawn(code)
+    y <- .fastr.channel.receive(ch1)
+    .fastr.context.join(cx)
+    .fastr.channel.close(ch1)
+    print(c(x, y))
+} else {
+    print(c(42L, 7L))
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R
new file mode 100644
index 0000000000..3c02fba5ab
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R
@@ -0,0 +1,18 @@
+# test subsequent remote updates in global space - second time value should have been reset
+
+if (length(grep("FastR", R.Version()$version.string)) == 1) {
+    ch1 <- .fastr.channel.create(1L)
+    code <- "ch2 <- .fastr.channel.get(1L); x <- 7; .fastr.channel.send(ch2, x)"
+    x <- 42
+    cx <- .fastr.context.spawn(code)
+    y <- .fastr.channel.receive(ch1)
+    .fastr.context.join(cx)
+    code <- "ch2 <- .fastr.channel.get(1L); res <- tryCatch(z <- x, error=function(e) e); .fastr.channel.send(ch2, res[[1]])"
+    cx <- .fastr.context.spawn(code)
+    y <- .fastr.channel.receive(ch1)
+    .fastr.context.join(cx)    
+    .fastr.channel.close(ch1)
+    print(y)
+} else {
+    print("object 'x' not found")
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R
new file mode 100644
index 0000000000..ec10067a70
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R
@@ -0,0 +1,15 @@
+# test remote update in base space - values should remain distinct
+
+if (length(grep("FastR", R.Version()$version.string)) == 1) {
+    ch1 <- .fastr.channel.create(1L)
+	# use an obscure name so it doesn't clash with other tests
+    code <- "ch2 <- .fastr.channel.get(1L); assign('tmp59857', 7, env=baseenv()); .fastr.channel.send(ch2, get('tmp59857', env=baseenv(), inherits=F))"
+    assign('tmp59857', 42, env=baseenv())
+    cx <- .fastr.context.spawn(code)
+    y <- .fastr.channel.receive(ch1)
+    .fastr.context.join(cx)
+    .fastr.channel.close(ch1)
+    print(c(get('tmp59857', env=baseenv(), inherits=F), y))
+} else {
+    print(c(42L, 7L))
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
new file mode 100644
index 0000000000..5977fcb204
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
@@ -0,0 +1,23 @@
+# test access to global environment with multiple context instantiations varying context number
+
+if (length(grep("FastR", R.Version()$version.string)) == 1) {
+    ch1 <- .fastr.channel.create(1L)
+    code <- "ch2 <- .fastr.channel.get(1L); x <- .fastr.channel.receive(ch2); .fastr.channel.send(ch2, x)"
+    x <- 7
+    # create one child context
+    cx <- .fastr.context.spawn(code)
+    .fastr.channel.send(ch1, 7)
+    y <- .fastr.channel.receive(ch1)
+    .fastr.context.join(cx)
+    # create two child contexts
+    cx <- .fastr.context.spawn(code, 2)
+    .fastr.channel.send(ch1, 42)
+    .fastr.channel.send(ch1, 24)
+    y <- .fastr.channel.receive(ch1)
+    z <- .fastr.channel.receive(ch1)
+    
+    .fastr.channel.close(ch1)
+    print(sort(c(y, z)))
+} else {
+    print(c(24L, 42L))
+}
-- 
GitLab


From 3993cba31c7c4c643448ada5a3c67db80b62f61d Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:16 +0200
Subject: [PATCH 294/402] change interface of FastRContext functions

---
 .../r/nodes/builtin/fastr/FastRContext.java   | 55 +++++++++----------
 .../com/oracle/truffle/r/runtime/RSource.java | 16 ++++++
 .../truffle/r/test/channels/R/sharing4.R      |  2 +-
 3 files changed, 42 insertions(+), 31 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index 16744029f0..c59f4dbc43 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.builtin.fastr;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.equalTo;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
@@ -78,10 +77,6 @@ public class FastRContext {
                                             equalTo(RContext.ContextKind.SHARE_PARENT_RO.name()).or(equalTo(RContext.ContextKind.SHARE_ALL.name())))));
         }
 
-        private static void pc(Casts casts) {
-            casts.arg("pc").asIntegerVector().findFirst().mustNotBeNA().mustBe(gt(0));
-        }
-
         private static void key(Casts casts) {
             casts.arg("key").asIntegerVector().mustBe(notEmpty()).findFirst();
         }
@@ -117,43 +112,43 @@ public class FastRContext {
      * {@code .fastr.context.join}.
      *
      */
-    @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX)
-    public abstract static class Spawn extends RBuiltinNode.Arg3 {
+    @RBuiltin(name = ".fastr.context.spawn", kind = PRIMITIVE, parameterNames = {"exprs", "kind"}, behavior = COMPLEX)
+    public abstract static class Spawn extends RBuiltinNode.Arg2 {
         @Override
         public Object[] getDefaultParameterValues() {
-            return new Object[]{RMissing.instance, 1, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"};
+            return new Object[]{RMissing.instance, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"};
         }
 
         static {
             Casts casts = new Casts(Spawn.class);
             CastsHelper.exprs(casts);
-            CastsHelper.pc(casts);
             CastsHelper.kind(casts);
         }
 
         @Specialization
         @TruffleBoundary
-        protected RIntVector spawn(RAbstractStringVector exprs, int pc, String kind) {
+        protected RIntVector spawn(RAbstractStringVector exprs, String kind) {
             RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind);
             if (FastROptions.SharedContexts.getBooleanValue() && contextKind != ContextKind.SHARE_ALL) {
                 throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Only shared contexts are allowed");
             }
             handleSharedContexts(contextKind);
 
-            RContext.EvalThread[] threads = new RContext.EvalThread[pc];
-            int[] data = new int[pc];
-            for (int i = 0; i < pc; i++) {
+            int length = exprs.getLength();
+            RContext.EvalThread[] threads = new RContext.EvalThread[length];
+            int[] data = new int[length];
+            for (int i = 0; i < length; i++) {
                 ContextInfo info = createContextInfo(contextKind);
-                threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
+                threads[i] = new RContext.EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
                 data[i] = info.getId();
             }
             if (contextKind == ContextKind.SHARE_ALL) {
                 REnvironment.convertSearchpathToMultiSlot();
             }
-            for (int i = 0; i < pc; i++) {
+            for (int i = 0; i < length; i++) {
                 threads[i].start();
             }
-            for (int i = 0; i < pc; i++) {
+            for (int i = 0; i < length; i++) {
                 threads[i].waitForInit();
             }
             return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
@@ -200,56 +195,56 @@ public class FastRContext {
      * sublist contains the result of the evaluation with name "result". It may also have an
      * attribute "error" if the evaluation threw an exception, in which case the result will be NA.
      */
-    @RBuiltin(name = ".fastr.context.eval", kind = PRIMITIVE, parameterNames = {"exprs", "pc", "kind"}, behavior = COMPLEX)
-    public abstract static class Eval extends RBuiltinNode.Arg3 {
+    @RBuiltin(name = ".fastr.context.eval", kind = PRIMITIVE, parameterNames = {"exprs", "kind"}, behavior = COMPLEX)
+    public abstract static class Eval extends RBuiltinNode.Arg2 {
         @Override
         public Object[] getDefaultParameterValues() {
-            return new Object[]{RMissing.instance, 1, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"};
+            return new Object[]{RMissing.instance, FastROptions.SharedContexts.getBooleanValue() ? "SHARE_ALL" : "SHARE_NOTHING"};
         }
 
         static {
             Casts casts = new Casts(Eval.class);
             CastsHelper.exprs(casts);
-            CastsHelper.pc(casts);
             CastsHelper.kind(casts);
         }
 
         @Specialization
         @TruffleBoundary
-        protected Object eval(RAbstractStringVector exprs, int pc, String kind) {
+        protected Object eval(RAbstractStringVector exprs, String kind) {
             RContext.ContextKind contextKind = RContext.ContextKind.valueOf(kind);
             if (FastROptions.SharedContexts.getBooleanValue() && contextKind != ContextKind.SHARE_ALL) {
                 throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Only shared contexts are allowed");
             }
             handleSharedContexts(contextKind);
 
-            Object[] results = new Object[pc];
-            if (pc == 1) {
+            int length = exprs.getLength();
+            Object[] results = new Object[length];
+            if (length == 1) {
                 ContextInfo info = createContextInfo(contextKind);
                 PolyglotEngine vm = info.createVM();
                 try {
-                    results[0] = RContext.EvalThread.run(vm, info, RSource.fromTextInternal(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL));
+                    results[0] = RContext.EvalThread.run(vm, info, RSource.fromTextInternalInvisible(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL));
                 } finally {
                     vm.dispose();
                 }
             } else {
                 // separate threads that run in parallel; invoking thread waits for completion
-                RContext.EvalThread[] threads = new RContext.EvalThread[pc];
-                for (int i = 0; i < pc; i++) {
+                RContext.EvalThread[] threads = new RContext.EvalThread[length];
+                for (int i = 0; i < length; i++) {
                     ContextInfo info = createContextInfo(contextKind);
-                    threads[i] = new RContext.EvalThread(info, RSource.fromTextInternal(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
+                    threads[i] = new RContext.EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
                 }
                 if (contextKind == ContextKind.SHARE_ALL) {
                     REnvironment.convertSearchpathToMultiSlot();
                 }
-                for (int i = 0; i < pc; i++) {
+                for (int i = 0; i < length; i++) {
                     threads[i].start();
                 }
-                for (int i = 0; i < pc; i++) {
+                for (int i = 0; i < length; i++) {
                     threads[i].waitForInit();
                 }
                 try {
-                    for (int i = 0; i < pc; i++) {
+                    for (int i = 0; i < length; i++) {
                         threads[i].join();
                         results[i] = threads[i].getEvalResult();
                     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
index 5f6462db6d..41ea6dacda 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
@@ -107,6 +107,13 @@ public class RSource {
         return fromTextInternal(text, description, RRuntime.R_APP_MIME);
     }
 
+    /**
+     * Create an {@code internal} source from {@code text} and {@code description}.
+     */
+    public static Source fromTextInternalInvisible(String text, Internal description) {
+        return fromTextInternalInvisible(text, description, RRuntime.R_APP_MIME);
+    }
+
     /**
      * Create an {@code internal} source from {@code text} and {@code description} of given
      * {@code mimeType}.
@@ -116,6 +123,15 @@ public class RSource {
         return Source.newBuilder(text).name(description.string).mimeType(mimeType).internal().interactive().build();
     }
 
+    /**
+     * Create an {@code internal} source from {@code text} and {@code description} of given
+     * {@code mimeType}.
+     */
+
+    public static Source fromTextInternalInvisible(String text, Internal description, String mimeType) {
+        return Source.newBuilder(text).name(description.string).mimeType(mimeType).internal().build();
+    }
+
     /**
      * Create an {@code internal} source for a deparsed package from {@code text} and
      * {@code packageName}.
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
index 5977fcb204..147da5fcf5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
@@ -10,7 +10,7 @@ if (length(grep("FastR", R.Version()$version.string)) == 1) {
     y <- .fastr.channel.receive(ch1)
     .fastr.context.join(cx)
     # create two child contexts
-    cx <- .fastr.context.spawn(code, 2)
+    cx <- .fastr.context.spawn(rep(code, 2))
     .fastr.channel.send(ch1, 42)
     .fastr.channel.send(ch1, 24)
     y <- .fastr.channel.receive(ch1)
-- 
GitLab


From 44e12ce4fd6597273cb00a159e6a8614b5670142 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:19 +0200
Subject: [PATCH 295/402] introduce SHARED cluster

---
 .../parallel/R/forkcluster_overrides.R        | 80 +++++++++++--------
 1 file changed, 47 insertions(+), 33 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
index c9367588dd..2d3ebf6b49 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
@@ -11,22 +11,35 @@
 
 ## Derived from snow and parallel packages
 
-eval(expression(
+eval(expression({
+
+# overwritten functions:
+
+makeCluster <- function (spec, type = getClusterOption("type"), ...) {
+    switch(type,
+        PSOCK = makePSOCKcluster(spec, ...),
+        FORK = makeForkCluster(spec, ...),
+        SOCK = snow::makeSOCKcluster(spec, ...),
+        MPI = snow::makeMPIcluster(spec, ...),
+        NWS = snow::makeNWScluster(spec, ...),
+        SHARED = makeSHAREDcluster(spec, ...), # this line was added
+        stop("unknown cluster type"))
+}
+
+# added functions:
+
 closeNode.SHAREDnode <- function(node) {
     .fastr.channel.close(node$channel)
-}), asNamespace("parallel"))
+}
 
-eval(expression(
 sendData.SHAREDnode <- function(node, data) {
     .fastr.channel.send(node$channel, data)
-}), asNamespace("parallel"))
+}
 
-eval(expression(
 recvData.SHAREDnode <- function(node) {
     .fastr.channel.receive(node$channel)
-}), asNamespace("parallel"))
+}
 
-eval(expression(
 recvOneData.SHAREDcluster <- function(cl) {
 	channel_ids = lapply(cl, function(l) l[["channel"]])
     res <- .fastr.channel.select(channel_ids)
@@ -35,39 +48,43 @@ recvOneData.SHAREDcluster <- function(cl) {
 	indexes = lapply(cl, function(l, id) if (identical(l[["channel"]], id)) id else as.integer(NA), id=selected_id)
 	node_ind = which(as.double(indexes)==as.double(selected_id))
 	list(node = node_ind, value = res[[2]])
-}), asNamespace("parallel"))
+}
 
-eval(expression(
-fastr.newSHAREDnodes <- function(nnodes, debug, options = defaultClusterOptions)
-{
+newSHAREDnodes <- function(nnodes, debug, options = defaultClusterOptions) {
 	context_code <- vector("character", nnodes)
 	contexts <- vector("integer", nnodes)
 	channels <- vector("integer", nnodes)
+	outfile <- getClusterOption("outfile", options)
 	for (i in 1:nnodes) {
 		# generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers)
 		port <- as.integer(parallel:::getClusterOption("port", options) + i * 1000)
-		script <- file.path(R.home(), "com.oracle.truffle.r.native", "library", "parallel", "RSHAREDnode.R")
-
-    	context_code[[i]] <- paste0("commandArgs<-function() c('--args', 'PORT=", port, "'); source('", script, "')")
-		if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", i, context_code[[i]]))
+		
+		startup <- substitute(local({
+            makeSHAREDmaster <- function(key) {
+                channel <- .fastr.channel.get(as.integer(key))
+                structure(list(channel=channel), class = "SHAREDnode")
+            }
+            parallel:::sinkWorkerOutput(OUTFILE)
+            parallel:::slaveLoop(makeSHAREDmaster(PORT))
+        }), list(OUTFILE=outfile, PORT=port))
+		
+        context_code[[i]] <- paste0(deparse(startup), collapse="\n")
+        if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", i, context_code[[i]]))
 
 		## Need to return a list here, in the same form as the
 		## "cluster" data structure.
     	channels[[i]] <- .fastr.channel.create(port)
 		if (isTRUE(debug)) cat(sprintf("Context %d started!\n", i))
 	}
-    contexts <- .fastr.context.spawn(context_code, nnodes)
+    contexts <- .fastr.context.spawn(context_code)
     cl <- vector("list", nnodes)
 	for (i in 1:nnodes) {
 		cl[[i]] <- structure(list(channel = channels[[i]], context=contexts[[i]], rank = i), class = "SHAREDnode")
 	}
 	cl
-	
-}), asNamespace("parallel"))
+}
 
-makeForkClusterExpr <- expression({
-makeForkCluster <- function(nnodes = getOption("mc.cores", 2L), options = defaultClusterOptions, ...)
-{
+makeSHAREDcluster <- function(nnodes = getOption("mc.cores", 2L), options = defaultClusterOptions, ...) {
     nnodes <- as.integer(nnodes)
     if(is.na(nnodes) || nnodes < 1L) stop("'nnodes' must be >= 1")
     .check_ncores(nnodes)
@@ -76,25 +93,22 @@ makeForkCluster <- function(nnodes = getOption("mc.cores", 2L), options = defaul
 	# Add the "debug" option defaulted to FALSE, if the user didn't specify
 	# If the user gives TRUE, print extra stuff during cluster setup
 	debug <- FALSE
-	tryCatch(
-		debug <- parallel:::getClusterOption("debug", options),
-		error = function(e) { }
-	)
-	options <- parallel:::addClusterOptions(options, list(debug = debug))
+	if (exists("debug", envir=options, inherits=FALSE)) {
+		debug <- parallel:::getClusterOption("debug", options)
+	} else {
+		options <- parallel:::addClusterOptions(options, list(debug = debug))
+	}
 	
-    cl <- fastr.newSHAREDnodes(nnodes, debug = debug, options=options)
+    cl <- newSHAREDnodes(nnodes, debug = debug, options=options)
 	class(cl) <- c("SHAREDcluster", "cluster")
 	cl
-}; environment(makeForkCluster)<-asNamespace("parallel")})
-eval(makeForkClusterExpr, asNamespace("parallel"))
-# seems like we don't need these anymore, but let's make sure
-#eval(makeForkClusterExpr, as.environment("package:parallel"))
-
+}
 
-eval(expression(
 stopCluster.SHAREDcluster <- function(cl) {
     for (n in cl) {
         parallel:::postNode(n, "DONE")
         .fastr.context.join(n$context)
     }
+}
+
 }), asNamespace("parallel"))
-- 
GitLab


From 5d0f1fc0f3e79b3c8c718c08545e5786b3c6b1c7 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:21 +0200
Subject: [PATCH 296/402] performance warnings for stack frame accesses

---
 .../src/com/oracle/truffle/r/runtime/RError.java          | 8 +++++++-
 .../src/com/oracle/truffle/r/runtime/Utils.java           | 6 ++++++
 .../src/com/oracle/truffle/r/runtime/data/RPromise.java   | 1 +
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index f1086ac6da..bfa0177952 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -264,7 +264,13 @@ public final class RError extends RuntimeException {
     @TruffleBoundary
     public static void performanceWarning(String string) {
         if (FastROptions.PerformanceWarnings.getBooleanValue()) {
-            warning(RError.SHOW_CALLER2, Message.PERFORMANCE, string);
+            System.out.println("Performance warning: " + string);
+            StackTraceElement[] trace = new RuntimeException().getStackTrace();
+            for (int i = 1; i < trace.length && i < 8; i++) {
+                StackTraceElement element = trace[i];
+                System.out.println("  at " + element.getClassName() + "." + element.getMethodName() + "(" + element.getFileName() + ":" + element.getLineNumber() + ")");
+            }
+            // warning(RError.SHOW_CALLER2, Message.PERFORMANCE, string);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index 847c4a79e1..a5ac484ad1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -363,6 +363,7 @@ public final class Utils {
      */
     @TruffleBoundary
     public static Frame getStackFrame(FrameAccess fa, RCaller target) {
+        RError.performanceWarning("slow frame access - getStackFrame1");
         assert target != null;
         return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Frame>() {
             boolean first = true;
@@ -389,6 +390,7 @@ public final class Utils {
      */
     @TruffleBoundary
     public static Frame getStackFrame(FrameAccess fa, int depth) {
+        RError.performanceWarning("slow frame access - getStackFrame2");
         return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Frame>() {
             boolean first = true;
 
@@ -419,6 +421,7 @@ public final class Utils {
      */
     @TruffleBoundary
     public static <T> T iterateRFrames(FrameAccess fa, Function<Frame, T> func) {
+        RError.performanceWarning("slow frame access - iterateRFrames");
         return Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<T>() {
             boolean first = true;
 
@@ -464,6 +467,7 @@ public final class Utils {
      */
     @TruffleBoundary
     public static Frame getActualCurrentFrame() {
+        RError.performanceWarning("slow frame access - getActualCurrentFrame");
         FrameInstance frameInstance = Truffle.getRuntime().getCurrentFrame();
         if (frameInstance == null) {
             // Might be the case during initialization, when envs are prepared before the actual
@@ -529,6 +533,7 @@ public final class Utils {
      */
     @TruffleBoundary
     public static Object createTraceback(int skip) {
+        RError.performanceWarning("slow frame access - createTraceback");
         FrameInstance current = Truffle.getRuntime().getCurrentFrame();
         if (current != null) {
             TracebackVisitor fiv = new TracebackVisitor(skip);
@@ -544,6 +549,7 @@ public final class Utils {
      */
     @TruffleBoundary
     public static String createStackTrace(boolean printFrameSlots) {
+        RError.performanceWarning("slow frame access - createStackTrace");
         FrameInstance current = Truffle.getRuntime().getCurrentFrame();
         if (current == null) {
             return "no R stack trace available\n";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
index cdb65dbbb9..8a7f12d15d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -318,6 +318,7 @@ public class RPromise implements RTypedValue {
         public void materialize() {
             if (execFrame == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
+// System.out.println("EagerPromiseBase.materialize()");
                 this.execFrame = Utils.getStackFrame(FrameAccess.MATERIALIZE, targetFrame).materialize();
             }
         }
-- 
GitLab


From 145e7b91896907cb41a171b1934a30065701ecae Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:24 +0200
Subject: [PATCH 297/402] more node copying in replacements and specials

---
 .../r/nodes/control/ReplacementNode.java      |  9 ++++--
 .../r/nodes/function/RCallSpecialNode.java    | 29 +++++++++++++++++--
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index 13c607e358..2eb77334c9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -60,6 +60,11 @@ abstract class ReplacementNode extends OperatorNode {
         this.lhs = lhs;
     }
 
+    @Override
+    public final Node deepCopy() {
+        return RContext.getASTBuilder().process(this).asRNode();
+    }
+
     public static ReplacementNode create(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls,
                     String targetVarName, boolean isSuper, int tempNamesStartIndex, boolean isVoid) {
         CompilerAsserts.neverPartOfCompilation();
@@ -145,7 +150,7 @@ abstract class ReplacementNode extends OperatorNode {
             RSyntaxNode[] newArgs = new RSyntaxNode[2];
             newArgs[0] = (RSyntaxNode) oldArgs[0];
             newArgs[1] = builder.lookup(oldArgs[1].getLazySourceSection(), ((RSyntaxLookup) oldArgs[1]).getIdentifier() + "<-", true);
-            newSyntaxLHS = RCallSpecialNode.createCall(callLHS.getLazySourceSection(), ((RSyntaxNode) callLHS.getSyntaxLHS()).asRNode(), callLHS.getSyntaxSignature(), newArgs);
+            newSyntaxLHS = RCallSpecialNode.createCall(callLHS.getLazySourceSection(), builder.process(callLHS.getSyntaxLHS(), codeBuilderContext).asRNode(), callLHS.getSyntaxSignature(), newArgs);
         }
         return RCallSpecialNode.createCallInReplace(source, newSyntaxLHS.asRNode(), ArgumentsSignature.get(names), argNodes, 0, argNodes.length - 1).asRNode();
     }
@@ -346,7 +351,7 @@ abstract class ReplacementNode extends OperatorNode {
 
         GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, boolean isSuper,
                         int tempNamesStartIndex) {
-            super(source, operator, lhs, rhs, tempNamesStartIndex);
+            super(source, operator, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), tempNamesStartIndex);
             /*
              * When there are more than two function calls in LHS, then we save some function calls
              * by saving the intermediate results into temporary variables and reusing them.
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
index 5ba452ebe4..e87a36945f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
@@ -24,7 +24,9 @@ package com.oracle.truffle.r.nodes.function;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -165,7 +167,11 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
      */
     private RCallSpecialNode callSpecialParent;
 
-    private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special) {
+    private final boolean inReplace;
+    private final int[] ignoredArguments;
+
+    private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special, boolean inReplace,
+                    int[] ignoredArguments) {
         this.sourceSection = sourceSection;
         this.expectedFunction = expectedFunction;
         this.special = special;
@@ -173,6 +179,8 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
         this.arguments = arguments;
         this.signature = signature;
         this.visible = expectedFunction.getRBuiltin().getVisibility();
+        this.inReplace = inReplace;
+        this.ignoredArguments = ignoredArguments;
     }
 
     /**
@@ -264,7 +272,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
         RFunction expectedFunction = RContext.lookupBuiltin(name);
         RInternalError.guarantee(expectedFunction != null);
 
-        RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special);
+        RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special, inReplace, ignoredArguments);
         for (int i = 0; i < arguments.length; i++) {
             if (!inReplace || !contains(ignoredArguments, i)) {
                 if (arguments[i] instanceof RCallSpecialNode) {
@@ -316,6 +324,23 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
         }
     }
 
+    @TruffleBoundary
+    private static void log(String format, Object... args) {
+        System.out.println(String.format(format, args));
+    }
+
+    @Override
+    public Node deepCopy() {
+        assert !inReplace && callSpecialParent == null && ignoredArguments.length == 0;
+        RCallSpecialNode node = (RCallSpecialNode) RContext.getASTBuilder().process(this).asRNode();
+        node.functionNode = node.insert(node.functionNode);
+        node.special = node.insert(node.special);
+        if (node.visibility != null) {
+            node.visibility = insert(node.visibility);
+        }
+        return node;
+    }
+
     private RCallNode getRCallNode(RSyntaxNode[] newArguments) {
         return RCallNode.createCall(sourceSection, functionNode, signature, newArguments);
     }
-- 
GitLab


From fa9d20e1b33d2d759c8d811223c13c8d354b8398 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:26 +0200
Subject: [PATCH 298/402] only deoptimize frame slots with String identifiers

---
 .../r/nodes/function/PromiseHelperNode.java        |  2 +-
 .../runtime/env/frame/FrameSlotChangeMonitor.java  | 14 +++++---------
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index f2407db524..b635984a2c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -96,7 +96,7 @@ public class PromiseHelperNode extends RBaseNode {
             boolean deoptOne = false;
             for (FrameSlot slot : frame.getFrameDescriptor().getSlots().toArray(new FrameSlot[0])) {
                 // We're only interested in RPromises
-                if (slot.getKind() != FrameSlotKind.Object) {
+                if (slot.getKind() != FrameSlotKind.Object || !(slot.getIdentifier() instanceof String)) {
                     continue;
                 }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 886f4922b6..cdb9f13b1c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -681,7 +681,7 @@ public final class FrameSlotChangeMonitor {
         Object info = slot.getInfo();
         if (!(info instanceof FrameSlotInfoImpl)) {
             CompilerDirectives.transferToInterpreter();
-            throw RInternalError.shouldNotReachHere("Each FrameSlot should hold a FrameSlotInfo in its info field!");
+            throw RInternalError.shouldNotReachHere("Each FrameSlot should hold a FrameSlotInfo in its info field! " + slot.getIdentifier().getClass() + " " + slot.getIdentifier());
         }
         return (FrameSlotInfoImpl) info;
     }
@@ -703,14 +703,10 @@ public final class FrameSlotChangeMonitor {
         if (frameSlot != null) {
             return frameSlot;
         } else {
-            if (identifier instanceof String || ((RFrameSlot) identifier).isMultiSlot()) {
-                FrameDescriptorMetaData metaData = getMetaData(fd);
-                invalidateNames(metaData, Arrays.asList(identifier));
-                return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier, metaData.name.startsWith("<new-env-")),
-                                initialKind);
-            } else {
-                return fd.addFrameSlot(identifier, initialKind);
-            }
+            FrameDescriptorMetaData metaData = getMetaData(fd);
+            invalidateNames(metaData, Arrays.asList(identifier));
+            return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier, metaData.name.startsWith("<new-env-")),
+                            initialKind);
         }
     }
 
-- 
GitLab


From 871399367593d971e9131465dbd21c8130375044 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:28 +0200
Subject: [PATCH 299/402] use FrameSlotChangeMonitor in more places

---
 .../com/oracle/truffle/r/nodes/builtin/base/OnExit.java    | 3 ++-
 .../truffle/r/nodes/function/FunctionDefinitionNode.java   | 4 ++--
 .../r/nodes/function/visibility/GetVisibilityNode.java     | 3 ++-
 .../r/nodes/function/visibility/SetVisibilityNode.java     | 7 ++++---
 4 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index c1bc7253e3..4dabafd778 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 @RBuiltin(name = "on.exit", visibility = OFF, kind = PRIMITIVE, parameterNames = {"expr", "add"}, nonEvalArgs = 0, behavior = COMPLEX)
@@ -71,7 +72,7 @@ public abstract class OnExit extends RBuiltinNode.Arg2 {
 
         if (onExitSlot == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            onExitSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.OnExit, FrameSlotKind.Object);
+            onExitSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.OnExit, FrameSlotKind.Object);
         }
 
         // the empty (RNull.instance) expression is used to clear on.exit
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 89c214040c..2c87c80b61 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -515,7 +515,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         }
         if (restartStackSlot == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            restartStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.RestartStack);
+            restartStackSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.RestartStack, FrameSlotKind.Object);
         }
         return restartStackSlot;
     }
@@ -527,7 +527,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         }
         if (handlerStackSlot == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            handlerStackSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.HandlerStack);
+            handlerStackSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.HandlerStack, FrameSlotKind.Object);
         }
         return handlerStackSlot;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java
index 61a735b946..31111421b9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 /**
@@ -52,7 +53,7 @@ public final class GetVisibilityNode extends Node {
     public boolean execute(Frame frame) {
         if (frameSlot == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean);
+            frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean);
         }
         try {
             return frame.getBoolean(frameSlot);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java
index a259f498ad..f3fea2a553 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/SetVisibilityNode.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RVisibility;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 /**
@@ -57,7 +58,7 @@ public final class SetVisibilityNode extends Node {
     private void ensureFrameSlot(Frame frame) {
         if (frameSlot == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean);
+            frameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean);
         }
     }
 
@@ -103,7 +104,7 @@ public final class SetVisibilityNode extends Node {
      */
     public static void executeAfterCallSlowPath(Frame frame, RCaller caller) {
         CompilerAsserts.neverPartOfCompilation();
-        frame.setBoolean(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean), caller.getVisibility());
+        frame.setBoolean(FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean), caller.getVisibility());
     }
 
     /**
@@ -111,6 +112,6 @@ public final class SetVisibilityNode extends Node {
      */
     public static void executeSlowPath(Frame frame, boolean visibility) {
         CompilerAsserts.neverPartOfCompilation();
-        frame.setBoolean(frame.getFrameDescriptor().findOrAddFrameSlot(RFrameSlot.Visibility, FrameSlotKind.Boolean), visibility);
+        frame.setBoolean(FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean), visibility);
     }
 }
-- 
GitLab


From 9755be85463ae004b1721edf93cbe26d189a85a0 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:30 +0200
Subject: [PATCH 300/402] turn on SharedContexts by default

---
 .../src/com/oracle/truffle/r/runtime/FastROptions.java          | 2 +-
 .../src/com/oracle/truffle/r/runtime/data/RPromise.java         | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index ce53703800..ad8d5d6299 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -54,7 +54,7 @@ public enum FastROptions {
     UseInternalGridGraphics("Whether the internal (Java) grid graphics implementation should be used", true),
     UseSpecials("Whether the fast-path special call nodes should be created for simple enough arguments.", true),
     ForceSources("Generate source sections for unserialized code", false),
-    SharedContexts("Whether all child contexts are to be shared contexts", false),
+    SharedContexts("Whether all child contexts are to be shared contexts", true),
     SearchPathForcePromises("Whether all promises for frames on shared path are forced in presence of shared contexts", false),
 
     // Promises optimizations
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
index 8a7f12d15d..cdb65dbbb9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -318,7 +318,6 @@ public class RPromise implements RTypedValue {
         public void materialize() {
             if (execFrame == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-// System.out.println("EagerPromiseBase.materialize()");
                 this.execFrame = Utils.getStackFrame(FrameAccess.MATERIALIZE, targetFrame).materialize();
             }
         }
-- 
GitLab


From 46edd4229015fc3eeab434ba1940f170830a67f9 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 11 Apr 2017 11:43:51 +0200
Subject: [PATCH 301/402] Added type profile to cast nodes and in some other
 places.

---
 .../r/library/fastrGrid/LUpViewPort.java      |  2 +-
 .../library/methods/MethodsListDispatch.java  |  2 +-
 .../r/library/stats/RandFunctionsNodes.java   |  2 +-
 .../nodes/builtin/base/AsCharacterFactor.java |  2 +-
 .../r/nodes/builtin/base/AsVector.java        |  2 +-
 .../truffle/r/nodes/builtin/base/Bind.java    |  6 ++--
 .../truffle/r/nodes/builtin/base/Colon.java   |  4 +--
 .../truffle/r/nodes/builtin/base/Combine.java |  2 +-
 .../truffle/r/nodes/builtin/base/Format.java  |  2 +-
 .../r/nodes/builtin/base/LaFunctions.java     |  2 +-
 .../truffle/r/nodes/builtin/base/Match.java   |  4 +--
 .../r/nodes/builtin/base/MatchArg.java        |  2 +-
 .../truffle/r/nodes/builtin/base/Order.java   |  4 +--
 .../truffle/r/nodes/builtin/base/PMinMax.java |  8 ++---
 .../truffle/r/nodes/builtin/base/Paste.java   |  4 +--
 .../truffle/r/nodes/builtin/base/Prod.java    | 33 +++++++++++--------
 .../r/nodes/builtin/base/Quantifier.java      |  4 +--
 .../truffle/r/nodes/builtin/base/Repeat.java  |  6 ++--
 .../builtin/base/S3DispatchFunctions.java     |  4 ++-
 .../truffle/r/nodes/builtin/base/Scan.java    |  2 +-
 .../r/nodes/builtin/base/SeqFunctions.java    |  2 +-
 .../r/nodes/builtin/base/StandardGeneric.java |  4 +--
 .../r/nodes/builtin/base/UpdateAttr.java      |  4 +--
 .../nodes/builtin/base/UpdateAttributes.java  |  4 +--
 .../r/nodes/builtin/base/UpdateDimNames.java  |  4 +--
 .../r/nodes/builtin/base/UpdateOldClass.java  |  2 +-
 .../truffle/r/nodes/builtin/base/VApply.java  | 10 +++---
 .../base/fastpaths/MatrixFastPath.java        |  4 +--
 .../r/nodes/builtin/fastr/FastRTrace.java     |  2 +-
 .../r/nodes/builtin/fastr/FastrDqrls.java     |  2 +-
 .../truffle/r/nodes/casts/TestCasts.java      | 32 +++++++++---------
 .../r/nodes/castsTests/CastBuilderTest.java   |  2 +-
 .../truffle/r/nodes/test/ChimneySweeping.java |  2 +-
 .../vector/CachedReplaceVectorNode.java       |  2 +-
 .../access/vector/ExtractVectorNode.java      |  2 +-
 .../nodes/access/vector/PositionCastNode.java |  2 +-
 .../access/vector/ReplaceVectorNode.java      |  2 +-
 .../truffle/r/nodes/binary/CastTypeNode.java  |  2 +-
 .../truffle/r/nodes/builtin/RBuiltinNode.java |  4 +--
 .../r/nodes/builtin/RExternalBuiltinNode.java | 10 +++---
 .../builtin/casts/ValueForwardingNode.java    |  2 +-
 .../truffle/r/nodes/ffi/AsLogicalNode.java    |  2 +-
 .../truffle/r/nodes/ffi/CoerceVectorNode.java |  4 +--
 .../r/nodes/function/ClassHierarchyNode.java  |  2 +-
 .../r/nodes/objects/GetS4DataSlot.java        |  2 +-
 .../truffle/r/nodes/objects/NewObject.java    |  4 +--
 .../truffle/r/nodes/unary/CastListNode.java   |  9 +++--
 .../truffle/r/nodes/unary/CastNode.java       |  9 ++++-
 .../oracle/truffle/r/runtime/RArguments.java  |  7 +++-
 49 files changed, 129 insertions(+), 107 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java
index 6e51c4b4d8..bee678f784 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java
@@ -39,7 +39,7 @@ public abstract class LUpViewPort extends RExternalBuiltinNode.Arg1 {
         GridState gridState = GridContext.getContext().getGridState();
         RList newViewPort = gridState.getViewPort();
         for (int i = 0; i < n; i++) {
-            newViewPort = (RList) castParentToViewPort.execute(newViewPort.getDataAt(ViewPort.PVP_PARENT));
+            newViewPort = (RList) castParentToViewPort.doCast(newViewPort.getDataAt(ViewPort.PVP_PARENT));
         }
         gridState.setViewPort(newViewPort);
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 29e34173b7..5ec3a48535 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -379,7 +379,7 @@ public class MethodsListDispatch {
                         if (pckg.length() > 0) {
                             Object gpckgObj = getPckgAttrNode.execute(vl);
                             if (gpckgObj != null) {
-                                String gpckg = checkSingleString(castToVector.execute(gpckgObj), false, "The \"package\" slot in generic function object", this, classHierarchyNode);
+                                String gpckg = checkSingleString(castToVector.doCast(gpckgObj), false, "The \"package\" slot in generic function object", this, classHierarchyNode);
                                 ok = pckg.equals(gpckg);
                             }
                         } else {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
index 2dbf940c2f..a0792babde 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java
@@ -76,7 +76,7 @@ public final class RandFunctionsNodes {
         public int lengthOne(RAbstractVector vector,
                         @Cached("createNonPreserving()") CastIntegerNode castNode,
                         @Cached("create()") BranchProfile seenNA) {
-            int result = ((RAbstractIntVector) castNode.execute(vector)).getDataAt(0);
+            int result = ((RAbstractIntVector) castNode.doCast(vector)).getDataAt(0);
             if (RRuntime.isNA(result) || result < 0) {
                 seenNA.enter();
                 throw RError.error(SHOW_CALLER, INVALID_UNNAMED_ARGUMENTS);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
index d68ee44432..71ceeb0626 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacterFactor.java
@@ -65,7 +65,7 @@ public abstract class AsCharacterFactor extends RBuiltinNode.Arg1 {
         String[] data = new String[n];
         Object levsAttr = getLevelsAttrNode.execute(xVec);
         Object levs;
-        if (levsAttr == null || !((levs = castToVectorNode.execute(levsAttr)) instanceof RAbstractStringVector)) {
+        if (levsAttr == null || !((levs = castToVectorNode.doCast(levsAttr)) instanceof RAbstractStringVector)) {
             throw error(RError.Message.MALFORMED_FACTOR);
         }
         RAbstractStringVector levsString = (RAbstractStringVector) levs;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index b54c737925..ece6175263 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -168,7 +168,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
                         @Cached("fromMode(cachedMode)") RType type,
                         @Cached("createCast(type)") CastNode cast,
                         @Cached("create()") DropAttributesNode drop) {
-            return drop.execute(cast == null ? x : cast.execute(x));
+            return drop.execute(cast == null ? x : cast.doCast(x));
         }
 
         public abstract static class DropAttributesNode extends RBaseNode {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 1f5c1a0d15..1247be422f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -133,7 +133,7 @@ public abstract class Bind extends RBaseNode {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return (RAbstractVector) castVector.execute(value);
+        return (RAbstractVector) castVector.doCast(value);
     }
 
     protected Object castLogical(Object operand, boolean preserveAllAttr) {
@@ -141,7 +141,7 @@ public abstract class Bind extends RBaseNode {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castLogical = insert(CastLogicalNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
-        return castLogical.execute(operand);
+        return castLogical.doCast(operand);
     }
 
     @SuppressWarnings("unused")
@@ -210,7 +210,7 @@ public abstract class Bind extends RBaseNode {
     }
 
     private RAbstractVector getVector(Object arg, CastNode castNode, boolean needsVectorCast) {
-        Object result = castNode.execute(arg);
+        Object result = castNode.doCast(arg);
         RAbstractVector vector;
         if (needsVectorCast) {
             vector = castVector(result);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index 4d4a9b0993..90e3aa33b9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -64,7 +64,7 @@ abstract class ColonSpecial extends RNode {
 
     @Specialization
     protected Object colon(Object left, Object right) {
-        return internal.execute(leftCast.execute(left), rightCast.execute(right));
+        return internal.execute(leftCast.doCast(left), rightCast.doCast(right));
     }
 }
 
@@ -89,7 +89,7 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
 
     @Specialization
     protected RSequence colon(Object left, Object right) {
-        return internal.execute(leftCast.execute(left), rightCast.execute(right));
+        return internal.execute(leftCast.doCast(left), rightCast.doCast(right));
     }
 
     @NodeInfo(cost = NodeCost.NONE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 8e38c82231..4900debc6e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -215,7 +215,7 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
         for (int i = 0; i < elements.length; i++) {
             CombineInputCast inputCast = getCast(i);
             Object value = args[i];
-            Object element = (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : cast.execute(inputCast.cast(value));
+            Object element = (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : cast.doCast(inputCast.cast(value));
             element = inputCast.valueProfile.profile(element);
             elements[i] = element;
             size += getElementSize(element);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index aaeb3235e0..6075cc51c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -62,7 +62,7 @@ public abstract class Format extends RBuiltinNode.Arg9 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castInteger = insert(CastIntegerNodeGen.create(true, false, false));
         }
-        return (RAbstractIntVector) castInteger.execute(operand);
+        return (RAbstractIntVector) castInteger.doCast(operand);
     }
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 76f62d8d8d..0840afea59 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -645,7 +645,7 @@ public class LaFunctions {
             if (a instanceof RAbstractDoubleVector) {
                 System.arraycopy(a.getInternalStore(), 0, avals, 0, n * n);
             } else {
-                RDoubleVector aDouble = (RDoubleVector) castDouble.execute(a);
+                RDoubleVector aDouble = (RDoubleVector) castDouble.doCast(a);
                 assert aDouble != a;
                 avals = aDouble.getInternalStore();
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index e15199525e..610db0cda9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -146,7 +146,7 @@ public abstract class Match extends RBuiltinNode.Arg4 {
     protected Object matchList(RAbstractListVector x, RAbstractVector table, int nomatchObj, @SuppressWarnings("unused") Object incomparables,
                     @Cached("create()") CastStringNode cast,
                     @Cached("createInternal()") ProfiledMatchInternalNode match) {
-        return match.execute((RAbstractVector) cast.execute(x), table, nomatchObj);
+        return match.execute((RAbstractVector) cast.doCast(x), table, nomatchObj);
     }
 
     @Specialization(guards = {"!isRAbstractListVector(x)", "!isRAbstractIntVector(x) || !isFactor(x)", "!isRAbstractIntVector(table) || !isFactor(table)"})
@@ -203,7 +203,7 @@ public abstract class Match extends RBuiltinNode.Arg4 {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 castString = insert(CastStringNodeGen.create(false, false, false));
             }
-            return (RAbstractStringVector) castString.execute(operand);
+            return (RAbstractStringVector) castString.doCast(operand);
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
index f672ab2914..0598b8eda2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchArg.java
@@ -87,7 +87,7 @@ public abstract class MatchArg extends RBuiltinNode.Arg3 {
         public abstract Object execute(Object arg, Object choices, Object severalOK);
 
         public final Object castAndExecute(Object arg, Object choices, Object severalOK) {
-            return execute(argCast.execute(arg), choicesCast.execute(choices), severalOKCast.execute(severalOK));
+            return execute(argCast.doCast(arg), choicesCast.doCast(choices), severalOKCast.doCast(severalOK));
         }
 
         @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
index d13a708f19..3bfa03b888 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java
@@ -139,7 +139,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return (RAbstractVector) castVector.execute(value);
+        return (RAbstractVector) castVector.doCast(value);
     }
 
     private RAbstractVector castVector2(Object value) {
@@ -147,7 +147,7 @@ public abstract class Order extends RPrecedenceBuiltinNode {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector2 = insert(CastToVectorNodeGen.create(false));
         }
-        return (RAbstractVector) castVector2.execute(value);
+        return (RAbstractVector) castVector2.doCast(value);
     }
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index 4b9aed674a..7f2f570817 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -106,7 +106,7 @@ public abstract class PMinMax extends RBuiltinNode.Arg2 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return ((RAbstractVector) castVector.execute(value)).materialize();
+        return ((RAbstractVector) castVector.doCast(value)).materialize();
     }
 
     private CastNode getIntegerCastNode() {
@@ -145,7 +145,7 @@ public abstract class PMinMax extends RBuiltinNode.Arg2 {
                 return vecLength;
             }
             length = Math.max(length, vecLength);
-            argValues[i] = castNode.execute(v);
+            argValues[i] = castNode.doCast(v);
         }
         return length;
     }
@@ -228,8 +228,8 @@ public abstract class PMinMax extends RBuiltinNode.Arg2 {
                     @Cached("create()") CastToVectorNode castVectorX,
                     @Cached("create()") CastToVectorNode castVectorY) {
         Object[] argValues = args.getArguments();
-        RAbstractDoubleVector x = (RAbstractDoubleVector) castVectorX.execute(castX.execute(argValues[0]));
-        RAbstractDoubleVector y = (RAbstractDoubleVector) castVectorY.execute(castY.execute(argValues[1]));
+        RAbstractDoubleVector x = (RAbstractDoubleVector) castVectorX.doCast(castX.doCast(argValues[0]));
+        RAbstractDoubleVector y = (RAbstractDoubleVector) castVectorY.doCast(castY.doCast(argValues[1]));
         int xLength = x.getLength();
         int yLength = y.getLength();
         int maxLength = Math.max(xLength, yLength);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index dfe6386183..d128c387dc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -93,11 +93,11 @@ public abstract class Paste extends RBuiltinNode.Arg3 {
         RStringVector classVec = getClassHierarchyNode().execute(result);
         if (hasNoClassProfile.profile(classVec == null || classVec.getLength() == 0)) {
             // coerce non-string result to string, i.e. do what 'as.character' would do
-            return getAsCharacterNode().execute(result);
+            return getAsCharacterNode().doCast(result);
         }
         // invoke the actual 'as.character' function (with its dispatch)
         ensureAsCharacterFuncNodes();
-        return castAsCharacterResultNode.execute(asCharacterDispatcher.call(frame, result));
+        return castAsCharacterResultNode.doCast(asCharacterDispatcher.call(frame, result));
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
index e9c8a1a306..cc8bb51840 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
@@ -17,6 +17,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -102,45 +103,51 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
         return ret;
     }
 
+    private final ValueProfile intVecProfile = ValueProfile.createClassProfile();
+
     @Specialization
     protected double prod(RAbstractDoubleVector x) {
-        double product = x.getDataAt(0);
-        for (int k = 1; k < x.getLength(); k++) {
-            product = prod.op(product, x.getDataAt(k));
+        RAbstractDoubleVector profiledVec = intVecProfile.profile(x);
+        double product = profiledVec.getDataAt(0);
+        for (int k = 1; k < profiledVec.getLength(); k++) {
+            product = prod.op(product, profiledVec.getDataAt(k));
         }
         return product;
     }
 
     @Specialization
     protected double prod(RAbstractIntVector x) {
-        double product = x.getDataAt(0);
-        for (int k = 1; k < x.getLength(); k++) {
-            product = prod.op(product, x.getDataAt(k));
+        RAbstractIntVector profiledVec = intVecProfile.profile(x);
+        double product = profiledVec.getDataAt(0);
+        for (int k = 1; k < profiledVec.getLength(); k++) {
+            product = prod.op(product, profiledVec.getDataAt(k));
         }
         return product;
     }
 
     @Specialization
     protected double prod(RAbstractLogicalVector x) {
-        double product = x.getDataAt(0);
-        for (int k = 1; k < x.getLength(); k++) {
-            product = prod.op(product, x.getDataAt(k));
+        RAbstractLogicalVector profiledVec = intVecProfile.profile(x);
+        double product = profiledVec.getDataAt(0);
+        for (int k = 1; k < profiledVec.getLength(); k++) {
+            product = prod.op(product, profiledVec.getDataAt(k));
         }
         return product;
     }
 
     @Specialization
     protected RComplex prod(RAbstractComplexVector x) {
-        RComplex product = x.getDataAt(0);
-        for (int k = 1; k < x.getLength(); k++) {
-            RComplex a = x.getDataAt(k);
+        RAbstractComplexVector profiledVec = intVecProfile.profile(x);
+        RComplex product = profiledVec.getDataAt(0);
+        for (int k = 1; k < profiledVec.getLength(); k++) {
+            RComplex a = profiledVec.getDataAt(k);
             product = prod.op(product.getRealPart(), product.getImaginaryPart(), a.getRealPart(), a.getImaginaryPart());
         }
         return product;
     }
 
     @Specialization
-    protected double prod(RNull n) {
+    protected double prod(@SuppressWarnings("unused") RNull n) {
         return 1d;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index 8a2811b1f8..c88f58c48a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -70,7 +70,7 @@ public abstract class Quantifier extends RBuiltinNode.Arg2 {
 
         @Override
         public Object execute(Object value) {
-            return profile.profile(next.execute(value));
+            return profile.profile(next.doCast(value));
         }
     }
 
@@ -146,7 +146,7 @@ public abstract class Quantifier extends RBuiltinNode.Arg2 {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 createArgCast(index);
             }
-            Object castValue = argCastNodes[index].execute(argValue);
+            Object castValue = argCastNodes[index].doCast(argValue);
             if (castValue instanceof RAbstractLogicalVector) {
                 RAbstractLogicalVector vector = (RAbstractLogicalVector) castValue;
                 naCheck.enable(vector);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
index cd00bcf957..83f22bc1cd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java
@@ -138,9 +138,9 @@ public abstract class Repeat extends RBuiltinNode.Arg2 {
         RArgsValuesAndNames margs = prepareArgs.execute(args, null);
 
         // cast arguments
-        Object times = castTimes.execute(margs.getArgument(ARG_IDX_TIMES));
-        Object lengthOut = castLengthOut.execute(margs.getArgument(ARG_IDX_LENGHT_OUT));
-        Object each = castEach.execute(margs.getArgument(ARG_IDX_EACH));
+        Object times = castTimes.doCast(margs.getArgument(ARG_IDX_TIMES));
+        Object lengthOut = castLengthOut.doCast(margs.getArgument(ARG_IDX_LENGHT_OUT));
+        Object each = castEach.doCast(margs.getArgument(ARG_IDX_EACH));
 
         return internalNode.execute(frame, x, times, lengthOut, each);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
index 8c2dfd931f..cbbb234aaf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java
@@ -135,6 +135,7 @@ public abstract class S3DispatchFunctions {
          */
         private Object getEnclosingArg(VirtualFrame frame, String generic) {
             if (RArguments.getArgumentsLength(frame) == 0 || RArguments.getArgument(frame, 0) == null) {
+                CompilerDirectives.transferToInterpreter();
                 throw error(RError.Message.UNKNOWN_FUNCTION_USE_METHOD, generic, RRuntime.toString(RNull.instance));
             }
             Object enclosingArg = RArguments.getArgument(frame, 0);
@@ -195,6 +196,7 @@ public abstract class S3DispatchFunctions {
 
         private final ValueProfile parameterSignatureProfile = ValueProfile.createIdentityProfile();
         private final ValueProfile suppliedParameterSignatureProfile = ValueProfile.createIdentityProfile();
+        private final ValueProfile rootNodeProfile = ValueProfile.createClassProfile();
 
         static {
             Casts.noCasts(NextMethod.class);
@@ -237,7 +239,7 @@ public abstract class S3DispatchFunctions {
             // arguments passed to NextMethod, the later override the former on a name clash
             ArgumentsSignature finalSignature;
             ArgumentsSignature suppliedSignature = suppliedParameterSignatureProfile.profile(RArguments.getSuppliedSignature(frame));
-            Object[] suppliedArguments = collectArguments.execute(frame, parameterSignatureProfile.profile(RArguments.getSignature(frame)));
+            Object[] suppliedArguments = collectArguments.execute(frame, parameterSignatureProfile.profile(RArguments.getSignature(frame, rootNodeProfile)));
             if (emptyArgsProfile.profile(args == RArgsValuesAndNames.EMPTY)) {
                 finalSignature = suppliedSignature;
             } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
index 62c1180a12..db79d22096 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java
@@ -73,7 +73,7 @@ public abstract class Scan extends RBuiltinNode.Arg19 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return ((RAbstractVector) castVector.execute(value)).materialize();
+        return ((RAbstractVector) castVector.doCast(value)).materialize();
     }
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 2207d23444..80c1bfd838 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -345,7 +345,7 @@ public final class SeqFunctions {
         protected RIntSequence seq(VirtualFrame frame, Object value,
                         @Cached("createLengthResultCast()") CastNode resultCast,
                         @Cached("createLengthDispatcher()") RExplicitBaseEnvCallDispatcher dispatcher) {
-            int result = (Integer) resultCast.execute(dispatcher.call(frame, value));
+            int result = (Integer) resultCast.doCast(dispatcher.call(frame, value));
             return RDataFactory.createIntSequence(1, 1, result);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
index b96cfacbd5..0334382ddc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java
@@ -100,7 +100,7 @@ public abstract class StandardGeneric extends RBuiltinNode.Arg2 {
             mtable = (REnvironment) RContext.getEngine().evalFunction(currentFunction, frame.materialize(), RCaller.create(frame, getOriginalCall()), null, def);
         }
         RList sigArgs = (RList) readSigARgs.execute(null, fnFrame);
-        int sigLength = (int) castIntScalar.execute(readSigLength.execute(null, fnFrame));
+        int sigLength = (int) castIntScalar.doCast(readSigLength.execute(null, fnFrame));
         if (sigLength > sigArgs.getLength()) {
             throw error(RError.Message.GENERIC, "'.SigArgs' is shorter than '.SigLength' says it should be");
         }
@@ -134,7 +134,7 @@ public abstract class StandardGeneric extends RBuiltinNode.Arg2 {
             noGenFunFound.enter();
             return null;
         }
-        String gen = (String) castStringScalar.execute(genObj);
+        String gen = (String) castStringScalar.doCast(genObj);
         if (sameNamesProfile.profile(gen == fname)) {
             return stdGenericInternal(frame, fname, fn);
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index 1487aa333f..1b8e654595 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -120,7 +120,7 @@ public abstract class UpdateAttr extends RBuiltinNode.Arg3 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castInteger = insert(CastIntegerNodeGen.create(true, false, false));
         }
-        return (RAbstractIntVector) castInteger.execute(vector);
+        return (RAbstractIntVector) castInteger.doCast(vector);
     }
 
     private RAbstractVector castVector(Object value) {
@@ -128,7 +128,7 @@ public abstract class UpdateAttr extends RBuiltinNode.Arg3 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return (RAbstractVector) castVector.execute(value);
+        return (RAbstractVector) castVector.doCast(value);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 70631ae526..c28a5e5175 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -105,7 +105,7 @@ public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castInteger = insert(CastIntegerNodeGen.create(true, false, false));
         }
-        return (RAbstractIntVector) castInteger.execute(vector);
+        return (RAbstractIntVector) castInteger.doCast(vector);
     }
 
     private RAbstractVector castVector(Object value) {
@@ -113,7 +113,7 @@ public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return (RAbstractVector) castVector.execute(value);
+        return (RAbstractVector) castVector.doCast(value);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index d4b65ff604..080ad9a807 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -65,7 +65,7 @@ public abstract class UpdateDimNames extends RBuiltinNode.Arg2 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castStringNode = insert(CastStringNodeGen.create(true, true, true));
         }
-        return castStringNode.execute(o);
+        return castStringNode.doCast(o);
     }
 
     private RAbstractVector castVector(Object value) {
@@ -73,7 +73,7 @@ public abstract class UpdateDimNames extends RBuiltinNode.Arg2 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVectorNode = insert(CastToVectorNodeGen.create(false));
         }
-        return ((RAbstractVector) castVectorNode.execute(value));
+        return ((RAbstractVector) castVectorNode.doCast(value));
     }
 
     public abstract RAbstractContainer executeRAbstractContainer(RAbstractContainer container, Object o);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index d766b5077c..d161c63837 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -57,7 +57,7 @@ public abstract class UpdateOldClass extends RBuiltinNode.Arg2 {
             return setOldClass(arg, RNull.instance);
         }
         initCastStringNode();
-        Object result = castStringNode.execute(className);
+        Object result = castStringNode.doCast(className);
         return setOldClass(arg, (RStringVector) result);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index f7ca2e99fb..56d5d6be3e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -109,7 +109,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castComplex = insert(CastComplexNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
-        return castComplex.execute(operand);
+        return castComplex.doCast(operand);
     }
 
     private Object castDouble(Object operand, boolean preserveAllAttr) {
@@ -117,7 +117,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castDouble = insert(CastDoubleNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
-        return castDouble.execute(operand);
+        return castDouble.doCast(operand);
     }
 
     private Object castInteger(Object operand, boolean preserveAllAttr) {
@@ -125,7 +125,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castInteger = insert(CastIntegerNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
-        return castInteger.execute(operand);
+        return castInteger.doCast(operand);
     }
 
     private Object castLogical(Object operand, boolean preserveAllAttr) {
@@ -133,7 +133,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castLogical = insert(CastLogicalNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
-        return castLogical.execute(operand);
+        return castLogical.doCast(operand);
     }
 
     private Object castString(Object operand, boolean preserveAllAttr) {
@@ -141,7 +141,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castString = insert(CastStringNodeGen.create(true, preserveAllAttr, preserveAllAttr));
         }
-        return castString.execute(operand);
+        return castString.doCast(operand);
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
index 0baf7029f0..1be6fc9e6c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
@@ -60,8 +60,8 @@ public abstract class MatrixFastPath extends RFastPathNode {
                     @Cached("createClassProfile()") ValueProfile classProfile) {
         boolean rowMissing = rowMissingProfile.profile(nrow == RMissing.instance);
         boolean colMissing = colMissingProfile.profile(ncol == RMissing.instance);
-        int row = rowMissing ? 1 : firstRow.executeInt(castRow.execute(nrow));
-        int col = colMissing ? 1 : firstCol.executeInt(castCol.execute(ncol));
+        int row = rowMissing ? 1 : firstRow.executeInt(castRow.doCast(nrow));
+        int col = colMissing ? 1 : firstCol.executeInt(castCol.doCast(ncol));
         Object dim = dimMissingProfile.profile(dimnames == RMissing.instance) ? RNull.instance : dimnames;
         return matrix.execute(classProfile.profile(data), row, col, false, dim, rowMissing, colMissing);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
index 66cc113556..5fe5c8bdba 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTrace.java
@@ -159,7 +159,7 @@ public class FastRTrace {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
                     castLogical = insert(CastLogicalNodeGen.create(false, false, false));
                 }
-                print = RRuntime.fromLogical((byte) castLogical.execute(printObj));
+                print = RRuntime.fromLogical((byte) castLogical.doCast(printObj));
             }
             complexCase(func, tracer, exit, at, print, signature);
             visibility.execute(frame, true);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
index d7d7701f67..5dc87230fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
@@ -61,7 +61,7 @@ public abstract class FastrDqrls extends RBuiltinNode.Arg7 {
 
     @Specialization(replaces = "doDouble")
     public RList doOther(RAbstractVector xVec, int n, int p, RAbstractVector yVec, int ny, double tol, RAbstractDoubleVector coeffVec, @Cached(value = "create()") CastDoubleNode castNode) {
-        return call(xVec, ((RAbstractDoubleVector) castNode.execute(xVec)).materialize(), n, p, yVec, ((RAbstractDoubleVector) castNode.execute(yVec)).materialize(), ny, tol, coeffVec);
+        return call(xVec, ((RAbstractDoubleVector) castNode.doCast(xVec)).materialize(), n, p, yVec, ((RAbstractDoubleVector) castNode.doCast(yVec)).materialize(), ny, tol, coeffVec);
     }
 
     private RList call(RAbstractVector originalXVec, RDoubleVector xVec, int n, int p, RAbstractVector originalYVec, RDoubleVector yVec, int ny, double tol, RAbstractDoubleVector coeffVec) {
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index f5fbaed21e..16b1166df7 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -150,7 +150,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 // use "new Integer(...)" to avoid boxing logic
-                return new Integer((int) node.execute(value));
+                return new Integer((int) node.doCast(value));
             }
         }
         testCompilation(new Object[]{1, 2, 3}, new Root("FirstInteger"));
@@ -171,7 +171,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                int result = (int) node.execute(constant);
+                int result = (int) node.doCast(constant);
                 CompilerAsserts.compilationConstant(result);
                 return null;
             }
@@ -191,7 +191,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return res;
             }
         }
@@ -209,7 +209,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return res;
             }
         }
@@ -227,7 +227,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return res;
             }
         }
@@ -248,7 +248,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 if (mustBeResultCompilationConstant) {
                     CompilerAsserts.compilationConstant(res);
                 }
@@ -272,7 +272,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                int result = (int) node.execute(constant);
+                int result = (int) node.doCast(constant);
                 CompilerAsserts.compilationConstant(result);
                 return null;
             }
@@ -293,7 +293,7 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                int result = (int) node.execute(constant);
+                int result = (int) node.doCast(constant);
                 CompilerAsserts.compilationConstant(result);
                 return null;
             }
@@ -315,8 +315,8 @@ public class TestCasts extends TestBase {
 
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
-                // return node.execute(value);
-                Object result = node.execute(constant);
+                // return node.doCast(value);
+                Object result = node.doCast(constant);
                 CompilerAsserts.compilationConstant(result);
                 return null;
             }
@@ -340,7 +340,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 @SuppressWarnings("unused")
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return null;
             }
         }
@@ -376,7 +376,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 @SuppressWarnings("unused")
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return null;
             }
         }
@@ -395,7 +395,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 @SuppressWarnings("unused")
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return null;
             }
         }
@@ -414,7 +414,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 @SuppressWarnings("unused")
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return null;
             }
         }
@@ -432,7 +432,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 @SuppressWarnings("unused")
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return null;
             }
         }
@@ -452,7 +452,7 @@ public class TestCasts extends TestBase {
             @Override
             protected Object execute(VirtualFrame frame, Object value) {
                 @SuppressWarnings("unused")
-                Object res = node.execute(value);
+                Object res = node.doCast(value);
                 return null;
             }
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
index 218c1393bd..1ae687272d 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
@@ -892,7 +892,7 @@ public class CastBuilderTest {
      */
     private Object cast(Object a) {
         CastNode.clearLastWarning();
-        NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.execute(args[0]));
+        NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.doCast(args[0]));
         return argCastNodeHandle.call(a);
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
index 3d94165a36..4214170ebf 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
@@ -327,7 +327,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
     private void testPipeline(CastNode cn, Samples<?> samples) {
         NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(cn, (node, args) -> {
-            return node.execute(args[0]);
+            return node.doCast(args[0]);
         });
 
         for (Object sample : samples.positiveSamples()) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
index bcd95f77d8..d6c7237c94 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
@@ -218,7 +218,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         PositionProfile[] positionProfiles = positionsCheckNode.executeCheck(vector, vectorDimensions, vectorLength, positions);
 
         if (castVectorNode != null) {
-            vector = (RAbstractVector) castVectorNode.execute(vector);
+            vector = (RAbstractVector) castVectorNode.doCast(vector);
         }
 
         int replacementLength = positionsCheckNode.getSelectedPositionsCount(positionProfiles);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index 44e7a6d2df..89b0358664 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -119,7 +119,7 @@ public abstract class ExtractVectorNode extends Node {
             } else if (position instanceof String) {
                 return ForeignAccess.send(foreignRead, object, new Object[]{position});
             } else if (position instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.execute(position));
+                String string = firstString.executeString(castNode.doCast(position));
                 return ForeignAccess.send(foreignRead, object, new Object[]{string});
             } else if (position instanceof RAbstractDoubleVector) {
                 return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1});
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java
index 06410a6a10..80e0e05b7b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java
@@ -108,7 +108,7 @@ abstract class PositionCastNode extends Node {
                     @Cached("create()") BoxPrimitiveNode box) {
         if (mode.isSubscript()) {
             // double gets casted to integer for subscript
-            return (RAbstractVector) box.execute(cast.execute(position));
+            return (RAbstractVector) box.execute(cast.doCast(position));
         } else {
             // because we need to perform a special bounds check with doubles
             // we cannot yet convert the double array to int for subsets
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index 03428c908e..d85926100c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -117,7 +117,7 @@ public abstract class ReplaceVectorNode extends Node {
             } else if (position instanceof String) {
                 return ForeignAccess.send(foreignRead, object, new Object[]{position, writtenValue});
             } else if (position instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.execute(position));
+                String string = firstString.executeString(castNode.doCast(position));
                 return ForeignAccess.send(foreignRead, object, new Object[]{string, writtenValue});
             } else if (position instanceof RAbstractDoubleVector) {
                 return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1, writtenValue});
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
index 4181bfc59c..65e0a251a6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java
@@ -50,7 +50,7 @@ public abstract class CastTypeNode extends RBaseNode {
     protected static Object doCast(RAbstractVector value, RType type,
                     @Cached("type") RType cachedType,
                     @Cached("createCast(cachedType)") CastNode cast) {
-        return cast.execute(value);
+        return cast.doCast(value);
     }
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index d2ed7222a4..8defc8bd28 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -28,7 +28,6 @@ import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -115,7 +114,6 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
 
     @Children private final CastNode[] argumentCasts;
     @CompilationFinal(dimensions = 1) private final Class<?>[] argumentClasses;
-    private final ValueProfile castClassProfile = ValueProfile.createClassProfile();
 
     protected RBuiltinNode(int argCount) {
         argumentCasts = getCasts();
@@ -125,7 +123,7 @@ public abstract class RBuiltinNode extends RBuiltinBaseNode implements NodeWithA
     protected Object castArg(Object[] args, int index) {
         Object value;
         if (index < argumentCasts.length && argumentCasts[index] != null) {
-            value = argumentCasts[index].execute(castClassProfile.profile(args[index]));
+            value = argumentCasts[index].doCast(args[index]);
         } else {
             value = args[index];
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
index 801f347157..be280fcfda 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RExternalBuiltinNode.java
@@ -78,7 +78,7 @@ public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements N
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castLogical = insert(CastLogicalNodeGen.create(false, false, false));
         }
-        return ((RAbstractLogicalVector) castLogical.execute(operand)).getDataAt(0);
+        return ((RAbstractLogicalVector) castLogical.doCast(operand)).getDataAt(0);
     }
 
     protected int castInt(RAbstractVector operand) {
@@ -86,7 +86,7 @@ public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements N
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castInt = insert(CastIntegerNodeGen.create(false, false, false));
         }
-        return ((RAbstractIntVector) castInt.execute(operand)).getDataAt(0);
+        return ((RAbstractIntVector) castInt.doCast(operand)).getDataAt(0);
     }
 
     protected RAbstractDoubleVector castDouble(RAbstractVector operand) {
@@ -94,7 +94,7 @@ public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements N
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castDouble = insert(CastDoubleNodeGen.create(false, false, false));
         }
-        return (RAbstractDoubleVector) castDouble.execute(operand);
+        return (RAbstractDoubleVector) castDouble.doCast(operand);
     }
 
     protected RAbstractVector castVector(Object value) {
@@ -102,7 +102,7 @@ public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements N
             CompilerDirectives.transferToInterpreterAndInvalidate();
             castVector = insert(CastToVectorNodeGen.create(false));
         }
-        return (RAbstractVector) castVector.execute(value);
+        return (RAbstractVector) castVector.doCast(value);
     }
 
     protected static String isString(Object arg) {
@@ -132,7 +132,7 @@ public abstract class RExternalBuiltinNode extends RBuiltinBaseNode implements N
     }
 
     protected Object castArg(RArgsValuesAndNames args, int index) {
-        return index < argumentCasts.length && argumentCasts[index] != null ? argumentCasts[index].execute(args.getArgument(index)) : args.getArgument(index);
+        return index < argumentCasts.length && argumentCasts[index] != null ? argumentCasts[index].doCast(args.getArgument(index)) : args.getArgument(index);
     }
 
     public abstract static class Arg0 extends RExternalBuiltinNode {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java
index 4ab161a998..362ec3b4ee 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ValueForwardingNode.java
@@ -89,6 +89,6 @@ public abstract class ValueForwardingNode extends CastNode {
 
     @Specialization
     protected Object executeOriginalPipeline(Object x, @Cached("createPipeline()") CastNode pipelineHeadNode) {
-        return pipelineHeadNode.execute(x);
+        return pipelineHeadNode.doCast(x);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
index 3f10ca646b..423574b454 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
@@ -54,7 +54,7 @@ public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 {
     @Specialization(guards = "obj.getLength() > 0")
     protected int asLogical(RAbstractAtomicVector obj,
                     @Cached("createNonPreserving()") CastLogicalNode castLogicalNode) {
-        Object castObj = castLogicalNode.execute(obj);
+        Object castObj = castLogicalNode.doCast(obj);
         if (castObj instanceof Byte) {
             return (byte) castObj;
         } else if (castObj instanceof RAbstractLogicalVector) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
index d7a8d9d574..1d4729c310 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
@@ -64,7 +64,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
     Object doCached(Object value, @SuppressWarnings("unused") int mode,
                     @Cached("mode") @SuppressWarnings("unused") int cachedMode,
                     @Cached("createCastNode(cachedMode)") CastNode castNode) {
-        return castNode.execute(value);
+        return castNode.doCast(value);
     }
 
     // Lists are coerced with only preserved names unlike other types
@@ -72,7 +72,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
     Object doCached(RList value, @SuppressWarnings("unused") int mode,
                     @Cached("mode") @SuppressWarnings("unused") int cachedMode,
                     @Cached("createCastNodeForList(cachedMode)") CastNode castNode) {
-        return castNode.execute(value);
+        return castNode.doCast(value);
     }
 
     @Fallback
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index 1c830d94f3..fd54fa745c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -234,7 +234,7 @@ abstract class S4Class extends RBaseNode {
             RFunction sExtendsForS3Function = ReadVariableNode.lookupFunction(".extendsForS3", methodsEnv.getFrame());
             // the assumption here is that the R function can only return either a String or
             // RStringVector
-            s4Extends = (RStringVector) castToVector.execute(
+            s4Extends = (RStringVector) castToVector.doCast(
                             RContext.getEngine().evalFunction(sExtendsForS3Function, methodsEnv.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), null, classAttr));
             RContext.getInstance().putS4Extends(classAttr, s4Extends);
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java
index 350638665a..6d2ca9ae16 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java
@@ -89,7 +89,7 @@ public abstract class GetS4DataSlot extends Node {
                     castToVector = insert(CastToVectorNode.create());
                 }
                 s3ClassAttrRemove.execute(obj.initAttributes());
-                setClassAttrNode.execute(obj, castToVector.execute(s3Class));
+                setClassAttrNode.execute(obj, castToVector.doCast(s3Class));
             } else {
                 setClassAttrNode.reset(obj);
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
index b4bb62f49e..bfbd4f087e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
@@ -51,9 +51,9 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 {
     protected Object doNewObject(Object classDef) {
 
         Object e = accessSlotVirtual.executeAccess(classDef, RRuntime.S_VIRTUAL);
-        if (((byte) castLogicalScalar.execute(e)) != RRuntime.LOGICAL_FALSE) {
+        if (((byte) castLogicalScalar.doCast(e)) != RRuntime.LOGICAL_FALSE) {
             e = accessSlotClassName.executeAccess(classDef, RRuntime.S_CLASSNAME);
-            throw error(RError.Message.OBJECT_FROM_VIRTUAL, castStringScalar.execute(e));
+            throw error(RError.Message.OBJECT_FROM_VIRTUAL, castStringScalar.doCast(e));
         }
         e = accessSlotClassName.executeAccess(classDef, RRuntime.S_CLASSNAME);
         Object prototype = accessSlotPrototypeName.executeAccess(classDef, RRuntime.S_PROTOTYPE);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index 1fc21b1956..5b442a98d5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
@@ -80,10 +81,12 @@ public abstract class CastListNode extends CastBaseNode {
     }
 
     @Specialization
-    protected RList doAbstractVector(RAbstractVector operand) {
-        Object[] data = new Object[operand.getLength()];
+    protected RList doAbstractVector(RAbstractVector operand,
+                    @Cached("createClassProfile()") ValueProfile vectorClassProfile) {
+        RAbstractVector profiledOperand = vectorClassProfile.profile(operand);
+        Object[] data = new Object[profiledOperand.getLength()];
         for (int i = 0; i < data.length; i++) {
-            data[i] = operand.getDataAtAsObject(i);
+            data[i] = profiledOperand.getDataAtAsObject(i);
         }
         RList ret = RDataFactory.createList(data, getPreservedDimensions(operand), getPreservedNames(operand));
         preserveDimensionNames(operand, ret);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
index a6475c8759..9e3f099560 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.casts.MessageData;
 import com.oracle.truffle.r.runtime.RError;
 
@@ -38,11 +39,17 @@ public abstract class CastNode extends UnaryNode {
     private static boolean isTesting = false;
     private static String lastWarning;
 
+    private final ValueProfile classProfile = ValueProfile.createClassProfile();
+
     public static void testingMode() {
         isTesting = true;
     }
 
-    public abstract Object execute(Object value);
+    public Object doCast(Object value) {
+        return execute(classProfile.profile(value));
+    }
+
+    protected abstract Object execute(Object value);
 
     /**
      * For testing purposes only, returns the last warning message (only when {@link #testingMode()}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
index aeec614642..d5cd4a077f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -272,6 +273,10 @@ public final class RArguments {
         return (MaterializedFrame) frame.getArguments()[INDEX_ENCLOSING_FRAME];
     }
 
+    public static ArgumentsSignature getSignature(Frame frame, ValueProfile functionProfile) {
+        return functionProfile.profile((HasSignature) getFunction(frame).getRootNode()).getSignature();
+    }
+
     public static ArgumentsSignature getSignature(Frame frame) {
         return ((HasSignature) getFunction(frame).getRootNode()).getSignature();
     }
-- 
GitLab


From 3d778473bca1f07d98720535fdf981b0d65dd826 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 12 Apr 2017 13:23:33 +0200
Subject: [PATCH 302/402] copyrights

---
 .../truffle/r/nodes/function/visibility/GetVisibilityNode.java  | 2 +-
 .../src/com/oracle/truffle/r/runtime/RArguments.java            | 2 +-
 .../src/com/oracle/truffle/r/runtime/context/ContextInfo.java   | 2 +-
 .../src/com/oracle/truffle/r/runtime/context/RContext.java      | 2 +-
 .../truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java    | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java
index 31111421b9..b59180138a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/visibility/GetVisibilityNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
index 2f7f55abe4..0240965f6f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index 84ee0da328..04862083a6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 6b6a10a5fc..b4a193b8fa 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
index c95c81051e..e7006cbd06 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From db3a771cffc9ae360609fb1b13d68464da0cf1d1 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 13 Apr 2017 09:43:34 +0200
Subject: [PATCH 303/402] synchronize on FSCM

---
 .../oracle/truffle/r/nodes/function/ArgumentStatePush.java   | 5 ++++-
 .../truffle/r/nodes/function/PostProcessArgumentsNode.java   | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
index 605d628d4f..4c9b9aa0b6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 /**
  * A {@link ArgumentStatePush} is used to bump up state transition for function arguments.
@@ -98,7 +99,9 @@ public abstract class ArgumentStatePush extends Node {
             if (writeArgMask != -1 && !FastROptions.RefCountIncrementOnly.getBooleanValue()) {
                 if (frameSlot == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(writeArgMask, FrameSlotKind.Object);
+                    synchronized (FrameSlotChangeMonitor.class) {
+                        frameSlot = frame.getFrameDescriptor().findOrAddFrameSlot(writeArgMask, FrameSlotKind.Object);
+                    }
                 }
                 frame.setObject(frameSlot, shareable);
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
index bb1d668a60..f5f59a4459 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.utilities.AssumedValue;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
 /**
@@ -73,7 +74,9 @@ public final class PostProcessArgumentsNode extends RNode {
                 if ((bits & mask) != 0) {
                     if (frameSlots[i] == null) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
-                        frameSlots[i] = frame.getFrameDescriptor().findOrAddFrameSlot(mask, FrameSlotKind.Object);
+                        synchronized (FrameSlotChangeMonitor.class) {
+                            frameSlots[i] = frame.getFrameDescriptor().findOrAddFrameSlot(mask, FrameSlotKind.Object);
+                        }
                     }
                     RShareable s;
                     try {
-- 
GitLab


From ca73eca4ccfe51cd64eef5534003109c9913ac98 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 14 Apr 2017 10:59:14 +0200
Subject: [PATCH 304/402] only read FrameSlotInfo.stableValue field once

---
 .../env/frame/FrameSlotChangeMonitor.java     | 29 +++++++++++--------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index cdb9f13b1c..8c7e60ef51 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -517,38 +517,43 @@ public final class FrameSlotChangeMonitor {
          */
 
         private void setValue(boolean value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Boolean) || ((boolean) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Boolean) || ((boolean) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(byte value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Byte) || ((byte) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Byte) || ((byte) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(int value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Integer) || ((int) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Integer) || ((int) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(double value, FrameSlot slot) {
-            if (stableValue != null && (!(stableValue.getValue() instanceof Double) || ((double) stableValue.getValue()) != value)) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && (!(sv.getValue() instanceof Double) || ((double) sv.getValue()) != value)) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
         private void setValue(Object value, FrameSlot slot) {
-            if (stableValue != null && stableValue.getValue() != value) {
-                invalidateStableValue(value, slot);
+            StableValue<Object> sv = stableValue;
+            if (sv != null && sv.getValue() != value) {
+                invalidateStableValue(sv, value, slot);
             }
         }
 
-        private void invalidateStableValue(Object value, FrameSlot slot) {
+        private void invalidateStableValue(StableValue<Object> sv, Object value, FrameSlot slot) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            stableValue.getAssumption().invalidate();
+            sv.getAssumption().invalidate();
             if (invalidationCount > 0) {
                 invalidationCount--;
                 out("setting singleton value %s = %s", slot.getIdentifier(), value == null ? "null" : value.getClass());
-- 
GitLab


From 828fe94fee439fcd8e360535c0425a1d9c329f4c Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Fri, 14 Apr 2017 15:03:17 +0200
Subject: [PATCH 305/402] disable ExactMath usages

---
 .../r/runtime/ops/BinaryArithmetic.java       | 21 +++++++++++--------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
index 1848dcc302..e3359b65ef 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
@@ -136,13 +136,14 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public int op(int left, int right) {
-            try {
-                return ExactMath.addExact(left, right);
-            } catch (ArithmeticException e) {
+            int r = left + right;
+            // TODO: not using ExactMath because of perf problems
+            if (((left ^ r) & (right ^ r)) < 0) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 replace(new AddOverflow());
                 return INT_NA;
             }
+            return r;
         }
 
         @Override
@@ -193,13 +194,14 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public int op(int left, int right) {
-            try {
-                return ExactMath.subtractExact(left, right);
-            } catch (ArithmeticException e) {
+            int r = left - right;
+            // TODO: not using ExactMath because of perf problems
+            if (((left ^ right) & (left ^ r)) < 0) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 replace(new SubtractOverflow());
                 return INT_NA;
             }
+            return r;
         }
 
         @Override
@@ -249,13 +251,14 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public int op(int left, int right) {
-            try {
-                return ExactMath.multiplyExact(left, right);
-            } catch (ArithmeticException e) {
+            long r = (long) left * (long) right;
+            // TODO: not using ExactMath because of perf problems
+            if ((int) r != r) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 replace(new MultiplyOverflow());
                 return INT_NA;
             }
+            return (int) r;
         }
 
         @Override
-- 
GitLab


From 7278062bf5d4e56f2847ac5f5c126b6f9918e8fe Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 18 Apr 2017 16:11:26 +0200
Subject: [PATCH 306/402] FastR Grid: initial support for window resizing

---
 .../r/library/fastrGrid/GridContext.java      |  5 +-
 .../r/library/fastrGrid/WindowDevice.java     | 45 +++++++++++++++
 .../device/awt/Graphics2DDevice.java          | 22 ++++++--
 .../fastrGrid/device/awt/JFrameDevice.java    | 56 ++++++++++++++++++-
 .../truffle/r/library/fastrGrid/fastrGrid.R   |  5 ++
 .../grDevices/InitWindowedDevice.java         |  5 +-
 6 files changed, 125 insertions(+), 13 deletions(-)
 create mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 10f8a4d797..799af373a1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -27,8 +27,6 @@ import java.util.ArrayList;
 import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
-import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
-import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
@@ -89,8 +87,7 @@ public final class GridContext {
     public void openDefaultDevice() {
         String defaultDev = RGridGraphicsAdapter.getDefaultDevice();
         if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) {
-            BufferedJFrameDevice result = new BufferedJFrameDevice(JFrameDevice.create(GridDevice.DEFAULT_WIDTH, GridDevice.DEFAULT_HEIGHT));
-            setCurrentDevice(defaultDev, result);
+            setCurrentDevice(defaultDev, WindowDevice.createWindowDevice());
         } else {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'.");
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
new file mode 100644
index 0000000000..4ae0265a38
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
+
+/**
+ * Contains code specific to FastR device that shows the graphical output interactively in a window.
+ */
+public final class WindowDevice {
+    private WindowDevice() {
+        // only static members
+    }
+
+    public static GridDevice createWindowDevice() {
+        return createWindowDevice(GridDevice.DEFAULT_WIDTH, GridDevice.DEFAULT_HEIGHT);
+    }
+
+    public static GridDevice createWindowDevice(int width, int height) {
+        JFrameDevice frameDevice = JFrameDevice.create(width, height);
+        return new BufferedJFrameDevice(frameDevice);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
index a99d30e2d1..90bf1adc20 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
@@ -91,7 +91,7 @@ public class Graphics2DDevice implements GridDevice {
 
     @Override
     public void openNewPage() {
-        graphics.clearRect(0, 0, width, height);
+        graphics.clearRect(0, 0, getWidthAwt(), getHeightAwt());
     }
 
     @Override
@@ -142,12 +142,12 @@ public class Graphics2DDevice implements GridDevice {
 
     @Override
     public double getWidth() {
-        return width / AWT_POINTS_IN_INCH;
+        return getWidthAwt() / AWT_POINTS_IN_INCH;
     }
 
     @Override
     public double getHeight() {
-        return height / AWT_POINTS_IN_INCH;
+        return getHeightAwt() / AWT_POINTS_IN_INCH;
     }
 
     @Override
@@ -165,6 +165,20 @@ public class Graphics2DDevice implements GridDevice {
         return swingUnits / AWT_POINTS_IN_INCH;
     }
 
+    /**
+     * Allows to override the default fixed width behavior with dynamically computed width.
+     */
+    int getWidthAwt() {
+        return width;
+    }
+
+    /**
+     * Allows to override the default fixed height behavior with dynamically computed height.
+     */
+    int getHeightAwt() {
+        return height;
+    }
+
     void setGraphics2D(Graphics2D newGraphics) {
         assert newGraphics != null;
         graphics = newGraphics;
@@ -175,7 +189,7 @@ public class Graphics2DDevice implements GridDevice {
     }
 
     private int transY(double y) {
-        return height - (int) (y * AWT_POINTS_IN_INCH);
+        return getHeightAwt() - (int) (y * AWT_POINTS_IN_INCH);
     }
 
     private static int transX(double x) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
index 7571ced32f..b9faaaa9ff 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
@@ -27,8 +27,12 @@ import java.awt.Dimension;
 import java.awt.Graphics2D;
 import java.awt.HeadlessException;
 import java.awt.Toolkit;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
+import java.util.Timer;
+import java.util.TimerTask;
 
 import javax.swing.JFrame;
 import javax.swing.JPanel;
@@ -37,6 +41,7 @@ public final class JFrameDevice extends Graphics2DDevice {
 
     private final JFrame currentFrame;
     private final boolean disposeResources;
+    private Runnable onResize;
 
     /**
      * @param frame The frame that should be used for drawing.
@@ -49,6 +54,9 @@ public final class JFrameDevice extends Graphics2DDevice {
         super(graphics, frame.getContentPane().getWidth(), frame.getContentPane().getHeight(), true);
         currentFrame = frame;
         this.disposeResources = disposeResources;
+        if (currentFrame instanceof FastRFrame) {
+            ((FastRFrame) currentFrame).device = this;
+        }
     }
 
     /**
@@ -72,6 +80,20 @@ public final class JFrameDevice extends Graphics2DDevice {
         }
     }
 
+    @Override
+    int getWidthAwt() {
+        return currentFrame.getContentPane().getWidth();
+    }
+
+    @Override
+    int getHeightAwt() {
+        return currentFrame.getContentPane().getHeight();
+    }
+
+    public void setResizeListener(Runnable onResize) {
+        this.onResize = onResize;
+    }
+
     JFrame getCurrentFrame() {
         return currentFrame;
     }
@@ -79,12 +101,20 @@ public final class JFrameDevice extends Graphics2DDevice {
     static class FastRFrame extends JFrame {
         private static final long serialVersionUID = 1L;
         private final JPanel fastRComponent = new JPanel();
+        private JFrameDevice device;
+
+        volatile boolean resizeScheduled = false;
+        private int oldWidth;
+        private int oldHeight;
+        private final Timer timer = new Timer();
 
         FastRFrame(int width, int height) throws HeadlessException {
             super("FastR");
-            addCloseListener();
+            addListeners();
             createUI(width, height);
             center();
+            oldWidth = width;
+            oldHeight = height;
         }
 
         private void createUI(int width, int height) {
@@ -94,13 +124,35 @@ public final class JFrameDevice extends Graphics2DDevice {
             fastRComponent.setPreferredSize(getSize());
         }
 
-        private void addCloseListener() {
+        private void addListeners() {
             addWindowFocusListener(new WindowAdapter() {
                 @Override
                 public void windowClosing(WindowEvent e) {
                     dispose();
                 }
             });
+            addComponentListener(new ComponentAdapter() {
+                @Override
+                public void componentResized(ComponentEvent e) {
+                    if (oldHeight == getHeight() && oldWidth == getWidth()) {
+                        return;
+                    }
+                    if (!resizeScheduled) {
+                        resizeScheduled = true;
+                        timer.schedule(new TimerTask() {
+                            @Override
+                            public void run() {
+                                oldWidth = getWidth();
+                                oldHeight = getHeight();
+                                resizeScheduled = false;
+                                if (device.onResize != null) {
+                                    device.onResize.run();
+                                }
+                            }
+                        }, 1000);
+                    }
+                }
+            });
         }
 
         private void center() {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
index d799ca533c..068c5fb4f5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/fastrGrid.R
@@ -15,6 +15,11 @@
 # logic to R. Some functions implement whole externals, like L_downvppath, some implement coherent
 # parts of the logic and the rest is in Java.
 
+# Used by the interactive device to redraw the whole scene if the window gets resized.
+redrawAll <- function() {
+    popViewport(0, recording = FALSE)
+    grid:::draw.all()
+}
 
 # chull from grDevices package is used in EdgeDetection.java
 # Note: chull calls to native function, which we may consider
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 52fe6b7900..1fdc13be74 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -28,12 +28,11 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
+import com.oracle.truffle.r.library.fastrGrid.WindowDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException;
-import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.Graphics2DDevice;
-import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -84,7 +83,7 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
         }
 
         // otherwise create the window ourselves
-        BufferedJFrameDevice device = new BufferedJFrameDevice(JFrameDevice.create(width, height));
+        GridDevice device = WindowDevice.createWindowDevice(width, height);
         String name = isFastRDevice ? "awt" : "X11cairo";
         GridContext.getContext().setCurrentDevice(name, device);
         return RNull.instance;
-- 
GitLab


From 41c77839068f87f2af17a23d89834d29937d9e11 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 18 Apr 2017 14:23:50 -0700
Subject: [PATCH 307/402] Truffle_NFI: move call back indices to seperate
 header file

---
 .../fficall/src/truffle_nfi/Makefile          |   2 +-
 .../fficall/src/truffle_nfi/rffi_callbacks.h  | 130 +-------------
 .../src/truffle_nfi/rffi_callbacksindex.h     | 160 ++++++++++++++++++
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java |   1 +
 4 files changed, 163 insertions(+), 130 deletions(-)
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h

diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
index ce8e60537b..8c9fb1057c 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
@@ -52,7 +52,7 @@ $(C_OBJECTS): | $(OBJ)
 $(OBJ):
 	mkdir -p $(OBJ)
 
-$(OBJ)/%.o: %.c $(TOPDIR)/include/Rinternals.h $(C_HDRS)
+$(OBJ)/%.o: %.c $(TOPDIR)/include/Rinternals.h rffi_callbacksindex.h $(C_HDRS)
 	$(CC) $(CFLAGS) $(INCLUDES) -I../variable_defs -c $< -o $@
 
 # for debugging, to see what's really being compiled
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
index d4e0e017db..a03e58c1c2 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
@@ -23,138 +23,10 @@
 #ifndef CALLBACKS_H
 #define CALLBACKS_H
 
-#define CADDR_x 0
-#define CADR_x 1
-#define CAR_x 2
-#define CDDR_x 3
-#define CDR_x 4
-#define DUPLICATE_ATTRIB_x 5
-#define ENCLOS_x 6
-#define GetRNGstate_x 7
-#define INTEGER_x 8
-#define IS_S4_OBJECT_x 9
-#define LENGTH_x 10
-#define LOGICAL_x 11
-#define NAMED_x 12
-#define OBJECT_x 13
-#define PRCODE_x 14
-#define PRENV_x 15
-#define PRINTNAME_x 16
-#define PRSEEN_x 17
-#define PRVALUE_x 18
-#define PutRNGstate_x 19
-#define RAW_x 20
-#define RDEBUG_x 21
-#define REAL_x 22
-#define RSTEP_x 23
-#define R_BaseEnv_x 24
-#define R_BaseNamespace_x 25
-#define R_BindingIsLocked_x 26
-#define R_CHAR_x 27
-#define R_CleanUp_x 28
-#define R_ExternalPtrAddr_x 29
-#define R_ExternalPtrProt_x 30
-#define R_ExternalPtrTag_x 31
-#define R_FindNamespace_x 32
-#define R_GetConnection_x 33
-#define R_GlobalContext_x 34
-#define R_GlobalEnv_x 35
-#define R_HomeDir_x 36
-#define R_Interactive_x 37
-#define R_MakeExternalPtr_x 38
-#define R_NamespaceRegistry_x 39
-#define R_NewHashedEnv_x 40
-#define R_ParseVector_x 41
-#define R_PromiseExpr_x 42
-#define R_ReadConnection_x 43
-#define R_SetExternalPtrAddr_x 44
-#define R_SetExternalPtrProt_x 45
-#define R_SetExternalPtrTag_x 46
-#define R_ToplevelExec_x 47
-#define R_WriteConnection_x 48
-#define R_computeIdentical_x 49
-#define R_do_MAKE_CLASS_x 50
-#define R_getContextCall_x 51
-#define R_getContextEnv_x 52
-#define R_getContextFun_x 53
-#define R_getContextSrcRef_x 54
-#define R_getGlobalFunctionContext_x 55
-#define R_getParentFunctionContext_x 56
-#define R_insideBrowser_x 57
-#define R_isEqual_x 58
-#define R_isGlobal_x 59
-#define R_lsInternal3_x 60
-#define R_new_custom_connection_x 61
-#define R_tryEval_x 62
-#define Rf_GetOption1_x 63
-#define Rf_PairToVectorList_x 64
-#define Rf_ScalarDouble_x 65
-#define Rf_ScalarInteger_x 66
-#define Rf_ScalarLogical_x 67
-#define Rf_ScalarString_x 68
-#define Rf_allocateArray_x 69
-#define Rf_allocateMatrix_x 70
-#define Rf_allocateVector_x 71
-#define Rf_anyDuplicated_x 72
-#define Rf_asChar_x 73
-#define Rf_asInteger_x 74
-#define Rf_asLogical_x 75
-#define Rf_asReal_x 76
-#define Rf_classgets_x 77
-#define Rf_coerceVector_x 78
-#define Rf_cons_x 79
-#define Rf_copyListMatrix_x 80
-#define Rf_copyMatrix_x 81
-#define Rf_defineVar_x 82
-#define Rf_duplicate_x 83
-#define Rf_error_x 84
-#define Rf_eval_x 85
-#define Rf_findVar_x 86
-#define Rf_findVarInFrame_x 87
-#define Rf_findVarInFrame3_x 88
-#define Rf_findfun_x 89
-#define Rf_getAttrib_x 90
-#define Rf_gsetVar_x 91
-#define Rf_inherits_x 92
-#define Rf_install_x 93
-#define Rf_installChar_x 94
-#define Rf_isNull_x 95
-#define Rf_isString_x 96
-#define Rf_lengthgets_x 97
-#define Rf_mkCharLenCE_x 98
-#define Rf_ncols_x 99
-#define Rf_nrows_x 100
-#define Rf_setAttrib_x 101
-#define Rf_warning_x 102
-#define Rf_warningcall_x 103
-#define Rprintf_x 104
-#define SETCADR_x 105
-#define SETCAR_x 106
-#define SETCDR_x 107
-#define SET_RDEBUG_x 108
-#define SET_RSTEP_x 109
-#define SET_STRING_ELT_x 110
-#define SET_SYMVALUE_x 111
-#define SET_TAG_x 112
-#define SET_TYPEOF_FASTR_x 113
-#define SET_VECTOR_ELT_x 114
-#define STRING_ELT_x 115
-#define SYMVALUE_x 116
-#define TAG_x 117
-#define TYPEOF_x 118
-#define VECTOR_ELT_x 119
-#define getConnectionClassString_x 120
-#define getOpenModeString_x 121
-#define getSummaryDescription_x 122
-#define isSeekable_x 123
-#define unif_rand_x 124
-
-#define CALLBACK_TABLE_SIZE 125
+#include "rffi_callbacksindex.h"
 
 extern void* callbacks[];
 
-// TODO Use an array indexed by above
-
 // This is the complete set , including those not yet implemented
 
 typedef SEXP (*call_Rf_ScalarInteger)(int value);
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
new file mode 100644
index 0000000000..3fcb214834
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// TODO This file should be generated automatically from RFFIUpCallMethod.main
+
+#ifndef CALLBACKSINDEX_H
+#define CALLBACKSINDEX_H
+
+#define CADDR_x 0
+#define CADR_x 1
+#define CAR_x 2
+#define CDDR_x 3
+#define CDR_x 4
+#define DUPLICATE_ATTRIB_x 5
+#define ENCLOS_x 6
+#define GetRNGstate_x 7
+#define INTEGER_x 8
+#define IS_S4_OBJECT_x 9
+#define LENGTH_x 10
+#define LOGICAL_x 11
+#define NAMED_x 12
+#define OBJECT_x 13
+#define PRCODE_x 14
+#define PRENV_x 15
+#define PRINTNAME_x 16
+#define PRSEEN_x 17
+#define PRVALUE_x 18
+#define PutRNGstate_x 19
+#define RAW_x 20
+#define RDEBUG_x 21
+#define REAL_x 22
+#define RSTEP_x 23
+#define R_BaseEnv_x 24
+#define R_BaseNamespace_x 25
+#define R_BindingIsLocked_x 26
+#define R_CHAR_x 27
+#define R_CleanUp_x 28
+#define R_ExternalPtrAddr_x 29
+#define R_ExternalPtrProt_x 30
+#define R_ExternalPtrTag_x 31
+#define R_FindNamespace_x 32
+#define R_GetConnection_x 33
+#define R_GlobalContext_x 34
+#define R_GlobalEnv_x 35
+#define R_HomeDir_x 36
+#define R_Interactive_x 37
+#define R_MakeExternalPtr_x 38
+#define R_NamespaceRegistry_x 39
+#define R_NewHashedEnv_x 40
+#define R_ParseVector_x 41
+#define R_PromiseExpr_x 42
+#define R_ReadConnection_x 43
+#define R_SetExternalPtrAddr_x 44
+#define R_SetExternalPtrProt_x 45
+#define R_SetExternalPtrTag_x 46
+#define R_ToplevelExec_x 47
+#define R_WriteConnection_x 48
+#define R_computeIdentical_x 49
+#define R_do_MAKE_CLASS_x 50
+#define R_do_new_object_x 51
+#define R_do_slot_x 52
+#define R_do_slot_assign_x 53
+#define R_getContextCall_x 54
+#define R_getContextEnv_x 55
+#define R_getContextFun_x 56
+#define R_getContextSrcRef_x 57
+#define R_getGlobalFunctionContext_x 58
+#define R_getParentFunctionContext_x 59
+#define R_insideBrowser_x 60
+#define R_isEqual_x 61
+#define R_isGlobal_x 62
+#define R_lsInternal3_x 63
+#define R_new_custom_connection_x 64
+#define R_tryEval_x 65
+#define Rf_GetOption1_x 66
+#define Rf_PairToVectorList_x 67
+#define Rf_ScalarDouble_x 68
+#define Rf_ScalarInteger_x 69
+#define Rf_ScalarLogical_x 70
+#define Rf_ScalarString_x 71
+#define Rf_allocateArray_x 72
+#define Rf_allocateMatrix_x 73
+#define Rf_allocateVector_x 74
+#define Rf_anyDuplicated_x 75
+#define Rf_asChar_x 76
+#define Rf_asInteger_x 77
+#define Rf_asLogical_x 78
+#define Rf_asReal_x 79
+#define Rf_classgets_x 80
+#define Rf_coerceVector_x 81
+#define Rf_cons_x 82
+#define Rf_copyListMatrix_x 83
+#define Rf_copyMatrix_x 84
+#define Rf_defineVar_x 85
+#define Rf_duplicate_x 86
+#define Rf_error_x 87
+#define Rf_eval_x 88
+#define Rf_findVar_x 89
+#define Rf_findVarInFrame_x 90
+#define Rf_findVarInFrame3_x 91
+#define Rf_findfun_x 92
+#define Rf_getAttrib_x 93
+#define Rf_gsetVar_x 94
+#define Rf_inherits_x 95
+#define Rf_install_x 96
+#define Rf_installChar_x 97
+#define Rf_isNull_x 98
+#define Rf_isString_x 99
+#define Rf_lengthgets_x 100
+#define Rf_mkCharLenCE_x 101
+#define Rf_ncols_x 102
+#define Rf_nrows_x 103
+#define Rf_setAttrib_x 104
+#define Rf_warning_x 105
+#define Rf_warningcall_x 106
+#define Rprintf_x 107
+#define SETCADR_x 108
+#define SETCAR_x 109
+#define SETCDR_x 110
+#define SET_RDEBUG_x 111
+#define SET_RSTEP_x 112
+#define SET_STRING_ELT_x 113
+#define SET_SYMVALUE_x 114
+#define SET_TAG_x 115
+#define SET_TYPEOF_FASTR_x 116
+#define SET_VECTOR_ELT_x 117
+#define STRING_ELT_x 118
+#define SYMVALUE_x 119
+#define TAG_x 120
+#define TYPEOF_x 121
+#define VECTOR_ELT_x 122
+#define getConnectionClassString_x 123
+#define getOpenModeString_x 124
+#define getSummaryDescription_x 125
+#define isSeekable_x 126
+#define unif_rand_x 127
+
+#define CALLBACK_TABLE_SIZE 128
+
+#endif // CALLBACKSINDEX_H
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index f3a19b0033..1b38154133 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -172,6 +172,7 @@ public enum RFFIUpCallMethod {
         for (RFFIUpCallMethod f : RFFIUpCallMethod.values()) {
             System.out.printf("#define %s_x %d\n", f.name(), f.ordinal());
         }
+        System.out.printf("\n#define CALLBACK_TABLE_SIZE %d\n", RFFIUpCallMethod.values().length);
     }
 
 }
-- 
GitLab


From 2d5f8d3547b46b920353b34a84a201b869fd01d0 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 18 Apr 2017 16:24:10 -0700
Subject: [PATCH 308/402] make RConnection a TruffleObject for C_ParseRd in
 NFI/LLVM

---
 .../r/engine/interop/RConnectionMR.java       | 42 +++++++++++++++++++
 .../interop/RForeignAccessFactoryImpl.java    |  3 ++
 .../truffle/r/runtime/conn/RConnection.java   |  3 +-
 3 files changed, 47 insertions(+), 1 deletion(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java
new file mode 100644
index 0000000000..45df6f9f19
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.conn.RConnection;
+
+@MessageResolution(receiverType = RConnection.class, language = TruffleRLanguage.class)
+public class RConnectionMR {
+    @CanResolve
+    public abstract static class RConnection extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RConnection;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 0c91b000ba..428399f41f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RForeignAccessFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
@@ -92,6 +93,8 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RDoubleMRForeign.ACCESS;
         } else if (obj instanceof CharSXPWrapper) {
             return CharSXPWrapperMRForeign.ACCESS;
+        } else if (obj instanceof RConnection) {
+            return RConnectionMRForeign.ACCESS;
         } else {
             if (obj instanceof RAbstractVector) {
                 return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index 1314faf885..df7d420c8b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -31,12 +31,13 @@ import java.nio.channels.ByteChannel;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 /**
  * Denotes an R {@code connection} instance used in the {@code base} I/O library.
  */
-public interface RConnection extends AutoCloseable {
+public interface RConnection extends AutoCloseable, RTruffleObject {
 
     static BaseRConnection fromIndex(int con) {
         return RContext.getInstance().stateRConnection.getConnection(con, true);
-- 
GitLab


From 0fef081529239baddce4a35d79816ca03d02ae76 Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Thu, 6 Apr 2017 18:31:57 +0200
Subject: [PATCH 309/402] GraalVM package created

---
 com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION |  12 +
 com.oracle.truffle.r.pkgs/graalvm/NAMESPACE   |  17 +
 com.oracle.truffle.r.pkgs/graalvm/R/g.R       | 337 ++++++++++++++++++
 com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R |  53 +++
 .../graalvm/data/handler.fr                   |  44 +++
 .../graalvm/data/handler.rb                   |  37 ++
 .../graalvm/data/server.js                    | 196 ++++++++++
 com.oracle.truffle.r.pkgs/graalvm/man/g.Rd    |  32 ++
 com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd |  18 +
 com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd  |  18 +
 com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd |  18 +
 com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd |  19 +
 .../graalvm/man/gget.js.Rd                    |  17 +
 .../graalvm/man/gget.r.Rd                     |  17 +
 .../graalvm/man/gget.rb.Rd                    |  17 +
 .../graalvm/man/graalvm.Rd                    |  59 +++
 .../graalvm/man/graalvm.setup.Rd              |  25 ++
 .../graalvm/man/graalvm.start.Rd              |  13 +
 .../graalvm/man/graalvm.stop.Rd               |  11 +
 com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd |  35 ++
 .../graalvm/man/gset.js.Rd                    |  17 +
 .../graalvm/man/gset.r.Rd                     |  17 +
 .../graalvm/man/gset.rb.Rd                    |  17 +
 23 files changed, 1046 insertions(+)
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/NAMESPACE
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/R/g.R
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/data/handler.fr
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/data/handler.rb
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/data/server.js
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/g.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd
 create mode 100644 com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd

diff --git a/com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION b/com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION
new file mode 100644
index 0000000000..895818a9a3
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/DESCRIPTION
@@ -0,0 +1,12 @@
+Package: graalvm
+Type: Package
+Title: GraalVM integration with GNUR
+Version: 1.0
+Date: 2017-04-06
+Author: Zbynek Slajchrt
+Maintainer: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
+Copyright: Oracle
+Description: It demonstrates FastR performance and polyglot capabilities of GraalVM to GNUR users.
+License: GPL-2
+Depends: curl, jsonlite
+RoxygenNote: 6.0.1
diff --git a/com.oracle.truffle.r.pkgs/graalvm/NAMESPACE b/com.oracle.truffle.r.pkgs/graalvm/NAMESPACE
new file mode 100644
index 0000000000..ce77a622a1
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/NAMESPACE
@@ -0,0 +1,17 @@
+# Generated by roxygen2: do not edit by hand
+
+export(g)
+export(g.js)
+export(g.r)
+export(g.rb)
+export(gget)
+export(gget.js)
+export(gget.r)
+export(gget.rb)
+export(graalvm.setup)
+export(graalvm.start)
+export(graalvm.stop)
+export(gset)
+export(gset.js)
+export(gset.r)
+export(gset.rb)
diff --git a/com.oracle.truffle.r.pkgs/graalvm/R/g.R b/com.oracle.truffle.r.pkgs/graalvm/R/g.R
new file mode 100644
index 0000000000..11190d265a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/R/g.R
@@ -0,0 +1,337 @@
+##
+ # Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ #
+ # This code is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License version 2 only, as
+ # published by the Free Software Foundation.
+ #
+ # This code is distributed in the hope that it will be useful, but WITHOUT
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ # version 2 for more details (a copy is included in the LICENSE file that
+ # accompanied this code).
+ #
+ # You should have received a copy of the GNU General Public License version
+ # 2 along with this work; if not, write to the Free Software Foundation,
+ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ #
+ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ # or visit www.oracle.com if you need additional information or have any
+ # questions.
+##
+
+graalvmEnv <- new.env(parent = emptyenv())
+graalvmEnv$status <- FALSE
+
+graalvm.status <- function() {
+	graalvmEnv$status
+}
+
+#' Set up the GraalVM agent
+#'
+#' @param home The home folder of the GraalVM installation
+#' @param host The local host name at which the GraalVM agent is listening
+#' @param port The port at which the GraalVM agent is listening
+#' @param rlibs The value of the FastR R_LIBS environmental variable. The default 
+#' value is calculated as paste0(graalvm.home, "/language/R/library").
+#' @examples
+#' graalvm.setup("~/work/graalvm-0.21")
+#' @export
+graalvm.setup <- function(home, host = "localhost", port = 9876, rlibs = paste0(home, "/language/R/library")) {
+	options(graalvm.home = home, graalvm.host = host, graalvm.port = port, graalvm.rlibs = rlibs)
+}
+
+commandURL <- function(cmd) {
+	gHost <- getOption("graalvm.host");
+	gPort <- getOption("graalvm.port");
+	sprintf("http://%s:%d/%s", gHost, gPort, cmd)
+}
+
+ping <- function() {
+	pingURL <- commandURL("ping")
+	tryCatch({ suppressWarnings(readLines(pingURL, warn=FALSE)); TRUE }, error = function(e) FALSE)
+}
+
+#' Start the GraalVM agent. The agent is normally started automatically upon the first
+#' code ecxecution.
+#' @export
+graalvm.start <- function() {
+	if (!ping()) {
+		graalvmEnv$status <- FALSE
+		gHome <- getOption("graalvm.home");
+		if (is.null(gHome)) stop("No GraalVM home configured. Use graalvm.setup() to specify it.")
+
+		serverScriptPath <- attr(packageDescription("graalvm"), "file")
+		serverScriptPath <-	substr(serverScriptPath, 1, nchar(serverScriptPath)-16)
+		serverScriptPath <- paste0(serverScriptPath, "data/server.js")
+	
+		libEnvVar <- paste0("R_LIBS=", getOption("graalvm.rlibs"))
+	
+		gHost <- getOption("graalvm.host");
+		gPort <- getOption("graalvm.port");
+	
+		nodeLaunchCmd <- paste0(libEnvVar, " ", gHome, "/bin/node ", serverScriptPath, " ", gHost, " ", gPort, " &")
+		system(nodeLaunchCmd, ignore.stdout = TRUE, ignore.stderr = TRUE)
+	
+		attempts <- 0L
+		while(!ping()) {
+			Sys.sleep(1)
+			attempts <- attempts + 1L
+			if (attempts >= 30) stop("Cannot launch GraalVM agent")
+		}
+
+		graalvmEnv$status <- TRUE
+	} 
+	
+	# register the function stopping the agent on exit
+	prevLast <- NULL
+	if (exists(".Last")) {
+		prevLast <- .Last
+	}
+	.Last <<- function() {
+		tryCatch(graalvm::graalvm.stop(), error = function(e) print(e))
+		# invoke the previous callback if any
+		if (!is.null(prevLast)) prevLast()
+	}
+	TRUE
+}
+
+#' Stop the GraalVM agent.
+#' @export
+graalvm.stop <- function() {
+	tryCatch({ 
+		suppressWarnings(readLines(commandURL("stop"), warn=FALSE))
+		graalvmEnv$status <- FALSE
+		TRUE
+	}, error = function(e) FALSE)
+}
+
+#' Execute code by GraalVM using the language interpreter that corresponds
+#' to the language mimetype.
+#'
+#' @param code the code to be executed. It must be a language element as long as the target
+#' language is R, otherwise it must be a string.
+#' @param echo controls whether this function returns the result of the interpreted code.
+#' The default value is TRUE.
+#' @param mimetype The mimetype of the target language. Currently supported values are
+#' "application/x-r", "text/javascript" and "application/x-ruby".
+#' @family execution functions
+#' @examples
+#' g(runif(10^3))
+#' g(runif(10^8), echo = FALSE) # We do not want that the result is returned due to its size
+#' g("1 < 2", mimetype = "text/javascript")
+#' @export
+g <- function(code, echo = TRUE, mimetype = "application/x-r") {
+	if (mimetype == "application/x-r") {
+		code <- deparse(substitute(code))
+	} else {
+		if (!is.character(code)) stop("The code argument must a character vector")
+	}
+	send(code, echo, mimetype)
+}
+
+#' Execute R code.
+#' @examples
+#' g.r("runif(10^3)")
+#' @family execution functions
+#' @export
+g.r <- function(code, echo = TRUE) {
+	if (!is.character(code)) stop("The code argument must a character vector")
+	send(code, echo, "application/x-r")
+}
+
+#' Execute JavaScript code.
+#' @examples
+#' g.js("1 < 2")
+#' @family execution functions
+#' @export
+g.js <- function(code, echo = TRUE) {
+	if (!is.character(code)) stop("The code argument must a character vector")
+	send(code, echo, "text/javascript")
+}
+
+#' Execute Ruby code.
+#' @examples
+#' g.rb("1 < 2")
+#' @family execution functions
+#' @export
+g.rb <- function(code, echo = TRUE) {
+	if (!is.character(code)) stop("The code argument must a character vector")
+	send(code, echo, "application/x-ruby")
+}
+
+#' Assign a value to a paired variable. The value is assigned both locally and remotely.
+#' The local variable must have been initialized by one of the language specific gget.* or
+#' ggset.* functions.
+#' 
+#' @family paired variables
+#' @examples
+#' # Create and initialize a variable in JS
+#' g.js("a = 1")
+#' # Pick up the a variable from JS and define its counterpart in GNUR
+#' gget.js(a)
+#' a
+#' # Increment the variable both locally and in JS 
+#' gset(a, a + 1)
+#' a
+#' g.js("a[0]")
+#' g.js("a[1] = 10")
+#' gget(a)
+#' a
+#' @export
+gset <- function(var, value = var) {
+	varName <- deparse(substitute(var))
+	if (exists(varName)) {
+		meta <- attr(var, "graalvm")
+		if (is.null(meta)) {
+			stop(paste("Unpaired variable ", varName))
+		}
+		deparsedValue = NULL
+		if (meta$mimetype == "application/x-r") {
+			deparsedValue <- paste(deparse(substitute(value)), collapse="\n")
+		}
+		setVar(varName, value, deparsedValue, meta$mimetype)
+	} else {
+		stop(paste("Undefined variable ", varName))
+	}
+}
+
+#' Assign the value to the paired variable in Graal FastR and locally.
+#'
+#' @family paired variables
+#' @export
+gset.r <- function(var, value) setVar(deparse(substitute(var)), value, paste(deparse(substitute(value)), collapse="\n"), "application/x-r")
+
+#' Assign the value to the paired variable in Graal JS and locally.
+#'
+#' @family paired variables
+#' @export
+gset.js <- function(var, value) setVar(deparse(substitute(var)), value, NULL, "text/javascript")
+
+#' Assign the value to the paired variable in Graal Ruby and locally.
+#'
+#' @family paired variables
+#' @export
+gset.rb <- function(var, value) setVar(deparse(substitute(var)), value, NULL, "application/x-ruby")
+
+#' Retrieve the variable defined in a GraalVM language. The local variable must have been 
+#' initialized by one of the language specific gget.* or ggset.* functions.
+#' 
+#' @family paired variables
+#' @export
+gget <- function(var) {
+	varName <- deparse(substitute(var))
+	if (exists(varName)) {
+		meta <- attr(var, "graalvm")
+		if (is.null(meta)) {
+			stop(paste("Unpaired variable ", varName))
+		}
+		getVar(varName, meta$mimetype) 
+	} else {
+		stop(paste("Undefined variable ", varName))
+	}
+}
+
+#' Retrieve the variable defined in GraalVM FastR.
+#'
+#' @family paired variables
+#' @export
+gget.r <- function(var) getVar(deparse(substitute(var)), "application/x-r")
+
+#' Retrieve the variable defined in GraalVM JS.
+#'
+#' @family paired variables
+#' @export
+gget.js <- function(var) getVar(deparse(substitute(var)), "text/javascript")
+
+#' Retrieve the variable defined in GraalVM Ruby.
+#'
+#' @family paired variables
+#' @export
+gget.rb <- function(var) getVar(deparse(substitute(var)), "application/x-ruby")
+
+setVar <- function(varName, value, deparsedValue, mimetype="application/x-r") {
+	localValue <- value
+	meta <- NULL
+	if (exists(varName)) {
+		meta <- attr(var, "graalvm")
+	} 
+	if (is.null(meta)) {
+		meta <- list(varName = varName, mimetype = mimetype)
+		attr(localValue, "graalvm") <- meta
+	}
+	if (meta$mimetype == "application/x-r") {
+		code <- paste0(meta$varName, "<-", deparsedValue) 
+	} else if (meta$mimetype == "text/javascript") {
+		code <- paste0(meta$varName, "=", toJSON(value)) 
+	} else if (meta$mimetype == "application/x-ruby") {
+		code <- paste0("$", meta$varName, "=", toJSON(value))
+	} else {
+		stop(paste("Unsupported language mimetype:", mimetype))
+	}
+	send(code, FALSE, meta$mimetype)
+	
+	assign(varName, localValue, inherits = TRUE)
+}
+
+getVar <- function(varName, mimetype="application/x-r") {
+	meta <- NULL
+	if (exists(varName)) {
+		meta <- attr(var, "graalvm")
+	} 
+	if (is.null(meta)) {
+		meta <- list(varName = varName, mimetype = mimetype)
+	}
+	if (meta$mimetype == "application/x-r") {
+		code <- meta$varName 
+	} else if (meta$mimetype == "text/javascript") {
+		code <- meta$varName 
+	} else if (meta$mimetype == "application/x-ruby") {
+		code <- paste0("$", meta$varName)
+	} else {
+		stop(paste("Unsupported language mimetype:", mimetype))
+	}
+	value <- send(code, TRUE, meta$mimetype)
+	
+	if (!is.null(value)) {
+		meta <- list("varName" = varName, "mimetype" = mimetype)
+		attr(value, "graalvm") <- meta
+	}
+	
+	assign(varName, value, inherits = TRUE)
+}
+
+send <- function(code, echo, mimetype) {
+	tryCatch(sendAttempt(code, echo, mimetype), error = function(e) {
+		# try to restart the agent and invoke it agains
+		graalvm.start()
+		sendAttempt(code, echo, mimetype)
+	})	
+}
+
+sendAttempt <- function(code, echo, mimetype) {
+	code <- paste(code, collapse="\n")
+	if (!graalvmEnv$status) {
+		graalvm.start()
+	}
+	h <- new_handle(failonerror = FALSE)
+	handle_setform(h, code=code, echo=as.character(echo), mimetype=mimetype)
+	url <- commandURL("")
+	resp <- curl_fetch_memory(url, handle = h)
+	respData <- rawToChar(resp$content)
+	respData <- strsplit(respData, "\r\n")[[1]]
+	if (mimetype == "application/x-r") {
+		respObj <- eval(parse(text=respData))
+	} else if (mimetype == "text/javascript") {
+		respObj <- fromJSON(respData)
+	} else if (mimetype == "application/x-ruby") {
+		respObj <- fromJSON(respData)
+	}
+	
+	if (resp$status_code >= 400) {
+		stop(respObj)
+	} else {
+		respObj
+	}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R b/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R
new file mode 100644
index 0000000000..2c6c4b66e7
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R
@@ -0,0 +1,53 @@
+#' GraalVM R package is supposed to demonstrate FastR performance and polyglot capabilities 
+#' of GraalVM to GNUR users.
+#'
+#' @name graalvm
+#' @examples
+#' # Loading and setting up
+#' 
+#' library(graalvm)
+#' graalvm.setup("~/work/graalvm-0.21")
+#' 
+#' # Code execution
+#' g(v <- runif(1e8))
+#' g(f <- function(x) { s <- 0; for (i in seq_along(x)) s <- s + x[[i]]; s })
+#' g(system.time(f(v)))
+#' g(system.time(f(v)))
+#' 
+#' g.js("1 < 2")
+#' g.rb("$a = 2")
+#' 
+#' 
+#' # Paired variables
+#' 
+#' # Create and initialize paired variables:
+#' gset.r(a1, TRUE) 
+#' gset.js(a2, c(1,2))
+#' gset.rb(a3, list(a=1,b="2")) 
+#' a1
+#' a2
+#' a3
+#' g.r("a1")
+#' g.js("a2")
+#' g.rb("$a3")
+#' 
+#' g(a1 <- FALSE)
+#' gget(a1)
+#' a1
+#' 
+#' # Paired functions
+#' 
+#' # Create a paired function
+#' gset.r(measure, function(n) { system.time(runif(n)) })
+#' # Execute the local version of the paired function
+#' measure(1e8)
+#' # Execute the remote version of the paired function
+#' g(measure(1e8))
+#' 
+#' # Executing a script file
+#' 
+#' tmp <- tempfile()
+#' writeLines(con = tmp, c("x<-10", "y<-x^2", "y"))
+#' g.r(readLines(con=tmp))
+#'
+NULL
diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr b/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr
new file mode 100644
index 0000000000..d45d981de9
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr
@@ -0,0 +1,44 @@
+##
+ # Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ #
+ # This code is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License version 2 only, as
+ # published by the Free Software Foundation.
+ #
+ # This code is distributed in the hope that it will be useful, but WITHOUT
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ # version 2 for more details (a copy is included in the LICENSE file that
+ # accompanied this code).
+ #
+ # You should have received a copy of the GNU General Public License version
+ # 2 along with this work; if not, write to the Free Software Foundation,
+ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ #
+ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ # or visit www.oracle.com if you need additional information or have any
+ # questions.
+##
+
+inp <- NULL
+out <- NULL
+err <- FALSE
+
+parser <- function(expr) {
+	# The expression is temporarily put into the block due to a bug in the FastR that is
+	# bundled into GraalVM 0.21, which causes that the expression eval(parse(text="x")) fails.
+	# The bug is already fixed in the newest version of FastR.
+	exp <<- parse(text = paste0("{", expr, "}"))
+}
+
+deparseObject <- function(obj) paste(deparse(obj), collapse = "\r\n")
+
+result <- function() deparseObject(out)
+
+isError <- function() err
+
+.fastr.interop.export('parser', parser)
+.fastr.interop.export('deparseObject', deparseObject)
+.fastr.interop.export('result', result)
+.fastr.interop.export('isError', isError)
diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/handler.rb b/com.oracle.truffle.r.pkgs/graalvm/data/handler.rb
new file mode 100644
index 0000000000..4189fed162
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/data/handler.rb
@@ -0,0 +1,37 @@
+=begin
+ Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+=end
+
+require 'json'
+
+$expr = ""
+
+def storeExpr(e)
+	$expr = Truffle::Interop.from_java_string(e)
+end
+
+def toJSON(res)
+	Truffle::Interop.to_java_string(res.to_json)
+end
+
+Truffle::Interop.export('storeExpr', method(:storeExpr))
+Truffle::Interop.export('rubyToJSON', method(:toJSON))
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/server.js b/com.oracle.truffle.r.pkgs/graalvm/data/server.js
new file mode 100644
index 0000000000..0e3604a98a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/data/server.js
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+var fs = require('fs');
+var http = require("http");
+
+function parseParams(body) {
+	var lines = body.split('\r\n');
+	var paramName = null;
+	var paramValue = "";
+	var params = {};
+	for(var i = 0; i < lines.length; i++) {
+		if (lines[i].startsWith("--------------------------")) {
+			if (paramName != null) {
+				params[paramName] = paramValue;
+				paramName = null;
+				paramValue = "";
+			}
+			continue;
+		}
+		if (lines[i].startsWith("Content-Disposition:")) {
+			paramName = lines[i].split('=')[1];
+			paramName = paramName.substring(1, paramName.length - 1);
+			i++;
+			continue;
+		}
+		if (lines[i] === "") {
+			continue;
+		}
+		paramValue += lines[i];
+	}
+	
+	return params;
+}
+
+function evalJS(code, echo) {
+	//console.log("Executing JS code: '" + code + "'");
+	var res = {}; 
+	try {
+		r = eval(code)
+		res.isError = false;
+		if (echo) {
+			res.data = JSON.stringify(r);
+		} else {
+			res.data = JSON.stringify(null);
+		}
+	} catch (error) {
+		//console.log("Caught error:" + JSON.stringify(error));
+		res.isError = true;
+		res.data = "" + error;
+	}
+	return res;
+}
+
+var rHandlerScript = fs.readFileSync( __dirname + "/handler.fr", "utf8");
+Interop.eval("application/x-r", rHandlerScript);
+
+rParser = Interop.import('parser');
+rResult = Interop.import('result');
+rIsError = Interop.import('isError');
+deparseObject = Interop.import('deparseObject');
+
+function evalR(code, echo) {
+	rParser(code);
+	if (echo) {
+		Interop.eval("application/x-r", "err <- TRUE; out <- tryCatch({ err <- TRUE; r <- eval(exp); err <- FALSE; r }, error = function(e) e$message)");
+	} else {
+		Interop.eval("application/x-r", "err <- TRUE; out <- tryCatch({ err <- TRUE; eval(exp); err <- FALSE; NULL }, error = function(e) e$message)");
+	}
+	var res = {}
+	res.data = rResult();
+	res.isError = rIsError();
+	return res;
+}
+
+var rubyHandlerScript = fs.readFileSync( __dirname + "/handler.rb", "utf8");
+Interop.eval("application/x-ruby", rubyHandlerScript);
+rubyStoreExpr = Interop.import('storeExpr');
+rubyToJSON = Interop.import('rubyToJSON');
+
+function evalRuby(code, echo) {
+	rubyStoreExpr(code);
+	var r;
+	code = `begin
+		eval($expr)
+	rescue Exception => exc
+		-1
+	end`;
+	if (echo) {
+		r = Interop.eval("application/x-ruby", code);
+	} else {
+		r = Interop.eval("application/x-ruby", code);
+	}
+	var res = {}
+	rJSON = rubyToJSON(r);
+	//console.log("Result from Ruby:" + rJSON);
+	res.data = rJSON;
+	res.isError = false;
+	return res;
+}
+
+function processPost(request, response) {
+    var queryData = "";
+
+    if(request.method == 'POST') {
+        request.on('data', function(data) {
+            queryData += data;
+            if(queryData.length > 1e6) {
+                queryData = "";
+                response.writeHead(413, {'Content-Type': 'text/plain'}).end();
+                request.connection.destroy();
+            }
+        });
+
+        request.on('end', function() {
+        	var params = parseParams(queryData);
+			//console.log("Params: " + JSON.stringify(params));
+        	var echo = params.echo === "TRUE";
+        	var res;
+        	if (params.mimetype == "application/x-r") {
+	        	res = evalR(params.code, echo);
+			} else if (params.mimetype == "text/javascript") {
+	        	res = evalJS(params.code, echo);
+			} else if (params.mimetype == "application/x-ruby") {
+	        	res = evalRuby(params.code, echo);
+	      	} else {
+        		res = {
+        			isError : true,
+        			data : deparseObject("Unsupported language: " + params.mimetype)
+        		}
+        	}
+			if (res.isError) {
+				response.writeHead(400, {'Content-Type': 'text/plain'});
+			} else {
+				response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
+			}
+			response.end(res.data);
+
+        });
+
+    } else {
+        response.writeHead(405, {'Content-Type': 'text/plain'});
+        response.end();
+    }
+}
+
+// Launch the server
+console.log("Starting GraalVM agent...");
+
+var server = http.createServer(function (inp, out) {
+	var command = inp.url.substring(1);
+	if (command == "ping") {
+		out.end("pong");
+	} else if (command == "stop") {
+		console.log("GraalVM agent stopped");
+		out.end(command, null, function() {
+			process.exit(0);
+		});
+	} else {
+		if(inp.method == 'POST') {
+			processPost(inp, out);
+		} else {
+			out.writeHead(200, "OK", {'Content-Type': 'text/plain'});
+			out.end();
+		}
+	}
+});
+
+host = process.argv[2]
+port = parseInt(process.argv[3])
+server.listen(port, host);
+server.on('error', function(err) {
+    console.log("Caught error: " + err);
+});
+
+console.log("GraalVM agent accepting at " + host + ":" + port);
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.Rd
new file mode 100644
index 0000000000..3038fd1e7f
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.Rd
@@ -0,0 +1,32 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{g}
+\alias{g}
+\title{Execute code by GraalVM using the language interpreter that corresponds
+to the language mimetype.}
+\usage{
+g(code, echo = TRUE, mimetype = "application/x-r")
+}
+\arguments{
+\item{code}{the code to be executed. It must be a language element as long as the target
+language is R, otherwise it must be a string.}
+
+\item{echo}{controls whether this function returns the result of the interpreted code.
+The default value is TRUE.}
+
+\item{mimetype}{The mimetype of the target language. Currently supported values are
+"application/x-r", "text/javascript" and "application/x-ruby".}
+}
+\description{
+Execute code by GraalVM using the language interpreter that corresponds
+to the language mimetype.
+}
+\examples{
+g(runif(10^3))
+g(runif(10^8), echo = FALSE) # We do not want that the result is returned due to its size
+g("1 < 2", mimetype = "text/javascript")
+}
+\seealso{
+Other execution functions: \code{\link{g.js}},
+  \code{\link{g.rb}}, \code{\link{g.r}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd
new file mode 100644
index 0000000000..7d9287f25b
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.js.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{g.js}
+\alias{g.js}
+\title{Execute JavaScript code.}
+\usage{
+g.js(code, echo = TRUE)
+}
+\description{
+Execute JavaScript code.
+}
+\examples{
+g.js("1 < 2")
+}
+\seealso{
+Other execution functions: \code{\link{g.rb}},
+  \code{\link{g.r}}, \code{\link{g}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd
new file mode 100644
index 0000000000..3566a2a0b4
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.r.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{g.r}
+\alias{g.r}
+\title{Execute R code.}
+\usage{
+g.r(code, echo = TRUE)
+}
+\description{
+Execute R code.
+}
+\examples{
+g.r("runif(10^3)")
+}
+\seealso{
+Other execution functions: \code{\link{g.js}},
+  \code{\link{g.rb}}, \code{\link{g}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd
new file mode 100644
index 0000000000..f307ee4a34
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/g.rb.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{g.rb}
+\alias{g.rb}
+\title{Execute Ruby code.}
+\usage{
+g.rb(code, echo = TRUE)
+}
+\description{
+Execute Ruby code.
+}
+\examples{
+g.rb("1 < 2")
+}
+\seealso{
+Other execution functions: \code{\link{g.js}},
+  \code{\link{g.r}}, \code{\link{g}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd
new file mode 100644
index 0000000000..e0515efb00
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gget}
+\alias{gget}
+\title{Retrieve the variable defined in a GraalVM language. The local variable must have been 
+initialized by one of the language specific gget.* or ggset.* functions.}
+\usage{
+gget(var)
+}
+\description{
+Retrieve the variable defined in a GraalVM language. The local variable must have been 
+initialized by one of the language specific gget.* or ggset.* functions.
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.rb}}, \code{\link{gget.r}},
+  \code{\link{gset.js}}, \code{\link{gset.rb}},
+  \code{\link{gset.r}}, \code{\link{gset}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd
new file mode 100644
index 0000000000..7caf44f206
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.js.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gget.js}
+\alias{gget.js}
+\title{Retrieve the variable defined in GraalVM JS.}
+\usage{
+gget.js(var)
+}
+\description{
+Retrieve the variable defined in GraalVM JS.
+}
+\seealso{
+Other paired variables: \code{\link{gget.rb}},
+  \code{\link{gget.r}}, \code{\link{gget}},
+  \code{\link{gset.js}}, \code{\link{gset.rb}},
+  \code{\link{gset.r}}, \code{\link{gset}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd
new file mode 100644
index 0000000000..df1678e584
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.r.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gget.r}
+\alias{gget.r}
+\title{Retrieve the variable defined in GraalVM FastR.}
+\usage{
+gget.r(var)
+}
+\description{
+Retrieve the variable defined in GraalVM FastR.
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.rb}}, \code{\link{gget}},
+  \code{\link{gset.js}}, \code{\link{gset.rb}},
+  \code{\link{gset.r}}, \code{\link{gset}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd
new file mode 100644
index 0000000000..4dfe3fd3fe
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gget.rb.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gget.rb}
+\alias{gget.rb}
+\title{Retrieve the variable defined in GraalVM Ruby.}
+\usage{
+gget.rb(var)
+}
+\description{
+Retrieve the variable defined in GraalVM Ruby.
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.r}}, \code{\link{gget}},
+  \code{\link{gset.js}}, \code{\link{gset.rb}},
+  \code{\link{gset.r}}, \code{\link{gset}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd
new file mode 100644
index 0000000000..a77541d69d
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd
@@ -0,0 +1,59 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/graalvm.R
+\name{graalvm}
+\alias{graalvm}
+\title{GraalVM R package is supposed to demonstrate FastR performance and polyglot capabilities 
+of GraalVM to GNUR users.}
+\description{
+GraalVM R package is supposed to demonstrate FastR performance and polyglot capabilities 
+of GraalVM to GNUR users.
+}
+\examples{
+# Loading and setting up
+
+library(graalvm)
+graalvm.setup("~/work/graalvm-0.21")
+
+# Code execution
+g(v <- runif(1e8))
+g(f <- function(x) { s <- 0; for (i in seq_along(x)) s <- s + x[[i]]; s })
+g(system.time(f(v)))
+g(system.time(f(v)))
+
+g.js("1 < 2")
+g.rb("$a = 2")
+
+
+# Paired variables
+
+# Create and initialize paired variables:
+gset.r(a1, TRUE) 
+gset.js(a2, c(1,2))
+gset.rb(a3, list(a=1,b="2")) 
+a1
+a2
+a3
+g.r("a1")
+g.js("a2")
+g.rb("$a3")
+
+g(a1 = FALSE)
+gget(a1)
+a1
+
+# Paired functions
+
+# Create a paired function
+gset.r(measure, function(n) { system.time(runif(n)) })
+# Execute the local version of the paired function
+measure(1e8)
+# Execute the remote version of the paired function
+g(measure(1e8))
+
+# Executing a script file
+
+tmp <- tempfile()
+writeLines(con = tmp, c("x<-10", "y<-x^2", "y"))
+g.r(readLines(con=tmp))
+
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd
new file mode 100644
index 0000000000..9007932d6d
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.setup.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{graalvm.setup}
+\alias{graalvm.setup}
+\title{Set up the GraalVM agent}
+\usage{
+graalvm.setup(home, host = "localhost", port = 9876, rlibs = paste0(home,
+  "/language/R/library"))
+}
+\arguments{
+\item{home}{The home folder of the GraalVM installation}
+
+\item{host}{The local host name at which the GraalVM agent is listening}
+
+\item{port}{The port at which the GraalVM agent is listening}
+
+\item{rlibs}{The value of the FastR R_LIBS environmental variable. The default 
+value is calculated as paste0(graalvm.home, "/language/R/library").}
+}
+\description{
+Set up the GraalVM agent
+}
+\examples{
+graalvm.setup("~/work/graalvm-0.21")
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd
new file mode 100644
index 0000000000..1527a6cf91
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.start.Rd
@@ -0,0 +1,13 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{graalvm.start}
+\alias{graalvm.start}
+\title{Start the GraalVM agent. The agent is normally started automatically upon the first
+code ecxecution.}
+\usage{
+graalvm.start()
+}
+\description{
+Start the GraalVM agent. The agent is normally started automatically upon the first
+code ecxecution.
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd
new file mode 100644
index 0000000000..d559fddba1
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.stop.Rd
@@ -0,0 +1,11 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{graalvm.stop}
+\alias{graalvm.stop}
+\title{Stop the GraalVM agent.}
+\usage{
+graalvm.stop()
+}
+\description{
+Stop the GraalVM agent.
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd
new file mode 100644
index 0000000000..9c139e088c
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.Rd
@@ -0,0 +1,35 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gset}
+\alias{gset}
+\title{Assign a value to a paired variable. The value is assigned both locally and remotely.
+The local variable must have been initialized by one of the language specific gget.* or
+ggset.* functions.}
+\usage{
+gset(var, value = var)
+}
+\description{
+Assign a value to a paired variable. The value is assigned both locally and remotely.
+The local variable must have been initialized by one of the language specific gget.* or
+ggset.* functions.
+}
+\examples{
+# Create and initialize a variable in JS
+g.js("a = 1")
+# Pick up the a variable from JS and define its counterpart in GNUR
+gget.js(a)
+a
+# Increment the variable both locally and in JS 
+gset(a, a + 1)
+a
+g.js("a[0]")
+g.js("a[1] = 10")
+gget(a)
+a
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.rb}}, \code{\link{gget.r}},
+  \code{\link{gget}}, \code{\link{gset.js}},
+  \code{\link{gset.rb}}, \code{\link{gset.r}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd
new file mode 100644
index 0000000000..1cf7308f64
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.js.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gset.js}
+\alias{gset.js}
+\title{Assign the value to the paired variable in Graal JS and locally.}
+\usage{
+gset.js(var, value)
+}
+\description{
+Assign the value to the paired variable in Graal JS and locally.
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.rb}}, \code{\link{gget.r}},
+  \code{\link{gget}}, \code{\link{gset.rb}},
+  \code{\link{gset.r}}, \code{\link{gset}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd
new file mode 100644
index 0000000000..669c2c700c
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.r.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gset.r}
+\alias{gset.r}
+\title{Assign the value to the paired variable in Graal FastR and locally.}
+\usage{
+gset.r(var, value)
+}
+\description{
+Assign the value to the paired variable in Graal FastR and locally.
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.rb}}, \code{\link{gget.r}},
+  \code{\link{gget}}, \code{\link{gset.js}},
+  \code{\link{gset.rb}}, \code{\link{gset}}
+}
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd
new file mode 100644
index 0000000000..45aaef4d8e
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/gset.rb.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/g.R
+\name{gset.rb}
+\alias{gset.rb}
+\title{Assign the value to the paired variable in Graal Ruby and locally.}
+\usage{
+gset.rb(var, value)
+}
+\description{
+Assign the value to the paired variable in Graal Ruby and locally.
+}
+\seealso{
+Other paired variables: \code{\link{gget.js}},
+  \code{\link{gget.rb}}, \code{\link{gget.r}},
+  \code{\link{gget}}, \code{\link{gset.js}},
+  \code{\link{gset.r}}, \code{\link{gset}}
+}
-- 
GitLab


From 22612a6d84a3275ab3eaff14eab99f3d27774018 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 19 Apr 2017 10:44:45 -0700
Subject: [PATCH 310/402] Truffle NFI fixes

---
 .../r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java       | 8 ++++----
 .../truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java | 2 +-
 .../fficall/src/truffle_nfi/lapack_rffi.c                 | 8 ++++++++
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
index 66b2d2c0be..bfb50624dc 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
@@ -39,7 +39,7 @@ public class TruffleNFI_Lapack implements LapackRFFI {
         dgeqp3("(sint32, sint32, [double], sint32, [sint32], [double], [double], sint32) : sint32"),
         dormq("(uint8, uint8, sint32, sint32, sint32, [double], sint32, [double], [double], sint32, [double], sint32) : sint32"),
         dtrtrs("(uint8, uint8, uint8, sint32, sint32, [double], sint32, [double], sint32) : sint32"),
-        dgetr("(sint32, sint32, [double], sint32, [sint32]) : sint32"),
+        dgetrf("(sint32, sint32, [double], sint32, [sint32]) : sint32"),
         dpotrf("(uint8, sint32, [double], sint32) : sint32"),
         dpotri("(uint8, sint32, [double], sint32) : sint32"),
         dpstrf("uint8, sint32, [double], sint32, [sint32], [sint32], double, [double]) : sint32"),
@@ -143,9 +143,9 @@ public class TruffleNFI_Lapack implements LapackRFFI {
 
         @Override
         public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
-            Function.dgetr.initialize();
+            Function.dgetrf.initialize();
             try {
-                return (int) ForeignAccess.sendExecute(Function.dgetr.executeNode, Function.dgetr.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv));
+                return (int) ForeignAccess.sendExecute(Function.dgetrf.executeNode, Function.dgetrf.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv));
             } catch (InteropException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
@@ -171,7 +171,7 @@ public class TruffleNFI_Lapack implements LapackRFFI {
         public int execute(char uplo, int n, double[] a, int lda) {
             Function.dpotri.initialize();
             try {
-                return (int) ForeignAccess.sendExecute(Function.dpotri.executeNode, Function.dpotrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda);
+                return (int) ForeignAccess.sendExecute(Function.dpotri.executeNode, Function.dpotri.function, uplo, n, JavaInterop.asTruffleObject(a), lda);
             } catch (InteropException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
index a0c1b6d886..f9a3e37eaa 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
@@ -40,7 +40,7 @@ public class TruffleNFI_PCRE implements PCRERFFI {
         maketables("(): sint64", true),
         compile("((uint64, string, sint32): void, string, sint32, uint64): void", false),
         getcapturecount("(uint64, uint64): sint32", false),
-        getcapturenames("((sint32, string): void, uint64, uint64)", false),
+        getcapturenames("((sint32, string): void, uint64, uint64): sint32", false),
         study("(uint64, sint32): void", false),
         exec("(uint64, uint64, [uint8], sint32, sint32, sint32, [sint32], sint32): sint32", true);
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
index cc68ca6f0a..17d0589252 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
@@ -85,6 +85,14 @@ int call_dpotrf(char uplo, int n, double *a, int lda) {
     return info;
 }
 
+extern int dpotri_(char *uplo, int *n, double *a, int *lda, int *info);
+
+int call_dpotri(char uplo, int n, double *a, int lda) {
+    int info;
+    dpotri_(&uplo, &n, a, &lda, &info);
+    return info;
+}
+
 extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info);
 
 int call_dpstrf(char uplo, int n, double *a, int lda, int *piv, int *rank, double tol, double *work) {
-- 
GitLab


From db8b80067ad70a4a1b801be363c4fc77583770f9 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 19 Apr 2017 10:45:10 -0700
Subject: [PATCH 311/402] re-enable NFI unit tests

---
 ci.hocon | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ci.hocon b/ci.hocon
index 947bcff284..240265cada 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -153,7 +153,7 @@ internalPkgtest: ${common} {
 
 builds = [
   ${gateTestLinux}            {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-amd64"}
-#  ${gateTestLinuxNFI}         {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-nfi-amd64"}
+  ${gateTestLinuxNFI}         {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-nfi-amd64"}
   ${gateTestNoSpecialsLinux}  {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-amd64-nospecials"}
   ${gateTestDarwin}           {capabilities : [darwin, amd64], targets : [gate], name: "gate-test-darwin-amd64"}
   ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate], name: "gate-style-linux-amd64"}
-- 
GitLab


From f24783f137633d35fa157a60b14ce19b6af7e220 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 19 Apr 2017 11:42:57 -0700
Subject: [PATCH 312/402] TruffleNFI: implement more Rinternals

---
 .../fficall/src/truffle_nfi/Rinternals.c                     | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
index 026f9f5ba7..db41b21bcc 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -906,7 +906,7 @@ SEXP *VECTOR_PTR(SEXP x){
 }
 
 SEXP Rf_asChar(SEXP x){
-	return unimplemented("Rf_asChar");
+	return ((call_Rf_asChar) callbacks[Rf_asChar_x])(x);
 }
 
 SEXP Rf_PairToVectorList(SEXP x){
@@ -931,8 +931,7 @@ int Rf_asInteger(SEXP x) {
 }
 
 double Rf_asReal(SEXP x) {
-	unimplemented("Rf_asReal");
-	return 0.0;
+	return ((call_Rf_asReal) callbacks[Rf_asReal_x])(x);
 }
 
 Rcomplex Rf_asComplex(SEXP x){
-- 
GitLab


From eaa6a499f097eb61a2302326c2691489581d2b1e Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 19 Apr 2017 14:04:26 -0700
Subject: [PATCH 313/402] Truffle NFI: fix tracing return values

---
 .../interop/ffi/nfi/TruffleNFI_Call.java      | 27 ++++++++++++-------
 1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
index acefb85638..195c194f99 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
@@ -238,7 +238,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction);
+                    result = ForeignAccess.sendExecute(executeNode, callFunction);
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -256,7 +257,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -274,7 +276,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -292,7 +295,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -310,8 +314,9 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]),
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]),
                                     JavaInterop.asTruffleObject(args[3]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -329,8 +334,9 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
                                     JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -348,8 +354,9 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
                                     JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -367,9 +374,10 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
                                     JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]),
                                     JavaInterop.asTruffleObject(args[6]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
@@ -387,9 +395,10 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object");
-                    return ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
                                     JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]),
                                     JavaInterop.asTruffleObject(args[6]), JavaInterop.asTruffleObject(args[7]));
+                    return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-- 
GitLab


From 16cf49f7da6cf2ddf95eda79ee10cc03c0723daa Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 19 Apr 2017 16:27:36 -0700
Subject: [PATCH 314/402] TruffleNFI: trace tools getc upcall

---
 .../truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java | 2 +-
 .../r/engine/interop/ffi/nfi/TruffleNFI_Tools.java        | 8 ++++++--
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
index 195c194f99..cd65b42fb8 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
@@ -230,7 +230,7 @@ public class TruffleNFI_Call implements CallRFFI {
         @Child Node bindNode = Message.createInvoke(1).createNode();
 
         @Specialization(guards = "args.length == 0")
-        protected Object invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args,
+        protected Object invokeCall0(NativeCallInfo nativeCallInfo, Object[] args,
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
index 305c038b49..6eb12e4527 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
@@ -52,10 +53,13 @@ public class TruffleNFI_Tools implements ToolsRFFI {
         private static class RConnGetCImpl implements RConnGetC {
             @Override
             public int getc(RConnection conn) {
+                RFFIUtils.traceUpCall("getc");
                 try {
-                    return conn.getc();
+                    int r = conn.getc();
+                    RFFIUtils.traceUpCallReturn("getc", r);
+                    return r;
                 } catch (IOException ex) {
-                    throw RInternalError.shouldNotReachHere(ex);
+                    return -1;
                 }
             }
         }
-- 
GitLab


From e02beb03173bdd91d75d3cb9dcc0cff73309998c Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 21 Apr 2017 23:20:04 +0200
Subject: [PATCH 315/402] Add @TruffleBoundary to more grid functions and logb

---
 .../r/library/fastrGrid/GridContext.java      |  2 ++
 .../r/library/fastrGrid/GridStateGetNode.java |  2 ++
 .../r/library/fastrGrid/GridStateSetNode.java |  2 ++
 .../r/nodes/builtin/base/LogFunctions.java    | 27 ++++++++++---------
 4 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 799af373a1..54a33fec0b 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import java.util.ArrayList;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
@@ -58,6 +59,7 @@ public final class GridContext {
         return INSTANCE;
     }
 
+    @TruffleBoundary
     public GridState getGridState() {
         gridState.setDeviceState(devices.get(currentDeviceIdx).state);
         return gridState;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
index f54af61482..d53f60c9c5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateGetNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import java.util.function.Function;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 
 /**
@@ -41,6 +42,7 @@ final class GridStateGetNode extends RExternalBuiltinNode.Arg0 {
     }
 
     @Override
+    @TruffleBoundary
     public Object execute() {
         Object result = getter.apply(GridContext.getContext().getGridState());
         assert result != null;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java
index 4b07fdcc38..25a798d189 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridStateSetNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import java.util.function.BiConsumer;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -46,6 +47,7 @@ public final class GridStateSetNode extends RExternalBuiltinNode.Arg1 {
     }
 
     @Override
+    @TruffleBoundary
     public Object execute(Object arg) {
         setter.accept(GridContext.getContext().getGridState(), arg);
         return RNull.instance;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index a286bc76d9..4a3a38d713 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -30,6 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.util.Arrays;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
@@ -54,6 +55,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
@@ -208,13 +210,13 @@ public class LogFunctions {
                 Arrays.fill(resultVector, 0, resultVector.length, Double.NaN);
             } else {
                 xNACheck.enable(vector);
-                Runnable[] warningResult = new Runnable[1];
+                RBaseNode[] warningCtx = new RBaseNode[1];
                 for (int i = 0; i < vector.getLength(); i++) {
                     double value = vector.getDataAt(i);
-                    resultVector[i] = xNACheck.check(value) ? RRuntime.DOUBLE_NA : logb(value, base, warningResult);
+                    resultVector[i] = xNACheck.check(value) ? RRuntime.DOUBLE_NA : logb(value, base, warningCtx);
                 }
-                if (warningResult[0] != null) {
-                    warningResult[0].run();
+                if (warningCtx[0] != null) {
+                    RError.warning(warningCtx[0], RError.Message.NAN_PRODUCED);
                 }
             }
             boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA();
@@ -230,26 +232,27 @@ public class LogFunctions {
                 nanProfile.enter();
                 return base;
             }
-            Runnable[] warningResult = new Runnable[1];
-            double ret = logb(x, base, warningResult);
-            if (warningResult[0] != null) {
-                warningResult[0].run();
+            RBaseNode[] warningCtx = new RBaseNode[1];
+            double ret = logb(x, base, warningCtx);
+            if (warningCtx[0] != null) {
+                RError.warning(warningCtx[0], RError.Message.NAN_PRODUCED);
             }
             return ret;
         }
 
-        private double logb(double x, double base, Runnable[] warningResult) {
+        @TruffleBoundary
+        private double logb(double x, double base, RBaseNode[] warningCtx) {
             double logx = Math.log(x);
             if (Double.isNaN(logx)) {
-                warningResult[0] = () -> RError.warning(this, RError.Message.NAN_PRODUCED);
+                warningCtx[0] = this;
             }
             if (base == Math.E) {
                 return logx;
             }
 
             double result = logx / Math.log(base);
-            if (warningResult[0] == null && Double.isNaN(result)) {
-                warningResult[0] = () -> RError.warning(RError.SHOW_CALLER, RError.Message.NAN_PRODUCED);
+            if (warningCtx[0] == null && Double.isNaN(result)) {
+                warningCtx[0] = RError.SHOW_CALLER;
             }
 
             return result;
-- 
GitLab


From ec810a6edb7f1712e5f3010a17325854228b2d72 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 21 Apr 2017 14:50:37 -0700
Subject: [PATCH 316/402] RFFIFactory: initialize in static block

---
 .../com/oracle/truffle/r/engine/TruffleRLanguage.java    | 1 -
 .../com/oracle/truffle/r/runtime/ffi/RFFIFactory.java    | 9 ++++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index 9f04a1454b..f9d97de35c 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -71,7 +71,6 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
      */
     private static void initialize() {
         try {
-            RFFIFactory.initialize();
             Locale.setDefault(Locale.ROOT);
             RAccuracyInfo.initialize();
         } catch (Throwable t) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index b443cb0a7c..27d418847b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -30,7 +30,11 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState;
  * Factory class for the different possible implementations of the {@link RFFI} interface.
  *
  * The RFFI may need to do special things in the case of multiple contexts, hence any given factory
- * must support the {@link #newContextState()} method.
+ * must support the {@link #newContextState()} method. Initialization of factory state that is
+ * dependent on the system being properly initialized <b>must</b> be done in the
+ * {@link ContextState#initialize} method and not in the constructor or {@link #createRFFI} method
+ * as they are invoked in the static block and the system is not typically initialized at that
+ * point.
  */
 public abstract class RFFIFactory {
     private enum Factory {
@@ -57,7 +61,7 @@ public abstract class RFFIFactory {
 
     @CompilationFinal protected static RFFI theRFFI;
 
-    public static RFFIFactory initialize() {
+    static {
         if (instance == null) {
             String klassName = getFactoryClassName();
             try {
@@ -67,7 +71,6 @@ public abstract class RFFIFactory {
                 throw Utils.rSuicide("Failed to instantiate class: " + klassName + ": " + ex);
             }
         }
-        return instance;
     }
 
     private static String getFactoryClassName() {
-- 
GitLab


From 717bfe7e041a7eec522ccba965d8fcc53797186e Mon Sep 17 00:00:00 2001
From: Gilles Duboscq <gilles.m.duboscq@oracle.com>
Date: Fri, 21 Apr 2017 15:20:42 +0200
Subject: [PATCH 317/402] Update Truffle import

---
 README.md                                                    | 2 +-
 .../src/com/oracle/truffle/r/nodes/casts/TestCasts.java      | 2 +-
 documentation/dev/truffle_llvm_ffi.md                        | 2 +-
 mx.fastr/mx_fastr.py                                         | 4 ++--
 mx.fastr/suite.py                                            | 5 +++--
 5 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index 6c421a3f83..ae5a5aa685 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ FastR is primarily aimed at long-running applications. The runtime performance b
 
 Building FastR from source is supported on Mac OS X (El Capitan onwards), and various flavors of Linux.
 FastR uses a build tool called `mx` (cf `maven`) which can be downloaded from [here](http://github.com/graalvm/mx).
-`mx` manages software in _suites_, which are normally one-to-one with a `git` repository. FastR depends fundamentally on the [truffle](http://github.com/graalvm/truffle) suite. However, performance also depends on the [Graal compiler](http://github.com/graalvm/graal-core) as without it, FastR operates in interpreted mode only. The conventional way to arrange the Git repos (suites) is as siblings in a parent directory, which we will call `FASTR_HOME`.
+`mx` manages software in _suites_, which are normally one-to-one with a `git` repository. FastR depends fundamentally on the [truffle](http://github.com/graalvm/truffle) suite. However, performance also depends on the [Graal compiler](http://github.com/graalvm/graal) as without it, FastR operates in interpreted mode only. The conventional way to arrange the Git repos (suites) is as siblings in a parent directory, which we will call `FASTR_HOME`.
 
 ## Pre-Requisites
 FastR shares some code with GnuR, for example, the default packages and the Blas library. Therefore, a version of GnuR (currently
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index 16b1166df7..9cc658a9ea 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -69,7 +69,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * mx --J @'-Dgraal.Dump=HighTier:1 -Dgraal.MethodFilter=*TestCasts* -Dgraal.TraceTruffleCompilation=true -Dgraal.PrintBackendCFG=false'  junits --tests TestCasts
  *
  * of course, Graal needs to be imported for this to work:
- * DEFAULT_DYNAMIC_IMPORTS=graal-core (or graal-enterprise)
+ * DEFAULT_DYNAMIC_IMPORTS=compiler (or graal-enterprise)
  */
 public class TestCasts extends TestBase {
 
diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md
index 8eb7fd13ca..511d667d43 100644
--- a/documentation/dev/truffle_llvm_ffi.md
+++ b/documentation/dev/truffle_llvm_ffi.md
@@ -15,7 +15,7 @@ The `sulong` repository must be cloned to a sibling directory of `fastr` and bui
     mx build
     mx su-pulldragonegg
 
-The `mx build` step will clone the `graal-core` repository, if necessary, and build that also. The `mx su-pulldragonegg` step is required to be able to compile Fortran code to LLVM, which is required by FastR.
+The `mx build` step will clone the `compiler` repository, if necessary, and build that also. The `mx su-pulldragonegg` step is required to be able to compile Fortran code to LLVM, which is required by FastR.
 
 ## Additional Pre-Requisites
 
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 0bc160dec4..eb799067a5 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -39,7 +39,7 @@ import os
 '''
 This is the launchpad for all the functions available for building/running/testing/analyzing
 FastR. FastR can run with or without the Graal compiler enabled. As a convenience if the
-graal-core suite is detected then the use of the Graal compiler is enabled without any
+compiler suite is detected then the use of the Graal compiler is enabled without any
 additional command line options being required to the mx command, i.e. it is as if --jdk jvmci
 was passed as an mx global option.
 '''
@@ -48,7 +48,7 @@ _fastr_suite = mx.suite('fastr')
 '''
 If this is None, then we run under the standard VM in interpreted mode only.
 '''
-_mx_graal = mx.suite("graal-core", fatalIfMissing=False)
+_mx_graal = mx.suite("compiler", fatalIfMissing=False)
 _mx_sulong = mx.suite("sulong", fatalIfMissing=False)
 
 _r_command_package = 'com.oracle.truffle.r.engine'
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 39727463a8..3fa9349077 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -28,9 +28,10 @@ suite = {
     "suites" : [
             {
                "name" : "truffle",
-               "version" : "e4c752d5477f3177b30ba80af7cd3c3e61329d2e",
+               "subdir" : True,
+               "version" : "f19ebf4be9550d744f8c431cc466a5f87682f9c4",
                "urls" : [
-                    {"url" : "https://github.com/graalvm/truffle", "kind" : "git"},
+                    {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
                 ]
             },
-- 
GitLab


From 0ef0fe224c03d33c7b6b7eee08d1dc57c46fb746 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 24 Apr 2017 15:27:44 +0200
Subject: [PATCH 318/402] ignore deprecation warnings from Truffle update

---
 .../src/com/oracle/truffle/r/engine/REngine.java         | 5 ++++-
 .../com/oracle/truffle/r/engine/TruffleRLanguage.java    | 9 ++++++---
 .../r/engine/interop/RAbstractVectorAccessFactory.java   | 3 +++
 .../r/nodes/builtin/base/printer/ValuePrinterNode.java   | 1 +
 .../src/com/oracle/truffle/r/nodes/casts/TestCasts.java  | 1 +
 .../com/oracle/truffle/r/nodes/test/TestUtilities.java   | 3 ++-
 .../src/com/oracle/truffle/r/nodes/RRootNode.java        | 1 +
 .../oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java    | 1 +
 .../com/oracle/truffle/r/runtime/context/RContext.java   | 4 ++--
 .../src/com/oracle/truffle/r/runtime/data/RTypes.java    | 3 ---
 .../src/com/oracle/truffle/r/runtime/ffi/DLL.java        | 1 +
 .../com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java   | 1 +
 .../com/oracle/truffle/r/runtime/rng/user/UserRNG.java   | 1 +
 13 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index 8798c06e69..73a6b694ca 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -293,6 +293,7 @@ final class REngine implements Engine, Engine.Timings {
     }
 
     @Override
+    @SuppressWarnings("deprecation")
     public CallTarget parseToCallTarget(Source source, MaterializedFrame executionFrame) throws ParseException {
         if (source == Engine.GET_CONTEXT) {
             /*
@@ -332,6 +333,7 @@ final class REngine implements Engine, Engine.Timings {
 
         @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
+        @SuppressWarnings("deprecation")
         PolyglotEngineRootNode(List<RSyntaxNode> statements, SourceSection sourceSection, MaterializedFrame executionFrame) {
             super(TruffleRLanguage.class, sourceSection, new FrameDescriptor());
             // can't print if initializing the system in embedded mode (no builtins yet)
@@ -519,6 +521,7 @@ final class REngine implements Engine, Engine.Timings {
         @Child private GetVisibilityNode visibility = GetVisibilityNode.create();
         @Child private SetVisibilityNode setVisibility = SetVisibilityNode.create();
 
+        @SuppressWarnings("deprecation")
         protected AnonymousRootNode(RNode body, String description, boolean printResult, boolean topLevel) {
             super(TruffleRLanguage.class, null, new FrameDescriptor());
             this.body = body;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index f9d97de35c..1e282c0909 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -90,11 +90,12 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
 
     private static boolean systemInitialized;
 
-    public static final TruffleRLanguage INSTANCE = new TruffleRLanguage();
+    public static TruffleRLanguage INSTANCE;
 
     public static final String MIME = RRuntime.R_APP_MIME;
 
-    private TruffleRLanguage() {
+    public TruffleRLanguage() {
+        INSTANCE = this;
     }
 
     @Override
@@ -185,8 +186,8 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
         return null;
     }
 
-    @SuppressWarnings("try")
     @Override
+    @SuppressWarnings({"try", "deprecation"})
     protected CallTarget parse(ParsingRequest request) throws Exception {
         CompilerAsserts.neverPartOfCompilation();
         try (RCloseable c = RContext.withinContext(findContext(createFindContextNode()))) {
@@ -228,10 +229,12 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
     }
 
     // TODO: why isn't the original method public?
+    @SuppressWarnings("deprecation")
     public Node actuallyCreateFindContextNode() {
         return createFindContextNode();
     }
 
+    @SuppressWarnings("deprecation")
     public RContext actuallyFindContext0(Node contextNode) {
         return findContext(contextNode);
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
index 75555feaac..f5b6dbbb1b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
@@ -48,6 +48,7 @@ public final class RAbstractVectorAccessFactory implements Factory18 {
 
         @Child private RLengthNode lengthNode = RLengthNode.create();
 
+        @SuppressWarnings("deprecation")
         VectorSizeNode() {
             super(TruffleRLanguage.class, null, null);
         }
@@ -65,6 +66,7 @@ public final class RAbstractVectorAccessFactory implements Factory18 {
         @Child private RLengthNode lengthNode = RLengthNode.create();
         @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
+        @SuppressWarnings("deprecation")
         VectorReadNode() {
             super(TruffleRLanguage.class, null, null);
             this.lengthAccess = false;
@@ -94,6 +96,7 @@ public final class RAbstractVectorAccessFactory implements Factory18 {
     }
 
     private abstract class InteropRootNode extends RootNode {
+        @SuppressWarnings("deprecation")
         InteropRootNode() {
             super(TruffleRLanguage.class, null, null);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index e1824bbccb..c9437d56e4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -562,6 +562,7 @@ public final class ValuePrinterNode extends RBaseNode {
         ValuePrinters.printNewLine(printCtx);
     }
 
+    @SuppressWarnings("deprecation")
     public static String prettyPrint(final Object value) {
         return (String) Truffle.getRuntime().createCallTarget(new RootNode(TruffleLanguage.class, null, null) {
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index 9cc658a9ea..9b512143f7 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -82,6 +82,7 @@ public class TestCasts extends TestBase {
         private boolean isCompiled = false;
         @Child protected T node;
 
+        @SuppressWarnings("deprecation")
         protected TestRootNode(String name, T node) {
             super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.INTERNAL, descriptor);
             this.name = name;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
index 80bf53c93e..2785376e2c 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -192,6 +192,7 @@ public class TestUtilities {
         private final NodeAdapter<T> invoke;
         @Child private T node;
 
+        @SuppressWarnings("deprecation")
         TestRoot(T node, NodeAdapter<T> invoke) {
             super(TruffleLanguage.class, null, null);
             this.node = node;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
index d04204e0e3..f1ed9c1896 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
@@ -47,6 +47,7 @@ public abstract class RRootNode extends RootNode implements HasSignature {
 
     private FastPathFactory fastPath;
 
+    @SuppressWarnings("deprecation")
     protected RRootNode(FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
         super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.SOURCE_UNAVAILABLE, frameDescriptor);
         this.fastPath = fastPath;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
index 475f51bdfd..f1420a80ce 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
@@ -47,6 +47,7 @@ public final class FFIUpCallRootNode extends RootNode {
     @Child private FFIUpCallNode theFFIUpCallNode;
     private final int numArgs;
 
+    @SuppressWarnings("deprecation")
     private FFIUpCallRootNode(FFIUpCallNode child) {
         super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
         theFFIUpCallNode = child;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index b4a193b8fa..7866245493 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -35,7 +35,6 @@ import java.util.concurrent.Semaphore;
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.ExecutionContext;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
@@ -97,7 +96,8 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  *
  * Contexts can be destroyed
  */
-public final class RContext extends ExecutionContext {
+@SuppressWarnings("deprecation")
+public final class RContext extends com.oracle.truffle.api.ExecutionContext {
 
     public static final int CONSOLE_WIDTH = 80;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
index 2ed4032233..c7c9a3819d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
@@ -26,8 +26,6 @@ import com.oracle.truffle.api.dsl.ImplicitCast;
 import com.oracle.truffle.api.dsl.TypeCast;
 import com.oracle.truffle.api.dsl.TypeCheck;
 import com.oracle.truffle.api.dsl.TypeSystem;
-import com.oracle.truffle.api.dsl.internal.DSLOptions;
-import com.oracle.truffle.api.dsl.internal.DSLOptions.DSLGenerator;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -68,7 +66,6 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
                 RAbstractContainer.class,
                 RArgsValuesAndNames.class
 })
-@DSLOptions(defaultGenerator = DSLGenerator.FLAT)
 public class RTypes {
 
     @TypeCheck(RNull.class)
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index a536479f99..2bb5d9a64a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -581,6 +581,7 @@ public class DLL {
 
         @Child RFindSymbolNode findSymbolNode = RFindSymbolNode.create();
 
+        @SuppressWarnings("deprecation")
         private RFindSymbolRootNode() {
             super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java
index 71d8f98278..d6b8451a81 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 public abstract class RFFIRootNode<T extends Node> extends RootNode {
     @Child T rffiNode;
 
+    @SuppressWarnings("deprecation")
     protected RFFIRootNode(T baseRFFINode) {
         super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
         this.rffiNode = baseRFFINode;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
index 93c1f23711..27203104d2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
@@ -78,6 +78,7 @@ public final class UserRNG implements RandomNumberGenerator {
     private abstract static class UserRNGRootNodeAdapter extends RootNode {
         @Child protected UserRngRFFI.UserRngRFFINode userRngRFFINode = RFFIFactory.getRFFI().getUserRngRFFI().createUserRngRFFINode();
 
+        @SuppressWarnings("deprecation")
         protected UserRNGRootNodeAdapter() {
             super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
         }
-- 
GitLab


From 080620fc00f0043b56a4923c1e1b5742adf0ff3d Mon Sep 17 00:00:00 2001
From: Gilles Duboscq <gilles.m.duboscq@oracle.com>
Date: Mon, 24 Apr 2017 22:58:32 +0200
Subject: [PATCH 319/402] Update truffle import

---
 mx.fastr/suite.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 3fa9349077..1e31f049ba 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "f19ebf4be9550d744f8c431cc466a5f87682f9c4",
+               "version" : "01a039cbfc6238fd78d9159292495f93d6428f2a",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From 491edc7dd62ca14b4000cb81f1dd376b16cd73e9 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 24 Apr 2017 18:33:13 +0200
Subject: [PATCH 320/402] Added caching nodes for special subset/subscript
 nodes to have separate instances for each vector type.

---
 .../builtin/base/infix/SpecialsUtils.java     | 191 ++++++++++++++++++
 .../r/nodes/builtin/base/infix/Subscript.java |  38 ++--
 .../r/nodes/builtin/base/infix/Subset.java    |  17 +-
 3 files changed, 222 insertions(+), 24 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 14eb27121a..cd5ba86cbc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -25,9 +25,11 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ValueProfile;
@@ -35,6 +37,10 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertValueNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecialNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecialNodeGen;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
@@ -52,6 +58,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * @see com.oracle.truffle.r.runtime.builtins.RSpecialFactory
  */
 class SpecialsUtils {
+
     private static final String valueArgName = "value".intern();
 
     public static boolean isCorrectUpdateSignature(ArgumentsSignature signature) {
@@ -63,6 +70,169 @@ class SpecialsUtils {
         return false;
     }
 
+    @NodeChild(value = "vector", type = RNode.class)
+    @NodeChild(value = "index", type = ConvertIndex.class)
+    protected abstract static class ProfiledSubscriptSpecialBase extends SubscriptSpecialCommon {
+
+        protected static final int CACHE_LIMIT = 3;
+
+        @Child protected SubscriptSpecialBase defaultAccessNode;
+
+        protected ProfiledSubscriptSpecialBase(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        protected SubscriptSpecialBase createAccessNode() {
+            return null;
+        }
+
+        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
+        public Object access(VirtualFrame frame, RAbstractVector vector, int index, @Cached(value = "vector.getClass()") Class<?> clazz,
+                        @Cached("createAccessNode()") SubscriptSpecialBase accessNodeCached) {
+            return accessNodeCached.execute(frame, clazz.cast(vector), index);
+        }
+
+        @Fallback
+        public Object accessGeneric(VirtualFrame frame, Object vector, Object index) {
+            if (defaultAccessNode == null) {
+                defaultAccessNode = insert(createAccessNode());
+            }
+            return defaultAccessNode.execute(frame, vector, index);
+        }
+    }
+
+    public abstract static class ProfiledSubscriptSpecial extends ProfiledSubscriptSpecialBase {
+
+        protected ProfiledSubscriptSpecial(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecialBase createAccessNode() {
+            return SubscriptSpecialNodeGen.create(inReplacement);
+        }
+
+        public static ProfiledSubscriptSpecial create(boolean inReplacement, SubscriptSpecial accessNode, RNode vectorNode, ConvertIndex indexNode) {
+            return ProfiledSubscriptSpecialNodeGen.create(inReplacement, accessNode, vectorNode, indexNode);
+        }
+
+    }
+
+    public abstract static class ProfiledSubsetSpecial extends ProfiledSubscriptSpecialBase {
+
+        @Child protected SubsetSpecial accessNode;
+
+        protected ProfiledSubsetSpecial(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecialBase createAccessNode() {
+            return SubsetSpecialNodeGen.create(inReplacement);
+        }
+
+        public static ProfiledSubsetSpecial create(boolean inReplacement, SubsetSpecial accessNode, RNode vectorNode, ConvertIndex indexNode) {
+            return ProfiledSubsetSpecialNodeGen.create(inReplacement, accessNode, vectorNode, indexNode);
+        }
+
+    }
+
+    @NodeChild(value = "vector", type = RNode.class)
+    @NodeChild(value = "index1", type = ConvertIndex.class)
+    @NodeChild(value = "index2", type = ConvertIndex.class)
+    protected abstract static class ProfiledSubscriptSpecial2Base extends SubscriptSpecialCommon {
+
+        protected static final int CACHE_LIMIT = 3;
+
+        @Child protected SubscriptSpecial2Base defaultAccessNode;
+
+        protected ProfiledSubscriptSpecial2Base(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        protected SubscriptSpecial2Base createAccessNode() {
+            return null;
+        }
+
+        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
+        public Object access(VirtualFrame frame, RAbstractVector vector, int index1, int index2, @Cached("vector.getClass()") Class<?> clazz,
+                        @Cached("createAccessNode()") SubscriptSpecial2Base accessNodeCached) {
+            return accessNodeCached.execute(frame, clazz.cast(vector), index1, index2);
+        }
+
+        @Fallback
+        public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2) {
+            if (defaultAccessNode == null) {
+                defaultAccessNode = insert(createAccessNode());
+            }
+            return defaultAccessNode.execute(frame, vector, index1, index2);
+        }
+    }
+
+    public abstract static class ProfiledSubscriptSpecial2 extends ProfiledSubscriptSpecial2Base {
+
+        @Child protected SubscriptSpecial2 accessNode;
+
+        protected ProfiledSubscriptSpecial2(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecial2Base createAccessNode() {
+            return SubscriptSpecial2NodeGen.create(inReplacement);
+        }
+
+        public static ProfiledSubscriptSpecial2 create(boolean inReplacement, SubscriptSpecial2 accessNode, RNode vectorNode, ConvertIndex indexNode1, ConvertIndex indexNode2) {
+            return ProfiledSubscriptSpecial2NodeGen.create(inReplacement, accessNode, vectorNode, indexNode1, indexNode2);
+        }
+    }
+
+    public abstract static class ProfiledSubsetSpecial2 extends ProfiledSubscriptSpecial2Base {
+
+        @Child protected SubsetSpecial2 accessNode;
+
+        protected ProfiledSubsetSpecial2(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecial2Base createAccessNode() {
+            return SubsetSpecial2NodeGen.create(inReplacement);
+        }
+
+        public static ProfiledSubsetSpecial2 create(boolean inReplacement, SubsetSpecial2 accessNode, RNode vectorNode, ConvertIndex indexNode1, ConvertIndex indexNode2) {
+            return ProfiledSubsetSpecial2NodeGen.create(inReplacement, accessNode, vectorNode, indexNode1, indexNode2);
+        }
+    }
+
+    /**
+     * Common code shared between specials doing subset/subscript related operation.
+     */
+    abstract static class SubscriptSpecialCommon1 extends Node {
+
+        protected final boolean inReplacement;
+
+        protected SubscriptSpecialCommon1(boolean inReplacement) {
+            this.inReplacement = inReplacement;
+        }
+
+        /**
+         * Checks whether the given (1-based) index is valid for the given vector.
+         */
+        protected static boolean isValidIndex(RAbstractVector vector, int index) {
+            return index >= 1 && index <= vector.getLength();
+        }
+
+        /**
+         * Checks if the value is single element that can be put into a list or vector as is,
+         * because in the case of vectors on the LSH of update we take each element and put it into
+         * the RHS of the update function.
+         */
+        protected static boolean isSingleElement(Object value) {
+            return value instanceof Integer || value instanceof Double || value instanceof Byte || value instanceof String;
+        }
+    }
+
     /**
      * Common code shared between specials doing subset/subscript related operation.
      */
@@ -112,6 +282,27 @@ class SpecialsUtils {
         }
     }
 
+    abstract static class SubscriptSpecial2Common1 extends SubscriptSpecialCommon1 {
+
+        protected SubscriptSpecial2Common1(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Child private GetDimAttributeNode getDimensions = GetDimAttributeNode.create();
+
+        protected int matrixIndex(RAbstractVector vector, int index1, int index2) {
+            return index1 - 1 + ((index2 - 1) * getDimensions.getDimensions(vector)[0]);
+        }
+
+        /**
+         * Checks whether the given (1-based) indexes are valid for the given matrix.
+         */
+        protected boolean isValidIndex(RAbstractVector vector, int index1, int index2) {
+            int[] dimensions = getDimensions.getDimensions(vector);
+            return dimensions != null && dimensions.length == 2 && index1 >= 1 && index1 <= dimensions[0] && index2 >= 1 && index2 <= dimensions[1];
+        }
+    }
+
     /**
      * Common code shared between specials accessing/updating fields.
      */
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 6a4401c32b..e18973884c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -23,14 +23,12 @@
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
-import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -39,9 +37,10 @@ import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubscriptSpecial;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubscriptSpecial2;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common1;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon1;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -65,9 +64,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 /**
  * Subscript code for vectors minus list is the same as subset code, this class allows sharing it.
  */
-@NodeChild(value = "vector", type = ProfiledValue.class)
-@NodeChild(value = "index", type = ConvertIndex.class)
-abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
+abstract class SubscriptSpecialBase extends SubscriptSpecialCommon1 {
 
     protected SubscriptSpecialBase(boolean inReplacement) {
         super(inReplacement);
@@ -75,6 +72,8 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
 
     @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
 
+    protected abstract Object execute(VirtualFrame frame, Object vec, Object index);
+
     protected boolean simpleVector(RAbstractVector vector) {
         return classHierarchy.execute(vector) == null;
     }
@@ -104,10 +103,7 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
 /**
  * Subscript code for matrices minus list is the same as subset code, this class allows sharing it.
  */
-@NodeChild(value = "vector", type = ProfiledValue.class)
-@NodeChild(value = "index1", type = ConvertIndex.class)
-@NodeChild(value = "index2", type = ConvertIndex.class)
-abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common {
+abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common1 {
 
     protected SubscriptSpecial2Base(boolean inReplacement) {
         super(inReplacement);
@@ -115,11 +111,7 @@ abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common {
 
     @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
 
-    protected abstract ProfiledValue getVector();
-
-    protected abstract ConvertIndex getIndex1();
-
-    protected abstract ConvertIndex getIndex2();
+    public abstract Object execute(VirtualFrame frame, Object vector, Object index1, Object index2);
 
     protected boolean simpleVector(RAbstractVector vector) {
         return classHierarchy.execute(vector) == null;
@@ -168,6 +160,10 @@ abstract class SubscriptSpecial extends SubscriptSpecialBase {
                     @Cached("createAccess()") ExtractVectorNode extract) {
         return extract.apply(frame, vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE);
     }
+
+    public static RNode create(boolean inReplacement, RNode profiledVector, ConvertIndex index) {
+        return ProfiledSubscriptSpecial.create(inReplacement, SubscriptSpecialNodeGen.create(inReplacement), profiledVector, index);
+    }
 }
 
 abstract class SubscriptSpecial2 extends SubscriptSpecial2Base {
@@ -181,6 +177,10 @@ abstract class SubscriptSpecial2 extends SubscriptSpecial2Base {
                     @Cached("create()") ExtractListElement extract) {
         return extract.execute(vector, matrixIndex(vector, index1, index2));
     }
+
+    public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index1, ConvertIndex index2) {
+        return ProfiledSubscriptSpecial2.create(inReplacement, SubscriptSpecial2NodeGen.create(inReplacement), vectorNode, index1, index2);
+    }
 }
 
 @RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
@@ -199,9 +199,9 @@ public abstract class Subscript extends RBuiltinNode.Arg4 {
     public static RNode special(ArgumentsSignature signature, RNode[] arguments, boolean inReplacement) {
         if (signature.getNonNullCount() == 0) {
             if (arguments.length == 2) {
-                return SubscriptSpecialNodeGen.create(inReplacement, profile(arguments[0]), convertIndex(arguments[1]));
+                return SubscriptSpecial.create(inReplacement, arguments[0], convertIndex(arguments[1]));
             } else if (arguments.length == 3) {
-                return SubscriptSpecial2NodeGen.create(inReplacement, profile(arguments[0]), convertIndex(arguments[1]), convertIndex(arguments[2]));
+                return SubscriptSpecial2.create(inReplacement, arguments[0], convertIndex(arguments[1]), convertIndex(arguments[2]));
             }
         }
         return null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index 18cafe6488..1662c36e29 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
-import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -37,7 +36,8 @@ import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubsetSpecial;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubsetSpecial2;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -82,6 +82,10 @@ abstract class SubsetSpecial extends SubscriptSpecialBase {
                     @Cached("createAccess()") ExtractVectorNode extract) {
         return extract.apply(frame, vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE);
     }
+
+    public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index) {
+        return ProfiledSubsetSpecial.create(inReplacement, null, vectorNode, index);
+    }
 }
 
 /**
@@ -106,6 +110,10 @@ abstract class SubsetSpecial2 extends SubscriptSpecial2Base {
                     @Cached("create()") ExtractListElement extract) {
         return RDataFactory.createList(new Object[]{extract.execute(vector, matrixIndex(vector, index1, index2))});
     }
+
+    public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index1, ConvertIndex index2) {
+        return ProfiledSubsetSpecial2.create(inReplacement, null, vectorNode, index1, index2);
+    }
 }
 
 @RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
@@ -118,12 +126,11 @@ public abstract class Subset extends RBuiltinNode.Arg3 {
 
     public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) {
         if (signature.getNonNullCount() == 0 && (args.length == 2 || args.length == 3)) {
-            ProfiledValue profiledVector = profile(args[0]);
             ConvertIndex index = convertIndex(args[1]);
             if (args.length == 2) {
-                return SubsetSpecialNodeGen.create(inReplacement, profiledVector, index);
+                return SubsetSpecial.create(inReplacement, args[0], index);
             } else {
-                return SubsetSpecial2NodeGen.create(inReplacement, profiledVector, index, convertIndex(args[2]));
+                return SubsetSpecial2.create(inReplacement, args[0], index, convertIndex(args[2]));
             }
         }
         return null;
-- 
GitLab


From 110cfe738c549d852ac14666a926ff25ac67004f Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Mon, 24 Apr 2017 17:51:07 +0200
Subject: [PATCH 321/402] The StackOverflowError issue fixed in the Substitute
 builtin

---
 .../oracle/truffle/r/runtime/RSubstitute.java | 21 +++++++++++++++----
 .../truffle/r/test/ExpectedTestOutput.test    |  4 ++++
 .../r/test/functions/TestFunctions.java       |  2 ++
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
index 21a0d9b77a..aa4108bd03 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,9 +87,11 @@ public class RSubstitute {
      * <li>..., replace by contents of ... (if bound)</li>
      * </ul>
      */
-    private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment env) {
+    private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment callEnv) {
         return new RSyntaxVisitor<T>() {
 
+            REnvironment env = callEnv;
+
             @Override
             protected T visit(RSyntaxCall element) {
                 RSyntaxElement lhs = element.getSyntaxLHS();
@@ -134,8 +136,19 @@ public class RSubstitute {
                                 }
                                 RArgsValuesAndNames dots = (RArgsValuesAndNames) substitute;
                                 for (int j = 0; j < dots.getLength(); j++) {
-                                    RSyntaxElement contents = substituteElement(dots.getArgument(j));
-                                    args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents)));
+                                    Object dotArg = dots.getArgument(j);
+                                    RSyntaxElement contents = substituteElement(dotArg);
+                                    if (dotArg instanceof RPromise) {
+                                        // Replace the environment used to substitute symbols in a
+                                        // promise by the empty one to prevent an infinite recursion
+                                        // if the promise contains a vararg
+                                        REnvironment origEnv = env;
+                                        env = REnvironment.emptyEnv();
+                                        args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents)));
+                                        env = origEnv;
+                                    } else {
+                                        args.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, dots.getSignature().getName(j), accept(contents)));
+                                    }
                                 }
                                 continue;
                             }
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 492004a017..bb6efbdeb0 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
@@ -76378,6 +76378,10 @@ Error in f(10) : ..1 used in an incorrect context, no ... to look in
 [1] FALSE
 [1] "bar"
 
+##com.oracle.truffle.r.test.functions.TestFunctions.testDots#
+#{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat("Here:"); f1(f2(a, ...)) }; f1(f3("aaa")) }
+Here:[1] TRUE
+
 ##com.oracle.truffle.r.test.functions.TestFunctions.testDots#
 #{ f<-function(...) print(attributes(list(...))); f(a=7) }
 $names
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
index c2ad5d4250..8265d0daad 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
@@ -341,6 +341,8 @@ public class TestFunctions extends TestBase {
         assertEval("{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ...,,,) } ; g(1) }");
         assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..2 + ..2 } ; f(1,,2) }");
         assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }");
+
+        assertEval("{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat(\"Here:\"); f1(f2(a, ...)) }; f1(f3(\"aaa\")) }");
     }
 
     @Test
-- 
GitLab


From 4d12e7e15e8f77577c200f34c923cfb41b7826bb Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Tue, 25 Apr 2017 10:41:05 +0200
Subject: [PATCH 322/402] Names quotified in deparse, if necessary

---
 .../src/com/oracle/truffle/r/runtime/RDeparse.java            | 2 +-
 .../src/com/oracle/truffle/r/test/ExpectedTestOutput.test     | 4 ++++
 .../oracle/truffle/r/test/builtins/TestBuiltin_deparse.java   | 2 ++
 3 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index b54a820393..9cd3ced303 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -893,7 +893,7 @@ public class RDeparse {
                 }
                 lbreak = linebreak(lbreak);
                 if (snames != null) {
-                    append(snames.getDataAt(i));
+                    append(quotify(snames.getDataAt(i), '\"'));
                     append(" = ");
                 }
                 appendValue(v.getDataAtAsObject(i));
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 bb6efbdeb0..07a17a4a94 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
@@ -17032,6 +17032,10 @@ Error in print(x, y) :
 #deparse(c(T, F))
 [1] "c(TRUE, FALSE)"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#
+#deparse(list(`x y`=1))
+[1] "structure(list(\"x y\" = 1), .Names = \"x y\")"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_deparse.testDeparse#
 #deparse(quote(1/0))
 [1] "1/0"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
index 04bb15c4d3..41c068ab4a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deparse.java
@@ -317,6 +317,8 @@ public class TestBuiltin_deparse extends TestBase {
         assertEval("deparse(quote(1/0))");
 
         assertEval("e <- quote(a <- 1); e[[3]] <- as.raw(c(1,6,9,254)); e");
+
+        assertEval("deparse(list(`x y`=1))");
     }
 
     @Test
-- 
GitLab


From ffc57072feaea1e4024c9f8ef5536b76a22dca11 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 24 Apr 2017 18:48:12 +0200
Subject: [PATCH 323/402] Cleanup

---
 .../builtin/base/infix/SpecialsUtils.java     | 27 +++----------------
 .../r/nodes/builtin/base/infix/Subscript.java |  8 +++---
 .../r/nodes/builtin/base/infix/Subset.java    |  8 +++---
 3 files changed, 11 insertions(+), 32 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index cd5ba86cbc..15ad550569 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -37,12 +37,9 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertValueNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecial2NodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecialNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecial2NodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecialNodeGen;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -83,7 +80,7 @@ class SpecialsUtils {
         }
 
         protected SubscriptSpecialBase createAccessNode() {
-            return null;
+            throw RInternalError.shouldNotReachHere();
         }
 
         @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
@@ -111,11 +108,6 @@ class SpecialsUtils {
         protected SubscriptSpecialBase createAccessNode() {
             return SubscriptSpecialNodeGen.create(inReplacement);
         }
-
-        public static ProfiledSubscriptSpecial create(boolean inReplacement, SubscriptSpecial accessNode, RNode vectorNode, ConvertIndex indexNode) {
-            return ProfiledSubscriptSpecialNodeGen.create(inReplacement, accessNode, vectorNode, indexNode);
-        }
-
     }
 
     public abstract static class ProfiledSubsetSpecial extends ProfiledSubscriptSpecialBase {
@@ -130,11 +122,6 @@ class SpecialsUtils {
         protected SubscriptSpecialBase createAccessNode() {
             return SubsetSpecialNodeGen.create(inReplacement);
         }
-
-        public static ProfiledSubsetSpecial create(boolean inReplacement, SubsetSpecial accessNode, RNode vectorNode, ConvertIndex indexNode) {
-            return ProfiledSubsetSpecialNodeGen.create(inReplacement, accessNode, vectorNode, indexNode);
-        }
-
     }
 
     @NodeChild(value = "vector", type = RNode.class)
@@ -151,7 +138,7 @@ class SpecialsUtils {
         }
 
         protected SubscriptSpecial2Base createAccessNode() {
-            return null;
+            throw RInternalError.shouldNotReachHere();
         }
 
         @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
@@ -181,10 +168,6 @@ class SpecialsUtils {
         protected SubscriptSpecial2Base createAccessNode() {
             return SubscriptSpecial2NodeGen.create(inReplacement);
         }
-
-        public static ProfiledSubscriptSpecial2 create(boolean inReplacement, SubscriptSpecial2 accessNode, RNode vectorNode, ConvertIndex indexNode1, ConvertIndex indexNode2) {
-            return ProfiledSubscriptSpecial2NodeGen.create(inReplacement, accessNode, vectorNode, indexNode1, indexNode2);
-        }
     }
 
     public abstract static class ProfiledSubsetSpecial2 extends ProfiledSubscriptSpecial2Base {
@@ -199,10 +182,6 @@ class SpecialsUtils {
         protected SubscriptSpecial2Base createAccessNode() {
             return SubsetSpecial2NodeGen.create(inReplacement);
         }
-
-        public static ProfiledSubsetSpecial2 create(boolean inReplacement, SubsetSpecial2 accessNode, RNode vectorNode, ConvertIndex indexNode1, ConvertIndex indexNode2) {
-            return ProfiledSubsetSpecial2NodeGen.create(inReplacement, accessNode, vectorNode, indexNode1, indexNode2);
-        }
     }
 
     /**
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index e18973884c..5e8621cc04 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -37,10 +37,10 @@ import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubscriptSpecial;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubscriptSpecial2;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common1;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon1;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecialNodeGen;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -162,7 +162,7 @@ abstract class SubscriptSpecial extends SubscriptSpecialBase {
     }
 
     public static RNode create(boolean inReplacement, RNode profiledVector, ConvertIndex index) {
-        return ProfiledSubscriptSpecial.create(inReplacement, SubscriptSpecialNodeGen.create(inReplacement), profiledVector, index);
+        return ProfiledSubscriptSpecialNodeGen.create(inReplacement, profiledVector, index);
     }
 }
 
@@ -179,7 +179,7 @@ abstract class SubscriptSpecial2 extends SubscriptSpecial2Base {
     }
 
     public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index1, ConvertIndex index2) {
-        return ProfiledSubscriptSpecial2.create(inReplacement, SubscriptSpecial2NodeGen.create(inReplacement), vectorNode, index1, index2);
+        return ProfiledSubscriptSpecial2NodeGen.create(inReplacement, vectorNode, index1, index2);
     }
 }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index 1662c36e29..e6d8a31377 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
@@ -36,8 +36,8 @@ import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubsetSpecial;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledSubsetSpecial2;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecialNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -84,7 +84,7 @@ abstract class SubsetSpecial extends SubscriptSpecialBase {
     }
 
     public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index) {
-        return ProfiledSubsetSpecial.create(inReplacement, null, vectorNode, index);
+        return ProfiledSubsetSpecialNodeGen.create(inReplacement, vectorNode, index);
     }
 }
 
@@ -112,7 +112,7 @@ abstract class SubsetSpecial2 extends SubscriptSpecial2Base {
     }
 
     public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index1, ConvertIndex index2) {
-        return ProfiledSubsetSpecial2.create(inReplacement, null, vectorNode, index1, index2);
+        return ProfiledSubsetSpecial2NodeGen.create(inReplacement, vectorNode, index1, index2);
     }
 }
 
-- 
GitLab


From 448a41d810a16e5a98f4a4588b0be006e5662768 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 25 Apr 2017 16:46:45 +0200
Subject: [PATCH 324/402] Restructured special subset/subscript implementation.

---
 .../base/infix/ProfiledSpecialsUtils.java     | 228 ++++++++++++++++++
 .../builtin/base/infix/SpecialsUtils.java     | 203 +---------------
 .../r/nodes/builtin/base/infix/Subscript.java |  26 +-
 .../r/nodes/builtin/base/infix/Subset.java    |   4 +-
 .../builtin/base/infix/UpdateSubscript.java   |  59 ++---
 .../builtin/base/infix/UpdateSubset.java      |   7 +-
 6 files changed, 269 insertions(+), 258 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
new file mode 100644
index 0000000000..fe6a876c60
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base.infix;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.NodeChild;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertValue;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+
+public class ProfiledSpecialsUtils {
+
+    @NodeChild(value = "vector", type = RNode.class)
+    @NodeChild(value = "index", type = ConvertIndex.class)
+    protected abstract static class ProfiledSubscriptSpecialBase extends RNode {
+
+        protected static final int CACHE_LIMIT = 3;
+        protected final boolean inReplacement;
+
+        @Child protected SubscriptSpecialBase defaultAccessNode;
+
+        protected ProfiledSubscriptSpecialBase(boolean inReplacement) {
+            this.inReplacement = inReplacement;
+        }
+
+        protected SubscriptSpecialBase createAccessNode() {
+            throw RInternalError.shouldNotReachHere();
+        }
+
+        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
+        public Object access(VirtualFrame frame, RAbstractVector vector, Object index,
+                        @Cached(value = "vector.getClass()") Class<?> clazz,
+                        @Cached("createAccessNode()") SubscriptSpecialBase accessNodeCached) {
+            return accessNodeCached.execute(frame, clazz.cast(vector), index);
+        }
+
+        @Specialization(replaces = "access")
+        public Object accessGeneric(VirtualFrame frame, Object vector, Object index) {
+            if (defaultAccessNode == null) {
+                defaultAccessNode = insert(createAccessNode());
+            }
+            return defaultAccessNode.execute(frame, vector, index);
+        }
+    }
+
+    public abstract static class ProfiledSubscriptSpecial extends ProfiledSubscriptSpecialBase {
+
+        protected ProfiledSubscriptSpecial(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecialBase createAccessNode() {
+            return SubscriptSpecialNodeGen.create(inReplacement);
+        }
+    }
+
+    public abstract static class ProfiledSubsetSpecial extends ProfiledSubscriptSpecialBase {
+
+        protected ProfiledSubsetSpecial(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecialBase createAccessNode() {
+            return SubsetSpecialNodeGen.create(inReplacement);
+        }
+    }
+
+    @NodeChild(value = "vector", type = RNode.class)
+    @NodeChild(value = "index1", type = ConvertIndex.class)
+    @NodeChild(value = "index2", type = ConvertIndex.class)
+    public abstract static class ProfiledSubscriptSpecial2Base extends RNode {
+
+        protected static final int CACHE_LIMIT = 3;
+        protected final boolean inReplacement;
+
+        @Child protected SubscriptSpecial2Base defaultAccessNode;
+
+        protected ProfiledSubscriptSpecial2Base(boolean inReplacement) {
+            this.inReplacement = inReplacement;
+        }
+
+        protected SubscriptSpecial2Base createAccessNode() {
+            throw RInternalError.shouldNotReachHere();
+        }
+
+        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
+        public Object access(VirtualFrame frame, RAbstractVector vector, Object index1, Object index2,
+                        @Cached("vector.getClass()") Class<?> clazz,
+                        @Cached("createAccessNode()") SubscriptSpecial2Base accessNodeCached) {
+            return accessNodeCached.execute(frame, clazz.cast(vector), index1, index2);
+        }
+
+        @Specialization(replaces = "access")
+        public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2) {
+            if (defaultAccessNode == null) {
+                defaultAccessNode = insert(createAccessNode());
+            }
+            return defaultAccessNode.execute(frame, vector, index1, index2);
+        }
+
+    }
+
+    public abstract static class ProfiledSubscriptSpecial2 extends ProfiledSubscriptSpecial2Base {
+
+        protected ProfiledSubscriptSpecial2(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecial2Base createAccessNode() {
+            return SubscriptSpecial2NodeGen.create(inReplacement);
+        }
+
+    }
+
+    public abstract static class ProfiledSubsetSpecial2 extends ProfiledSubscriptSpecial2Base {
+
+        protected ProfiledSubsetSpecial2(boolean inReplacement) {
+            super(inReplacement);
+        }
+
+        @Override
+        protected SubscriptSpecial2Base createAccessNode() {
+            return SubsetSpecial2NodeGen.create(inReplacement);
+        }
+    }
+
+    @NodeChild(value = "vector", type = RNode.class)
+    @NodeChild(value = "index", type = ConvertIndex.class)
+    @NodeChild(value = "value", type = ConvertValue.class)
+    public abstract static class ProfiledUpdateSubscriptSpecialBase extends RNode {
+
+        protected static final int CACHE_LIMIT = 3;
+        protected final boolean inReplacement;
+
+        public abstract Object execute(VirtualFrame frame, Object vector, Object index, Object value);
+
+        @Child protected UpdateSubscriptSpecial defaultAccessNode;
+
+        protected ProfiledUpdateSubscriptSpecialBase(boolean inReplacement) {
+            this.inReplacement = inReplacement;
+        }
+
+        protected UpdateSubscriptSpecial createAccessNode() {
+            return UpdateSubscriptSpecialNodeGen.create(inReplacement);
+        }
+
+        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
+        public Object access(VirtualFrame frame, Object vector, Object index, Object value,
+                        @Cached("vector.getClass()") Class<?> clazz,
+                        @Cached("createAccessNode()") UpdateSubscriptSpecial accessNodeCached) {
+            return accessNodeCached.execute(frame, clazz.cast(vector), index, value);
+        }
+
+        @Specialization(replaces = "access")
+        public Object accessGeneric(VirtualFrame frame, Object vector, Object index, Object value) {
+            if (defaultAccessNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                defaultAccessNode = insert(createAccessNode());
+            }
+            return defaultAccessNode.execute(frame, vector, index, value);
+        }
+    }
+
+    @NodeChild(value = "vector", type = RNode.class)
+    @NodeChild(value = "index1", type = ConvertIndex.class)
+    @NodeChild(value = "index2", type = ConvertIndex.class)
+    @NodeChild(value = "value", type = ConvertValue.class)
+    public abstract static class ProfiledUpdateSubscriptSpecial2 extends RNode {
+
+        protected static final int CACHE_LIMIT = 3;
+        protected final boolean inReplacement;
+
+        public abstract Object execute(VirtualFrame frame, Object vector, Object index1, Object index2, Object value);
+
+        @Child protected UpdateSubscriptSpecial2 defaultAccessNode;
+
+        protected ProfiledUpdateSubscriptSpecial2(boolean inReplacement) {
+            this.inReplacement = inReplacement;
+        }
+
+        protected UpdateSubscriptSpecial2 createAccessNode() {
+            return UpdateSubscriptSpecial2NodeGen.create(inReplacement);
+        }
+
+        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
+        public Object access(VirtualFrame frame, Object vector, Object index1, Object index2, Object value,
+                        @Cached("vector.getClass()") Class<?> clazz,
+                        @Cached("createAccessNode()") UpdateSubscriptSpecial2 accessNodeCached) {
+            return accessNodeCached.execute(frame, clazz.cast(vector), index1, index2, value);
+        }
+
+        @Specialization(replaces = "access")
+        public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2, Object value) {
+            if (defaultAccessNode == null) {
+                defaultAccessNode = insert(createAccessNode());
+            }
+            return defaultAccessNode.execute(frame, vector, index1, index2, value);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 15ad550569..569af73be2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -25,27 +25,23 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertValueNodeGen;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
+import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -67,155 +63,12 @@ class SpecialsUtils {
         return false;
     }
 
-    @NodeChild(value = "vector", type = RNode.class)
-    @NodeChild(value = "index", type = ConvertIndex.class)
-    protected abstract static class ProfiledSubscriptSpecialBase extends SubscriptSpecialCommon {
-
-        protected static final int CACHE_LIMIT = 3;
-
-        @Child protected SubscriptSpecialBase defaultAccessNode;
-
-        protected ProfiledSubscriptSpecialBase(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        protected SubscriptSpecialBase createAccessNode() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
-        public Object access(VirtualFrame frame, RAbstractVector vector, int index, @Cached(value = "vector.getClass()") Class<?> clazz,
-                        @Cached("createAccessNode()") SubscriptSpecialBase accessNodeCached) {
-            return accessNodeCached.execute(frame, clazz.cast(vector), index);
-        }
-
-        @Fallback
-        public Object accessGeneric(VirtualFrame frame, Object vector, Object index) {
-            if (defaultAccessNode == null) {
-                defaultAccessNode = insert(createAccessNode());
-            }
-            return defaultAccessNode.execute(frame, vector, index);
-        }
-    }
-
-    public abstract static class ProfiledSubscriptSpecial extends ProfiledSubscriptSpecialBase {
-
-        protected ProfiledSubscriptSpecial(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        @Override
-        protected SubscriptSpecialBase createAccessNode() {
-            return SubscriptSpecialNodeGen.create(inReplacement);
-        }
-    }
-
-    public abstract static class ProfiledSubsetSpecial extends ProfiledSubscriptSpecialBase {
-
-        @Child protected SubsetSpecial accessNode;
-
-        protected ProfiledSubsetSpecial(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        @Override
-        protected SubscriptSpecialBase createAccessNode() {
-            return SubsetSpecialNodeGen.create(inReplacement);
-        }
-    }
-
-    @NodeChild(value = "vector", type = RNode.class)
-    @NodeChild(value = "index1", type = ConvertIndex.class)
-    @NodeChild(value = "index2", type = ConvertIndex.class)
-    protected abstract static class ProfiledSubscriptSpecial2Base extends SubscriptSpecialCommon {
-
-        protected static final int CACHE_LIMIT = 3;
-
-        @Child protected SubscriptSpecial2Base defaultAccessNode;
-
-        protected ProfiledSubscriptSpecial2Base(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        protected SubscriptSpecial2Base createAccessNode() {
-            throw RInternalError.shouldNotReachHere();
-        }
-
-        @Specialization(limit = "CACHE_LIMIT", guards = "vector.getClass() == clazz")
-        public Object access(VirtualFrame frame, RAbstractVector vector, int index1, int index2, @Cached("vector.getClass()") Class<?> clazz,
-                        @Cached("createAccessNode()") SubscriptSpecial2Base accessNodeCached) {
-            return accessNodeCached.execute(frame, clazz.cast(vector), index1, index2);
-        }
-
-        @Fallback
-        public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2) {
-            if (defaultAccessNode == null) {
-                defaultAccessNode = insert(createAccessNode());
-            }
-            return defaultAccessNode.execute(frame, vector, index1, index2);
-        }
-    }
-
-    public abstract static class ProfiledSubscriptSpecial2 extends ProfiledSubscriptSpecial2Base {
-
-        @Child protected SubscriptSpecial2 accessNode;
-
-        protected ProfiledSubscriptSpecial2(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        @Override
-        protected SubscriptSpecial2Base createAccessNode() {
-            return SubscriptSpecial2NodeGen.create(inReplacement);
-        }
-    }
-
-    public abstract static class ProfiledSubsetSpecial2 extends ProfiledSubscriptSpecial2Base {
-
-        @Child protected SubsetSpecial2 accessNode;
-
-        protected ProfiledSubsetSpecial2(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        @Override
-        protected SubscriptSpecial2Base createAccessNode() {
-            return SubsetSpecial2NodeGen.create(inReplacement);
-        }
-    }
-
     /**
      * Common code shared between specials doing subset/subscript related operation.
      */
-    abstract static class SubscriptSpecialCommon1 extends Node {
-
-        protected final boolean inReplacement;
-
-        protected SubscriptSpecialCommon1(boolean inReplacement) {
-            this.inReplacement = inReplacement;
-        }
+    abstract static class SubscriptSpecialCommon extends Node {
 
-        /**
-         * Checks whether the given (1-based) index is valid for the given vector.
-         */
-        protected static boolean isValidIndex(RAbstractVector vector, int index) {
-            return index >= 1 && index <= vector.getLength();
-        }
-
-        /**
-         * Checks if the value is single element that can be put into a list or vector as is,
-         * because in the case of vectors on the LSH of update we take each element and put it into
-         * the RHS of the update function.
-         */
-        protected static boolean isSingleElement(Object value) {
-            return value instanceof Integer || value instanceof Double || value instanceof Byte || value instanceof String;
-        }
-    }
-
-    /**
-     * Common code shared between specials doing subset/subscript related operation.
-     */
-    abstract static class SubscriptSpecialCommon extends RNode {
+        @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
 
         protected final boolean inReplacement;
 
@@ -223,6 +76,10 @@ class SpecialsUtils {
             this.inReplacement = inReplacement;
         }
 
+        protected boolean simpleVector(RAbstractVector vector) {
+            return classHierarchy.execute(vector) == null;
+        }
+
         /**
          * Checks whether the given (1-based) index is valid for the given vector.
          */
@@ -261,27 +118,6 @@ class SpecialsUtils {
         }
     }
 
-    abstract static class SubscriptSpecial2Common1 extends SubscriptSpecialCommon1 {
-
-        protected SubscriptSpecial2Common1(boolean inReplacement) {
-            super(inReplacement);
-        }
-
-        @Child private GetDimAttributeNode getDimensions = GetDimAttributeNode.create();
-
-        protected int matrixIndex(RAbstractVector vector, int index1, int index2) {
-            return index1 - 1 + ((index2 - 1) * getDimensions.getDimensions(vector)[0]);
-        }
-
-        /**
-         * Checks whether the given (1-based) indexes are valid for the given matrix.
-         */
-        protected boolean isValidIndex(RAbstractVector vector, int index1, int index2) {
-            int[] dimensions = getDimensions.getDimensions(vector);
-            return dimensions != null && dimensions.length == 2 && index1 >= 1 && index1 <= dimensions[0] && index2 >= 1 && index2 <= dimensions[1];
-        }
-    }
-
     /**
      * Common code shared between specials accessing/updating fields.
      */
@@ -318,27 +154,6 @@ class SpecialsUtils {
         }
     }
 
-    @NodeInfo(cost = NodeCost.NONE)
-    public static final class ProfiledValue extends RBaseNode {
-
-        private final ValueProfile profile = ValueProfile.createClassProfile();
-
-        @Child private RNode delegate;
-
-        protected ProfiledValue(RNode delegate) {
-            this.delegate = delegate;
-        }
-
-        public Object execute(VirtualFrame frame) {
-            return profile.profile(delegate.execute(frame));
-        }
-
-        @Override
-        protected RSyntaxNode getRSyntaxNode() {
-            return delegate.asRSyntaxNode();
-        }
-    }
-
     @NodeInfo(cost = NodeCost.NONE)
     @NodeChild(value = "delegate", type = RNode.class)
     public abstract static class ConvertIndex extends RNode {
@@ -417,10 +232,6 @@ class SpecialsUtils {
         }
     }
 
-    public static ProfiledValue profile(RNode value) {
-        return new ProfiledValue(value);
-    }
-
     public static ConvertIndex convertIndex(RNode value) {
         return ConvertIndexNodeGen.create(value);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 5e8621cc04..113fccddad 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -36,13 +36,11 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubscriptSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubscriptSpecialNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common1;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon1;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecial2NodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubscriptSpecialNodeGen;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common;
+import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -64,20 +62,14 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 /**
  * Subscript code for vectors minus list is the same as subset code, this class allows sharing it.
  */
-abstract class SubscriptSpecialBase extends SubscriptSpecialCommon1 {
+abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
 
     protected SubscriptSpecialBase(boolean inReplacement) {
         super(inReplacement);
     }
 
-    @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
-
     protected abstract Object execute(VirtualFrame frame, Object vec, Object index);
 
-    protected boolean simpleVector(RAbstractVector vector) {
-        return classHierarchy.execute(vector) == null;
-    }
-
     @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
     protected int access(RAbstractIntVector vector, int index) {
         return vector.getDataAt(index - 1);
@@ -103,20 +95,14 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon1 {
 /**
  * Subscript code for matrices minus list is the same as subset code, this class allows sharing it.
  */
-abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common1 {
+abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common {
 
     protected SubscriptSpecial2Base(boolean inReplacement) {
         super(inReplacement);
     }
 
-    @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
-
     public abstract Object execute(VirtualFrame frame, Object vector, Object index1, Object index2);
 
-    protected boolean simpleVector(RAbstractVector vector) {
-        return classHierarchy.execute(vector) == null;
-    }
-
     @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
     protected int access(RAbstractIntVector vector, int index1, int index2) {
         return vector.getDataAt(matrixIndex(vector, index1, index2));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index e6d8a31377..6d6a04e16b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
@@ -35,9 +35,9 @@ import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubsetSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledSubsetSpecialNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecial2NodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ProfiledSubsetSpecialNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index e9d5efbbd2..9bc4b7371c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue;
-import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -32,20 +31,18 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledUpdateSubscriptSpecial2NodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.infix.ProfiledSpecialsUtilsFactory.ProfiledUpdateSubscriptSpecialBaseNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertValue;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecial2Common;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.SubscriptSpecialCommon;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -59,45 +56,38 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-@NodeChild(value = "vector", type = ProfiledValue.class)
-@NodeChild(value = "index", type = ConvertIndex.class)
-@NodeChild(value = "value", type = ConvertValue.class)
 abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
 
     protected UpdateSubscriptSpecial(boolean inReplacement) {
         super(inReplacement);
     }
 
-    @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
-
     private final NACheck naCheck = NACheck.create();
 
-    protected boolean simple(Object vector) {
-        return classHierarchy.execute(vector) == null;
-    }
+    protected abstract Object execute(VirtualFrame frame, Object vec, Object index, Object value);
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
     protected RIntVector set(RIntVector vector, int index, int value) {
         return vector.updateDataAt(index - 1, value, naCheck);
     }
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
     protected RDoubleVector set(RDoubleVector vector, int index, double value) {
         return vector.updateDataAt(index - 1, value, naCheck);
     }
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
     protected RStringVector set(RStringVector vector, int index, String value) {
         return vector.updateDataAt(index - 1, value, naCheck);
     }
 
-    @Specialization(guards = {"simple(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"})
+    @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"})
     protected static Object set(RList list, int index, Object value) {
         list.setDataAt(list.getInternalStore(), index - 1, value);
         return list;
     }
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index)"})
     protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index, int value) {
         return vector.updateDataAt(index - 1, value, naCheck);
     }
@@ -107,48 +97,44 @@ abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon {
     protected static Object setFallback(Object vector, Object index, Object value) {
         throw RSpecialFactory.throwFullCallNeeded(value);
     }
+
+    public static RNode create(boolean inReplacement, RNode vector, ConvertIndex index, ConvertValue value) {
+        return ProfiledUpdateSubscriptSpecialBaseNodeGen.create(inReplacement, vector, index, value);
+    }
 }
 
-@NodeChild(value = "vector", type = ProfiledValue.class)
-@NodeChild(value = "index1", type = ConvertIndex.class)
-@NodeChild(value = "index2", type = ConvertIndex.class)
-@NodeChild(value = "value", type = ConvertValue.class)
 abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
 
     protected UpdateSubscriptSpecial2(boolean inReplacement) {
         super(inReplacement);
     }
 
-    @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
-
     private final NACheck naCheck = NACheck.create();
 
-    protected boolean simple(Object vector) {
-        return classHierarchy.execute(vector) == null;
-    }
+    protected abstract Object execute(VirtualFrame frame, Object vec, Object index1, Object index2, Object value);
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
     protected RIntVector set(RIntVector vector, int index1, int index2, int value) {
         return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
     }
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
     protected RDoubleVector set(RDoubleVector vector, int index1, int index2, double value) {
         return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
     }
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
     protected RStringVector set(RStringVector vector, int index1, int index2, String value) {
         return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
     }
 
-    @Specialization(guards = {"simple(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"})
+    @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"})
     protected Object set(RList list, int index1, int index2, Object value) {
         list.setDataAt(list.getInternalStore(), matrixIndex(list, index1, index2), value);
         return list;
     }
 
-    @Specialization(guards = {"simple(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
+    @Specialization(guards = {"simpleVector(vector)", "!vector.isShared()", "isValidIndex(vector, index1, index2)"})
     protected RDoubleVector setDoubleIntIndexIntValue(RDoubleVector vector, int index1, int index2, int value) {
         return vector.updateDataAt(matrixIndex(vector, index1, index2), value, naCheck);
     }
@@ -158,6 +144,10 @@ abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common {
     protected static Object setFallback(Object vector, Object index1, Object index2, Object value) {
         throw RSpecialFactory.throwFullCallNeeded(value);
     }
+
+    public static RNode create(boolean inReplacement, RNode vector, ConvertIndex index1, ConvertIndex index2, ConvertValue value) {
+        return ProfiledUpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index1, index2, value);
+    }
 }
 
 @RBuiltin(name = "[[<-", kind = PRIMITIVE, parameterNames = {"", "..."}, dispatch = INTERNAL_GENERIC, behavior = PURE)
@@ -173,12 +163,11 @@ public abstract class UpdateSubscript extends RBuiltinNode.Arg2 {
 
     public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) {
         if (SpecialsUtils.isCorrectUpdateSignature(signature) && (args.length == 3 || args.length == 4)) {
-            ProfiledValue vector = profile(args[0]);
             ConvertIndex index = convertIndex(args[1]);
             if (args.length == 3) {
-                return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, convertValue(args[2]));
+                return UpdateSubscriptSpecial.create(inReplacement, args[0], index, convertValue(args[2]));
             } else {
-                return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), convertValue(args[3]));
+                return UpdateSubscriptSpecial2.create(inReplacement, args[0], index, convertIndex(args[2]), convertValue(args[3]));
             }
         }
         return null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index 450506ba10..bb734f4ae2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertValue;
-import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.profile;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -38,7 +37,6 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ConvertIndex;
-import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.ProfiledValue;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -58,12 +56,11 @@ public abstract class UpdateSubset extends RBuiltinNode.Arg1 {
 
     public static RNode special(ArgumentsSignature signature, RNode[] args, boolean inReplacement) {
         if (SpecialsUtils.isCorrectUpdateSignature(signature) && (args.length == 3 || args.length == 4)) {
-            ProfiledValue vector = profile(args[0]);
             ConvertIndex index = convertIndex(args[1]);
             if (args.length == 3) {
-                return UpdateSubscriptSpecialNodeGen.create(inReplacement, vector, index, convertValue(args[2]));
+                return UpdateSubscriptSpecial.create(inReplacement, args[0], index, convertValue(args[2]));
             } else {
-                return UpdateSubscriptSpecial2NodeGen.create(inReplacement, vector, index, convertIndex(args[2]), convertValue(args[3]));
+                return UpdateSubscriptSpecial2.create(inReplacement, args[0], index, convertIndex(args[2]), convertValue(args[3]));
             }
         }
         return null;
-- 
GitLab


From c7a98a81e3e7cd502bc62f4a69099d4a28f8b815 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 20 Apr 2017 17:02:10 -0700
Subject: [PATCH 325/402] Enable FastR to run in 'managed code only' mode

* Add @TruffleBoundaries to File/Fifo Connections
* Means to disable AWT support in FastR Grid implementation
* Means to turns off loading of native code of builtin packages.
* Managed implementation/mock of RFFIFactory
---
 .../com/oracle/truffle/r/engine/REngine.java  |   2 +-
 .../r/engine/RRuntimeASTAccessImpl.java       |   3 +
 .../r/library/fastrGrid/GridContext.java      |   9 +-
 .../r/library/fastrGrid/WindowDevice.java     |   6 +
 .../grDevices/InitWindowedDevice.java         |   7 +
 .../truffle/r/library/graphics/RGraphics.java |   2 +-
 .../truffle/r/library/utils/CountFields.java  |   2 +-
 com.oracle.truffle.r.native/Makefile          |   4 +
 com.oracle.truffle.r.native/fficall/Makefile  |   9 +
 .../library/base/Makefile                     |  23 +-
 .../builtin/EagerResourceHandlerFactory.java  | 156 ++++++++++++
 .../r/nodes/builtin/RBuiltinPackages.java     |  11 +-
 .../r/nodes/builtin/base/BasePackage.java     |   4 +
 .../oracle/truffle/r/runtime/FastRConfig.java |  47 ++++
 .../truffle/r/runtime/FastROptions.java       |   3 +-
 ...y.java => LazyResourceHandlerFactory.java} |   2 +-
 .../oracle/truffle/r/runtime/REnvVars.java    |   5 +-
 .../com/oracle/truffle/r/runtime/RError.java  |   1 +
 .../r/runtime/ResourceHandlerFactory.java     |  11 +-
 .../truffle/r/runtime/TempPathName.java       |   1 +
 .../r/runtime/conn/FifoConnections.java       |   3 +
 .../r/runtime/conn/FileConnections.java       |   4 +
 .../r/runtime/conn/SocketConnections.java     |   2 +
 .../r/runtime/data/ObjectSizeFactory.java     |  12 +-
 .../runtime/data/SimpleObjectSizeFactory.java |  87 +++++++
 .../truffle/r/runtime/ffi/RFFIFactory.java    |   5 +
 .../runtime/ffi/managed/FilesystemUtils.java  |  41 ++++
 .../r/runtime/ffi/managed/Managed_Base.java   | 185 ++++++++++++++
 .../ffi/managed/Managed_LapackRFFI.java       |  94 +++++++
 .../runtime/ffi/managed/Managed_PCRERFFI.java |  59 +++++
 .../ffi/managed/Managed_REmbedRFFI.java       |  54 ++++
 .../ffi/managed/Managed_RFFIFactory.java      | 232 ++++++++++++++++++
 documentation/dev/ffi.md                      |   7 +-
 documentation/dev/managed_ffi.md              |  25 ++
 34 files changed, 1100 insertions(+), 18 deletions(-)
 create mode 100644 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
 rename com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/{DefaultResourceHandlerFactory.java => LazyResourceHandlerFactory.java} (98%)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
 create mode 100644 documentation/dev/managed_ffi.md

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index 73a6b694ca..391ae348f8 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -162,7 +162,7 @@ final class REngine implements Engine, Engine.Timings {
         REnvironment.baseInitialize(baseFrame, globalFrame);
         RBuiltinPackages.loadBase(baseFrame);
         RGraphics.initialize();
-        if (FastROptions.LoadBase.getBooleanValue()) {
+        if (FastROptions.LoadProfiles.getBooleanValue()) {
             /*
              * eval the system/site/user profiles. Experimentally GnuR does not report warnings
              * during system profile evaluation, but does for the site/user profiles.
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index ad2140fbde..a5d042faf3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -561,16 +561,19 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     }
 
     @Override
+    @TruffleBoundary
     public boolean enableDebug(RFunction func, boolean once) {
         return DebugHandling.enableDebug(func, "", RNull.instance, once, false);
     }
 
     @Override
+    @TruffleBoundary
     public boolean isDebugged(RFunction func) {
         return DebugHandling.isDebugged(func);
     }
 
     @Override
+    @TruffleBoundary
     public boolean disableDebug(RFunction func) {
         return DebugHandling.undebug(func);
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index 54a33fec0b..a2c92c4c53 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid;
 
+import static com.oracle.truffle.r.library.fastrGrid.WindowDevice.awtNotSupported;
+
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -29,6 +31,7 @@ import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
 import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
+import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -89,7 +92,11 @@ public final class GridContext {
     public void openDefaultDevice() {
         String defaultDev = RGridGraphicsAdapter.getDefaultDevice();
         if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) {
-            setCurrentDevice(defaultDev, WindowDevice.createWindowDevice());
+            if (!FastRConfig.InternalGridAwtSupport) {
+                throw awtNotSupported();
+            } else {
+                setCurrentDevice(defaultDev, WindowDevice.createWindowDevice());
+            }
         } else {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'.");
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
index 4ae0265a38..6183981d46 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.library.fastrGrid;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 
 /**
  * Contains code specific to FastR device that shows the graphical output interactively in a window.
@@ -42,4 +44,8 @@ public final class WindowDevice {
         JFrameDevice frameDevice = JFrameDevice.create(width, height);
         return new BufferedJFrameDevice(frameDevice);
     }
+
+    public static RError awtNotSupported() {
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, "AWT based grid devices are not supported.");
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 1fdc13be74..9825b273c1 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.library.fastrGrid.grDevices;
 
+import static com.oracle.truffle.r.library.fastrGrid.WindowDevice.awtNotSupported;
+
 import java.awt.Graphics2D;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -34,6 +36,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.Graphics2DDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -54,6 +57,10 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
     @Override
     @TruffleBoundary
     protected Object call(RArgsValuesAndNames args) {
+        if (!FastRConfig.InternalGridAwtSupport) {
+            throw awtNotSupported();
+        }
+
         int width = getIntOrDefault(args, 1, GridDevice.DEFAULT_WIDTH);
         int height = getIntOrDefault(args, 2, GridDevice.DEFAULT_HEIGHT);
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
index 4f635579bc..657822c217 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
@@ -34,7 +34,7 @@ public class RGraphics {
         if (initialized.compareAndSet(false, true)) {
             if (FastROptions.UseInternalGridGraphics.getBooleanValue()) {
                 RGridGraphicsAdapter.initialize();
-            } else {
+            } else if (FastROptions.LoadPackagesNativeCode.getBooleanValue()) {
                 DLL.DLLInfo dllInfo = DLL.findLibraryContainingSymbol("InitGraphics");
                 DLL.SymbolHandle symbolHandle = DLL.findSymbol("InitGraphics", dllInfo);
                 assert symbolHandle != DLL.SYMBOL_NOT_FOUND;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
index b3405af7d8..bf6252a67e 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java
@@ -65,6 +65,7 @@ public abstract class CountFields extends RExternalBuiltinNode.Arg6 {
     }
 
     @Specialization
+    @TruffleBoundary
     protected Object count(int conn, Object sep, Object quote, int nskipArg, boolean blskip, String commentCharArg) {
         char comChar;
         if (!(commentCharArg != null && commentCharArg.length() == 1)) {
@@ -104,7 +105,6 @@ public abstract class CountFields extends RExternalBuiltinNode.Arg6 {
         }
     }
 
-    @TruffleBoundary
     private static Object countFields(RConnection file, char sepChar, String quoteSet, @SuppressWarnings("unused") int nskip, boolean blskip, char comChar) throws IOException {
         LocalData data = new LocalData();
         data.sepchar = sepChar;
diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index fae4e67969..69ba9ce186 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -31,8 +31,12 @@ export R_VERSION = $(subst R-,,$(notdir $(basename $(basename $(wildcard $(FASTR
 export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION)
 
 ifndef FASTR_RFFI
+ifeq ($(FASTR_MANAGED),true)
+export FASTR_RFFI = managed
+else
 export FASTR_RFFI = jni
 endif
+endif
 
 # Completely accurate dependency analysis is very difficult for this project, so use a version number
 # to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the 
diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile
index 47d879c4c0..68f128ec2b 100644
--- a/com.oracle.truffle.r.native/fficall/Makefile
+++ b/com.oracle.truffle.r.native/fficall/Makefile
@@ -56,6 +56,9 @@ all: $(R_LIB)
 # to remove the sentinels
 
 $(R_LIB): fficall.done 
+ifeq ($(FASTR_RFFI),managed)
+	# nop
+else
 ifeq ($(OS_NAME),Darwin)
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack  -lpcre -lz $(VERSION_FLAGS)
 	install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB)
@@ -66,7 +69,12 @@ ifeq ($(OS_NAME),Darwin)
 else
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) $(shell echo $(PKG_LDFLAGS_OVERRIDE)) -Wl,-rpath,'$$ORIGIN' -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack  -lpcre -lz
 endif
+endif # managed
 
+ifeq ($(FASTR_RFFI),managed)
+fficall.done: common.done
+	touch fficall.done
+else
 ifeq ($(FASTR_RFFI),nfi)
 fficall.done: common.done
 	$(MAKE) -C src/truffle_nfi all
@@ -96,6 +104,7 @@ endif
 	touch fficall.done
 endif
 endif
+endif
 
 common.done:
 	$(MAKE) -C src/common all	
diff --git a/com.oracle.truffle.r.native/library/base/Makefile b/com.oracle.truffle.r.native/library/base/Makefile
index 6e57a6d587..f4077b8f23 100644
--- a/com.oracle.truffle.r.native/library/base/Makefile
+++ b/com.oracle.truffle.r.native/library/base/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -21,4 +21,25 @@
 # questions.
 #
 
+ifeq ($(FASTR_RFFI),managed)
+BASE_UNCOMPRESSED = $(addprefix $(FASTR_LIBRARY_DIR)/base/R/, base.rdb)
+BASE_SCRIPT = $(addprefix $(FASTR_LIBRARY_DIR)/base/R/, base)
+LIB_PKG_POST = $(BASE_UNCOMPRESSED) $(BASE_SCRIPT)
+endif
+
 include ../lib.mk
+
+ifeq ($(FASTR_RFFI),managed)
+# original base assumes that "base" DLL is loaded, we change it to check for that first
+$(BASE_SCRIPT): $(GNUR_HOME)/library/base/R/base
+	sed -i '/## populate C\/Fortran symbols/a if (length(getLoadedDLLs()) > 0)' $(FASTR_LIBRARY_DIR)/base/R/base
+# The following changes GnuR's build script makebasedb.R so that it does not
+# compress the lazy load database, then it builds GnuR and copies the
+# uncompressed base package database to FastR library location
+$(BASE_UNCOMPRESSED): $(GNUR_HOME)/src/library/base/all.R
+	sed -i 's|compress = TRUE|compress = FALSE|g' $(GNUR_HOME)/src/library/base/makebasedb.R
+	(cd $(GNUR_HOME); $(MAKE))
+	cp $(GNUR_HOME)/library/$(PKG)/R/base.rd* $(FASTR_LIBRARY_DIR)/base/R/
+	sed -i 's|compress = FALSE|compress = TRUE|g' $(GNUR_HOME)/src/library/base/makebasedb.R
+	(cd $(GNUR_HOME); $(MAKE))
+endif
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java
new file mode 100644
index 0000000000..701bc12f35
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ResourceHandlerFactory;
+import com.oracle.truffle.r.runtime.ResourceHandlerFactory.Handler;
+
+/**
+ * Implementation of {@link ResourceHandlerFactory} that pre-loads all the resources in its static
+ * constructor.
+ */
+public class EagerResourceHandlerFactory extends ResourceHandlerFactory implements Handler {
+    private static class FileInfo {
+        private final String name;
+        private final URL url;
+        private byte[] data;
+
+        FileInfo(String name, URL url, byte[] data) {
+            this.name = name;
+            this.url = url;
+            this.data = data;
+        }
+
+        @Override
+        public String toString() {
+            return "name: " + name + ", url: " + url.toString();
+        }
+    }
+
+    private static HashMap<String, FileInfo> files = new HashMap<>();
+
+    static {
+        gatherResources();
+    }
+
+    @Override
+    public URL getResource(Class<?> accessor, String name) {
+        return files.get(name).url;
+    }
+
+    @Override
+    public InputStream getResourceAsStream(Class<?> accessor, String name) {
+        // actual resource
+        String fileName = Paths.get(name).getFileName().toString();
+        FileInfo fileInfo = files.get(fileName);
+        if (fileInfo == null || fileInfo.data == null) {
+            RInternalError.shouldNotReachHere("getResourceAsStream: failed to find resource: " + name);
+            return null;
+        } else {
+            return new ByteArrayInputStream(fileInfo.data);
+        }
+    }
+
+    @Override
+    protected Handler newHandler() {
+        return this;
+    }
+
+    public static boolean addResource(@SuppressWarnings("unused") Class<?> accessor, String name, String path, boolean capture) {
+        byte[] bytes = null;
+        if (capture) {
+            try {
+                bytes = Files.readAllBytes(Paths.get(path));
+            } catch (IOException ex) {
+                return false;
+            }
+        }
+        try {
+            files.put(name, new FileInfo(name, new URL("file://" + path), bytes));
+        } catch (MalformedURLException ex) {
+            RInternalError.shouldNotReachHere("addResource " + ex.getMessage());
+        }
+        return true;
+    }
+
+    private static void gatherResources() {
+        CodeSource source = RBuiltinPackage.class.getProtectionDomain().getCodeSource();
+        try {
+            URL jarURL = source.getLocation();
+            JarFile fastrJar = new JarFile(new File(jarURL.toURI()));
+            Enumeration<JarEntry> iter = fastrJar.entries();
+            while (iter.hasMoreElements()) {
+                JarEntry entry = iter.nextElement();
+                String name = entry.getName();
+                if (name.endsWith(".R") || name.endsWith("CONTRIBUTORS")) {
+                    int size = (int) entry.getSize();
+                    byte[] buf = new byte[size];
+                    InputStream is = fastrJar.getInputStream(entry);
+                    int totalRead = 0;
+                    int n;
+                    while ((n = is.read(buf, totalRead, buf.length - totalRead)) > 0) {
+                        totalRead += n;
+                    }
+                    // using a proper jar URL causes build image problems
+                    // and no-one really cares what the URL is - we have the data already
+                    String fileName = Paths.get(name).getFileName().toString();
+                    files.put(fileName, new FileInfo(fileName, new URL("file://" + name), buf));
+                }
+            }
+        } catch (Exception ex) {
+            RInternalError.shouldNotReachHere("error locating resources: " + ex.getMessage());
+        }
+    }
+
+    @Override
+    public String[] getRFiles(Class<?> accessor, String pkgName) {
+        ArrayList<String> list = new ArrayList<>();
+        for (Map.Entry<String, FileInfo> entry : files.entrySet()) {
+            if (entry.getValue().url.toString().contains(pkgName + "/R")) {
+                String content = new String(entry.getValue().data);
+                list.add(content);
+            }
+        }
+        String[] result = new String[list.size()];
+        list.toArray(result);
+        return result;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
index 68b4977bee..aac98e96fe 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
 import com.oracle.truffle.r.nodes.builtin.base.BaseVariables;
+import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -97,12 +98,14 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         try {
             baseSource = RSource.fromFileName(basePathbase.toString(), true);
         } catch (IOException ex) {
-            Utils.rSuicide(String.format("unable to open the base package %s", basePathbase));
+            throw Utils.rSuicide(String.format("unable to open the base package %s", basePathbase));
         }
         // Load the (stub) DLL for base
-        String path = baseDirPath.resolve("libs").resolve("base.so").toString();
-        Source loadSource = RSource.fromTextInternal(".Internal(dyn.load(" + RRuntime.escapeString(path, false, true) + ", TRUE, TRUE, \"\"))", RSource.Internal.R_IMPL);
-        RContext.getEngine().parseAndEval(loadSource, baseFrame, false);
+        if (FastROptions.LoadPackagesNativeCode.getBooleanValue()) {
+            String path = baseDirPath.resolve("libs").resolve("base.so").toString();
+            Source loadSource = RSource.fromTextInternal(".Internal(dyn.load(" + RRuntime.escapeString(path, false, true) + ", TRUE, TRUE, \"\"))", RSource.Internal.R_IMPL);
+            RContext.getEngine().parseAndEval(loadSource, baseFrame, false);
+        }
 
         // Any RBuiltinKind.SUBSTITUTE functions installed above should not be overridden
         try {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 170c7bb52a..241fd56c01 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -724,6 +724,10 @@ public class BasePackage extends RBuiltinPackage {
         add(WhileBuiltin.class, WhileBuiltinNodeGen::create);
 
         // grid intrinsics
+        addGridIntrinsics();
+    }
+
+    private void addGridIntrinsics() {
         add(DoSetViewPortBuiltin.class, DoSetViewPortBuiltin::create);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
new file mode 100644
index 0000000000..6aef3d709e
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime;
+
+public final class FastRConfig {
+    /**
+     * Whether the internal grid emulation should use AWT backed graphical devices.
+     */
+    public static final boolean InternalGridAwtSupport;
+
+    /**
+     * Umbrella option, which changes default values of other options in a way that FastR will not
+     * invoke any native code directly and other potentially security sensitive operations are
+     * restricted. Can be configured via environment variable {@code FASTR_MANAGED}.
+     */
+    public static final boolean ManagedMode;
+
+    static {
+        String managedModeVal = System.getenv("FASTR_MANAGED");
+        ManagedMode = managedModeVal != null && managedModeVal.equals("true");
+        InternalGridAwtSupport = !ManagedMode;
+    }
+
+    private FastRConfig() {
+        // only static fields
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index ad8d5d6299..8c99eacf36 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -46,7 +46,7 @@ public enum FastROptions {
     TraceNativeCalls("Trace all native function calls (performed via .Call, .External, etc.)", false),
     Rdebug("Rdebug=f1,f2.,,,; list of R function to call debug on (implies +Instrument)", null, true),
     PerformanceWarnings("Print FastR performance warning", false),
-    LoadBase("Load base package", true),
+    LoadProfiles("Load the system, site and user profile scripts.", !FastRConfig.ManagedMode),
     PrintComplexLookups("Print a message for each non-trivial variable lookup", false),
     FullPrecisionSum("Use 128 bit arithmetic in sum builtin", false),
     InvisibleArgs("Argument writes do not trigger state transitions", true),
@@ -56,6 +56,7 @@ public enum FastROptions {
     ForceSources("Generate source sections for unserialized code", false),
     SharedContexts("Whether all child contexts are to be shared contexts", true),
     SearchPathForcePromises("Whether all promises for frames on shared path are forced in presence of shared contexts", false),
+    LoadPackagesNativeCode("Load native code of packages, including builtin packages.", !FastRConfig.ManagedMode),
 
     // Promises optimizations
     EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DefaultResourceHandlerFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java
similarity index 98%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DefaultResourceHandlerFactory.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java
index 618db88629..1befec1946 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/DefaultResourceHandlerFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java
@@ -40,7 +40,7 @@ import com.oracle.truffle.r.runtime.ResourceHandlerFactory.Handler;
 /**
  * Default implementation uses the default mechanism in {@code java.lang.Class}.
  */
-class DefaultResourceHandlerFactory extends ResourceHandlerFactory implements Handler {
+class LazyResourceHandlerFactory extends ResourceHandlerFactory implements Handler {
 
     @Override
     public URL getResource(Class<?> accessor, String name) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index 639f77c174..e0a2d61e83 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -33,6 +33,7 @@ import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.security.CodeSource;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -190,6 +191,8 @@ public final class REnvVars implements RContext.ContextState {
         return rHome;
     }
 
+    private static CodeSource codeSource = REnvVars.class.getProtectionDomain().getCodeSource();
+
     /**
      * In the case where {@code R_HOME} is not set, which should only occur when FastR is invoked
      * from a {@link PolyglotEngine} created by another language, we try to locate the
@@ -200,7 +203,7 @@ public final class REnvVars implements RContext.ContextState {
      * @return either a valid {@code R_HOME} or {@code null}
      */
     private static Path getRHomePath() {
-        Path path = Paths.get(REnvVars.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent();
+        Path path = Paths.get(codeSource.getLocation().getPath()).getParent();
         String markerFile = markerFile();
         while (path != null) {
             if (validateRHome(path, markerFile)) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index bfa0177952..0824d30cdd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -875,6 +875,7 @@ public final class RError extends RuntimeException {
         CANNOT_CHANGE_LOCKED_ACTIVE_BINDING("cannot change active binding if binding is locked"),
         NO_BINDING_FOR("no binding for \"%s\""),
         INVALID_SUBSTRING_ARGS("invalid substring arguments"),
+        OBJECT_SIZE_ESTIMATE("The object size is only estimated."),
         REPLACING_IN_NON_CHAR_OBJ("replacing substrings in a non-character object");
 
         public final String message;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java
index b20589fd84..f785535b8e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,14 @@ public abstract class ResourceHandlerFactory {
     }
 
     static {
-        final String prop = System.getProperty("fastr.resource.factory.class", "com.oracle.truffle.r.runtime.DefaultResourceHandlerFactory");
+        String prop = System.getProperty("fastr.resource.factory.class");
+        if (prop == null) {
+            if (FastRConfig.ManagedMode) {
+                prop = "com.oracle.truffle.r.nodes.builtin.EagerResourceHandlerFactory";
+            } else {
+                prop = LazyResourceHandlerFactory.class.getName();
+            }
+        }
         try {
             theInstance = (ResourceHandlerFactory) Class.forName(prop).newInstance();
         } catch (Exception ex) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
index 0975c771c1..7ce064541e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
@@ -84,6 +84,7 @@ public class TempPathName implements RContext.ContextState {
     }
 
     @Override
+    @TruffleBoundary
     public void beforeDestroy(RContext context) {
         if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
             return;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index df63d1fc42..ed9b67884e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -35,6 +35,7 @@ import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 import java.util.Arrays;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.ProcessOutputManager;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
@@ -54,6 +55,7 @@ public class FifoConnections {
         }
 
         @Override
+        @TruffleBoundary
         protected void createDelegateConnection() throws IOException {
             final DelegateRConnection delegate;
             if (isBlocking()) {
@@ -267,6 +269,7 @@ public class FifoConnections {
      * @param path The path to the named pipe.
      * @throws IOException
      */
+    @TruffleBoundary
     private static void createNamedPipe(String path) throws IOException {
 
         String[] command = new String[]{"mkfifo", path};
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 7aa052f920..51e1782e0d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -46,6 +46,7 @@ import org.tukaani.xz.XZ;
 import org.tukaani.xz.XZInputStream;
 import org.tukaani.xz.XZOutputStream;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RCompression;
 import com.oracle.truffle.r.runtime.RCompression.Type;
 import com.oracle.truffle.r.runtime.RError;
@@ -87,6 +88,7 @@ public class FileConnections {
         }
 
         @Override
+        @TruffleBoundary
         protected void createDelegateConnection() throws IOException {
 
             DelegateRConnection delegate = FileConnections.createDelegateConnection(this, RCompression.Type.NONE, raw);
@@ -111,6 +113,7 @@ public class FileConnections {
         }
 
         @Override
+        @TruffleBoundary
         protected void createDelegateConnection() throws IOException {
             setDelegate(FileConnections.createDelegateConnection(this, cType, false));
 
@@ -215,6 +218,7 @@ public class FileConnections {
         }
     }
 
+    @TruffleBoundary
     private static DelegateRConnection createDelegateConnection(BasePathRConnection base, RCompression.Type cType, boolean raw) throws IOException {
         AbstractOpenMode openMode = base.getOpenMode().abstractOpenMode;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
index a4ea565e9e..ae41e53ce7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SocketConnections.java
@@ -29,6 +29,7 @@ import java.nio.channels.ByteChannel;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
@@ -56,6 +57,7 @@ public class SocketConnections {
         }
 
         @Override
+        @TruffleBoundary
         protected void createDelegateConnection() throws IOException {
             DelegateRConnection delegate;
             if (server) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java
index 18a0cb472d..dc5b6529b9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,13 +22,21 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler;
 import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer;
 
 public abstract class ObjectSizeFactory {
 
     static {
-        final String prop = System.getProperty("fastr.objectsize.factory.class", "com.oracle.truffle.r.runtime.data.AgentObjectSizeFactory");
+        String prop = System.getProperty("fastr.objectsize.factory.class");
+        if (prop == null) {
+            if (FastRConfig.ManagedMode) {
+                prop = SimpleObjectSizeFactory.class.getName();
+            } else {
+                prop = AgentObjectSizeFactory.class.getName();
+            }
+        }
         try {
             theInstance = (ObjectSizeFactory) Class.forName(prop).newInstance();
         } catch (Exception ex) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java
new file mode 100644
index 0000000000..6f5d17a466
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.data;
+
+import java.util.HashMap;
+
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler;
+import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+/**
+ * Very simple object size calculation that does not need an instrumentation agent.
+ */
+public class SimpleObjectSizeFactory extends ObjectSizeFactory {
+    private HashMap<Class<?>, TypeCustomizer> typeCustomizers;
+
+    @Override
+    public long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) {
+        RError.warning(RError.NO_CALLER, Message.OBJECT_SIZE_ESTIMATE);
+        // Customizers
+        for (Class<?> klass : typeCustomizers.keySet()) {
+            if (obj.getClass().equals(klass)) {
+                return typeCustomizers.get(klass).getObjectSize(obj);
+            }
+        }
+        // Well known vector types
+        if (obj instanceof RAbstractDoubleVector) {
+            return Double.BYTES * ((RAbstractDoubleVector) obj).getLength();
+        } else if (obj instanceof RAbstractIntVector) {
+            return Integer.BYTES * ((RAbstractIntVector) obj).getLength();
+        } else if (obj instanceof RAbstractStringVector) {
+            int length = 0;
+            RAbstractStringVector strVec = (RAbstractStringVector) obj;
+            for (int i = 0; i < strVec.getLength(); i++) {
+                length += strVec.getDataAt(i).length();
+            }
+            return length * 2;
+        } else if (obj instanceof RAbstractLogicalVector || obj instanceof RAbstractRawVector) {
+            return Byte.BYTES * ((RAbstractAtomicVector) obj).getLength();
+        } else if (obj instanceof RAbstractListVector) {
+            int total = 0;
+            RAbstractListVector list = (RAbstractListVector) obj;
+            for (int i = 0; i < list.getLength(); i++) {
+                // Note: RLists should not be cyclic
+                total += getObjectSize(list.getDataAt(i), ignoreObjectHandler);
+            }
+            return total;
+        }
+        return 4;
+    }
+
+    @Override
+    public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) {
+        if (typeCustomizers == null) {
+            typeCustomizers = new HashMap<>();
+        }
+        typeCustomizers.put(klass, typeCustomizer);
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index 27d418847b..60d3811bdb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.runtime.ffi;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
 
@@ -40,6 +41,7 @@ public abstract class RFFIFactory {
     private enum Factory {
         JNI("com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory"),
         LLVM("com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_RFFIFactory"),
+        MANAGED("com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory"),
         NFI("com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_RFFIFactory");
 
         private final String klassName;
@@ -86,6 +88,9 @@ public abstract class RFFIFactory {
         if (prop != null) {
             return checkFactoryName(prop);
         }
+        if (FastRConfig.ManagedMode) {
+            return Factory.MANAGED.klassName;
+        }
         return DEFAULT_FACTORY.klassName;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java
new file mode 100644
index 0000000000..ea6d2db107
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.managed;
+
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.EnumSet;
+import java.util.Set;
+
+class FilesystemUtils {
+    private static PosixFilePermission[] permissionValues = PosixFilePermission.values();
+
+    static Set<PosixFilePermission> permissionsFromMode(int mode) {
+        Set<PosixFilePermission> permissions = EnumSet.noneOf(PosixFilePermission.class);
+        for (int i = 0; i < permissionValues.length; i++) {
+            if ((mode & (1 << (permissionValues.length - i - 1))) != 0) {
+                permissions.add(permissionValues[i]);
+            }
+        }
+        return permissions;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java
new file mode 100644
index 0000000000..988632777a
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.managed;
+
+import static com.oracle.truffle.r.runtime.ffi.managed.FilesystemUtils.permissionsFromMode;
+import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+
+import java.io.IOException;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.Set;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+
+public class Managed_Base implements BaseRFFI {
+    /**
+     * Process id is used as seed for random number generator. We return another "random" number.
+     */
+    @Override
+    public GetpidNode createGetpidNode() {
+        return new GetpidNode() {
+            private int fakePid = (int) System.currentTimeMillis();
+
+            @Override
+            public int execute() {
+                return fakePid;
+            }
+        };
+    }
+
+    @Override
+    public GetwdNode createGetwdNode() {
+        return new GetwdNode() {
+            @Override
+            @TruffleBoundary
+            public String execute() {
+                return Paths.get(".").toAbsolutePath().normalize().toString();
+            }
+        };
+    }
+
+    @Override
+    public SetwdNode createSetwdNode() {
+        return new SetwdNode() {
+            @Override
+            public int execute(String dir) {
+                throw unsupported("setwd");
+            }
+        };
+    }
+
+    @Override
+    public MkdirNode createMkdirNode() {
+        return new MkdirNode() {
+            @Override
+            @TruffleBoundary
+            public void execute(String dir, int mode) throws IOException {
+                Set<PosixFilePermission> permissions = permissionsFromMode(mode);
+                Files.createDirectories(Paths.get(dir), PosixFilePermissions.asFileAttribute(permissions));
+            }
+        };
+    }
+
+    @Override
+    public ReadlinkNode createReadlinkNode() {
+        return new ReadlinkNode() {
+            @Override
+            public String execute(String path) throws IOException {
+                throw unsupported("linknode");
+            }
+        };
+    }
+
+    @Override
+    public MkdtempNode createMkdtempNode() {
+        return new MkdtempNode() {
+            @Override
+            @TruffleBoundary
+            public String execute(String template) {
+                Path path = null;
+                boolean done = false;
+                while (!done) {
+                    try {
+                        path = Paths.get(template);
+                        Files.createDirectories(path);
+                        done = true;
+                    } catch (FileAlreadyExistsException e) {
+                        // nop
+                    } catch (IOException e) {
+                        throw RError.error(RError.NO_CALLER, Message.GENERIC, "Cannot create temp directories.");
+                    }
+                }
+                return path.toString();
+            }
+        };
+    }
+
+    @Override
+    public ChmodNode createChmodNode() {
+        return new ChmodNode() {
+            @Override
+            @TruffleBoundary
+            public int execute(String path, int mode) {
+                try {
+                    Files.setPosixFilePermissions(Paths.get(path), permissionsFromMode(mode));
+                    return mode;
+                } catch (IOException e) {
+                    throw RError.error(RError.NO_CALLER, Message.GENERIC, "Cannot change file permissions.");
+                }
+            }
+        };
+    }
+
+    @Override
+    public StrolNode createStrolNode() {
+        return null;
+    }
+
+    @Override
+    public UnameNode createUnameNode() {
+        return new UnameNode() {
+            @Override
+            public UtsName execute() {
+                return new UtsName() {
+                    @Override
+                    public String sysname() {
+                        return System.getProperty("os.name");
+                    }
+
+                    @Override
+                    public String release() {
+                        return "";
+                    }
+
+                    @Override
+                    public String version() {
+                        return System.getProperty("os.version");
+                    }
+
+                    @Override
+                    public String machine() {
+                        return System.getProperty("os.arch");
+                    }
+
+                    @Override
+                    public String nodename() {
+                        return "";
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public GlobNode createGlobNode() {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java
new file mode 100644
index 0000000000..2b532244fe
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.managed;
+
+import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+
+public class Managed_LapackRFFI implements LapackRFFI {
+    @Override
+    public IlaverNode createIlaverNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DgeevNode createDgeevNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public Dgeqp3Node createDgeqp3Node() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DormqrNode createDormqrNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DtrtrsNode createDtrtrsNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DgetrfNode createDgetrfNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DpotrfNode createDpotrfNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DpotriNode createDpotriNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DpstrfNode createDpstrfNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DgesvNode createDgesvNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DlangeNode createDlangeNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DgeconNode createDgeconNode() {
+        throw unsupported("lapack");
+    }
+
+    @Override
+    public DsyevrNode createDsyevrNode() {
+        throw unsupported("lapack");
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
new file mode 100644
index 0000000000..e060345226
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.managed;
+
+import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+
+public class Managed_PCRERFFI implements PCRERFFI {
+    @Override
+    public MaketablesNode createMaketablesNode() {
+        throw unsupported("PCRER");
+    }
+
+    @Override
+    public CompileNode createCompileNode() {
+        throw unsupported("PCRER");
+    }
+
+    @Override
+    public GetCaptureCountNode createGetCaptureCountNode() {
+        throw unsupported("PCRER");
+    }
+
+    @Override
+    public GetCaptureNamesNode createGetCaptureNamesNode() {
+        throw unsupported("PCRER");
+    }
+
+    @Override
+    public StudyNode createStudyNode() {
+        throw unsupported("PCRER");
+    }
+
+    @Override
+    public ExecNode createExecNode() {
+        throw unsupported("PCRER");
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java
new file mode 100644
index 0000000000..9d0a0a079f
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.managed;
+
+import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+
+public class Managed_REmbedRFFI implements REmbedRFFI {
+    @Override
+    public void suicide(String x) {
+        throw unsupported("REmbed");
+    }
+
+    @Override
+    public void cleanUp(int type, int x, int y) {
+        throw unsupported("REmbed");
+    }
+
+    @Override
+    public String readConsole(String prompt) {
+        throw unsupported("REmbed");
+    }
+
+    @Override
+    public void writeConsole(String x) {
+        throw unsupported("REmbed");
+    }
+
+    @Override
+    public void writeErrConsole(String x) {
+        throw unsupported("REmbed");
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
new file mode 100644
index 0000000000..f5ec388349
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.managed;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.GridRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+/**
+ * Operations that can be, at least partially, implemented in Java are implemented, other operations
+ * throw {@link RError}.
+ */
+public class Managed_RFFIFactory extends RFFIFactory implements RFFI {
+    @Override
+    protected RFFI createRFFI() {
+        return this;
+    }
+
+    @Override
+    public BaseRFFI getBaseRFFI() {
+        return new Managed_Base();
+    }
+
+    @Override
+    public LapackRFFI getLapackRFFI() {
+        return new Managed_LapackRFFI();
+    }
+
+    @Override
+    public RApplRFFI getRApplRFFI() {
+        return new RApplRFFI() {
+            @Override
+            public Dqrdc2Node createDqrdc2Node() {
+                throw unsupported("dqrdc");
+            }
+
+            @Override
+            public DqrcfNode createDqrcfNode() {
+                throw unsupported("dqrcf");
+            }
+
+            @Override
+            public DqrlsNode createDqrlsNode() {
+                throw unsupported("dqrls");
+            }
+        };
+    }
+
+    @Override
+    public StatsRFFI getStatsRFFI() {
+        return new StatsRFFI() {
+            @Override
+            public FactorNode createFactorNode() {
+                throw unsupported("factor");
+            }
+
+            @Override
+            public WorkNode createWorkNode() {
+                throw unsupported("work");
+            }
+        };
+    }
+
+    @Override
+    public ToolsRFFI getToolsRFFI() {
+        return new ToolsRFFI() {
+            @Override
+            public ParseRdNode createParseRdNode() {
+                throw unsupported("parseRD");
+            }
+        };
+    }
+
+    // TODO: will be removed anyway
+    @Override
+    public GridRFFI getGridRFFI() {
+        return new GridRFFI() {
+            @Override
+            public InitGridNode createInitGridNode() {
+                return null;
+            }
+
+            @Override
+            public KillGridNode createKillGridNode() {
+                return null;
+            }
+        };
+    }
+
+    @Override
+    public CRFFI getCRFFI() {
+        return new CRFFI() {
+            @Override
+            public InvokeCNode createInvokeCNode() {
+                throw unsupported("invoke");
+            }
+        };
+    }
+
+    @Override
+    public CallRFFI getCallRFFI() {
+        return new CallRFFI() {
+            @Override
+            public InvokeCallNode createInvokeCallNode() {
+                throw unsupported("native code invocation");
+            }
+
+            @Override
+            public InvokeVoidCallNode createInvokeVoidCallNode() {
+                throw unsupported("native code invocation");
+            }
+        };
+    }
+
+    @Override
+    public UserRngRFFI getUserRngRFFI() {
+        return new UserRngRFFI() {
+            @Override
+            public UserRngRFFINode createUserRngRFFINode() {
+                throw unsupported("user defined RNG");
+            }
+        };
+    }
+
+    @Override
+    public PCRERFFI getPCRERFFI() {
+        return new Managed_PCRERFFI();
+    }
+
+    @Override
+    public ZipRFFI getZipRFFI() {
+        return new ZipRFFI() {
+            @Override
+            public CompressNode createCompressNode() {
+                throw unsupported("zip compression");
+            }
+
+            @Override
+            public UncompressNode createUncompressNode() {
+                throw unsupported("zip decompression");
+            }
+        };
+    }
+
+    @Override
+    public DLLRFFI getDLLRFFI() {
+        return new DLLRFFI() {
+            @Override
+            public DLOpenNode createDLOpenNode() {
+                throw unsupported("DLL open");
+            }
+
+            @Override
+            public DLSymNode createDLSymNode() {
+                throw unsupported("createDLSym");
+            }
+
+            @Override
+            public DLCloseNode createDLCloseNode() {
+                throw unsupported("createDLClose");
+            }
+        };
+    }
+
+    @Override
+    public REmbedRFFI getREmbedRFFI() {
+        return new Managed_REmbedRFFI();
+    }
+
+    @Override
+    public MiscRFFI getMiscRFFI() {
+        return new MiscRFFI() {
+            @Override
+            public ExactSumNode createExactSumNode() {
+                throw unsupported("exactsum");
+            }
+        };
+    }
+
+    @Override
+    public ContextState newContextState() {
+        return new ContextState() {
+            @Override
+            public ContextState initialize(RContext context) {
+                return this;
+            }
+        };
+    }
+
+    @TruffleBoundary
+    static RError unsupported(String name) {
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, String.format("Feature '%s' is not supported by managed FFI, i.e. it requires running native code.", name));
+    }
+}
diff --git a/documentation/dev/ffi.md b/documentation/dev/ffi.md
index 69fb145d11..0a35d7f1ef 100644
--- a/documentation/dev/ffi.md
+++ b/documentation/dev/ffi.md
@@ -1,10 +1,13 @@
 # The R FFI Implementation
 
 # Introduction
-FastR interfaces to native C and Fortran code in a number of ways, for example, access to C library APIs not supported by the Java JDK, access to LaPack functions, and the `.Call`, `.Fortran`, `.C` builtins. Each of these are defined by a Java interface,e.g. `CallRFFI` for the `.Call` builtin. To facilitate experimentation and different implementations, the implementation of these interfaces is defined by a factory class, `RFFIFactory`, that is chosen at run time via the `fastr.ffi.factory.class` system property, or the `FASTR_RFFI` environment variable.
+FastR can interface to native C and Fortran code in a number of ways, for example, access to C library APIs not supported by the Java JDK, access to LaPack functions, and the `.Call`, `.Fortran`, `.C` builtins. Each of these are defined by a Java interface,e.g. `CallRFFI` for the `.Call` builtin. To facilitate experimentation and different implementations, the implementation of these interfaces is defined by a factory class, `RFFIFactory`, that is chosen at run time via the `fastr.ffi.factory.class` system property, or the `FASTR_RFFI` environment variable.
 The factory is responsible for creating an instance of the `RFFI` interface that in turn provides access to implementations of the underlying interfaces such as `CallRFFI`. This structure allows
 for each of the individual interfaces to be implemented by a different mechanism. Currently the default factory class is `JNI_RFFIFactory` which uses the Java JNI system to implement the transition to native code.
 
+# No native code mode
+FastR can be configured to avoid running any unmanaged code coming from GNU R or packages. It is described in more detail [here](managed_ffi.md).
+
 # Native Implementation
 The native implementation of the [R FFI](https://cran.r-project.org/doc/manuals/r-release/R-exts.html) is contained in the `fficall` directory of
 the `com.oracle/truffle.r.native` project`. It's actually a bit more than that as it also contains code copied from GNU R, for example that supports graphics or is sufficiently
@@ -58,7 +61,7 @@ The implementation is currently incomplete.
 
 # RFFI Initialization
 Not all of the individual interfaces need to be instantiated on startup. The `getXXXRFFI()` method of `RFFI` is responsible for instantiating the `XXX` interface (e.e.g `Call`).
-However, the factory can choose to instantiate the interfqces eagerly if desired. The choice of factory class is made by `RFFIFactory.initialize()` which is called when the
+However, the factory can choose to instantiate the interfaces eagerly if desired. The choice of factory class is made by `RFFIFactory.initialize()` which is called when the
 initial `RContext` is being created by `PolyglotEngine`. Note that at this stage, very little code can be executed as the initial context has not yet been fully created and registered with `PolyglotEngine`.
 
 In general, state maintained by the `RFFI` implementation classes is `RContext` specific and to facilitate this `RFFIFactory` defines a `newContextState` method that is called by `RContext`. Again, at the point this is called the context is not active and so any execution that requires an active context must be delayed until the `initialize` method is called on the `ContextState` instance. Typically special initialization may be required on the initialization of the initial context, such as loading native libraries, and also on the initialization of a `SHARED_PARENT_RW` context kind.
diff --git a/documentation/dev/managed_ffi.md b/documentation/dev/managed_ffi.md
new file mode 100644
index 0000000000..4e07641430
--- /dev/null
+++ b/documentation/dev/managed_ffi.md
@@ -0,0 +1,25 @@
+
+# Quick start
+FastR supports a 'managed' mode, in which it does not execute any native code directly, especially code coming from GNU R and packages, 
+and tries to avoid other potentially security sensitive code, e.g. instrumentation agents. To enable this mode, clean build and run 
+FastR with environment variable `FASTR_MANAGED` set to *true*.
+
+# Details
+FastR has an 'implementation' of RFFI that does not use any native code directly (e.g. through JNI) and implements only small subset of the API. 
+Any usage of the unimplemented parts will cause error at runtime. To enable this RFFI implementation clean build FastR with environment variable 
+`FASTR_RFFI` set to *managed* and when running FastR set java property named *fastr.rffi.factory.class* to 
+`com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory`.
+
+There are additional options that can restrict other usages of native code in FastR:
+
+* When FastR option `LoadPackagesNativeCode=false`, then FastR does not load builtin packages (graphics and base) native code. 
+Note that loading of their native code is going to fail with *managed* RFFI implementation.
+* When FastR option `LoadProfiles=false`, then FastR does not load user profile, machine profile etc. Those scripts typically use 
+some R code that ends up trying to call native code, which is again going to fail with *managed* RFFI implementation.
+* Set `FastRConfig#InternalGridAwtSupport` to `false` before building FastR. This should remove usages of AWT from FastR's 
+bytecode and thus reduce the amount of native code that can be invoked by running arbitrary R code in FastR.
+
+Following option can be useful for improving security when running FastR:
+
+* Set java property *fastr.objectsize.factory.class*  to `com.oracle.truffle.r.runtime.data.SimpleObjectSizeFactory` to avoid 
+usage of otherwise more precise `AgentObjectSizeFactory`, which uses instrumentation agent.
-- 
GitLab


From 45f0efda9d25b9782637c71210e7e4fedb5e5bad Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Wed, 26 Apr 2017 17:57:16 +0200
Subject: [PATCH 326/402] Update base library Makefile to work on MacOS

---
 com.oracle.truffle.r.native/library/base/Makefile | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.native/library/base/Makefile b/com.oracle.truffle.r.native/library/base/Makefile
index f4077b8f23..997d0c4410 100644
--- a/com.oracle.truffle.r.native/library/base/Makefile
+++ b/com.oracle.truffle.r.native/library/base/Makefile
@@ -32,14 +32,16 @@ include ../lib.mk
 ifeq ($(FASTR_RFFI),managed)
 # original base assumes that "base" DLL is loaded, we change it to check for that first
 $(BASE_SCRIPT): $(GNUR_HOME)/library/base/R/base
-	sed -i '/## populate C\/Fortran symbols/a if (length(getLoadedDLLs()) > 0)' $(FASTR_LIBRARY_DIR)/base/R/base
+	sed 's|## populate C\/Fortran symbols|if (length(getLoadedDLLs()) > 0)|g' $(FASTR_LIBRARY_DIR)/base/R/base > $(FASTR_LIBRARY_DIR)/base/R/base.tmp
+	mv $(FASTR_LIBRARY_DIR)/base/R/base.tmp $(FASTR_LIBRARY_DIR)/base/R/base
 # The following changes GnuR's build script makebasedb.R so that it does not
 # compress the lazy load database, then it builds GnuR and copies the
 # uncompressed base package database to FastR library location
 $(BASE_UNCOMPRESSED): $(GNUR_HOME)/src/library/base/all.R
-	sed -i 's|compress = TRUE|compress = FALSE|g' $(GNUR_HOME)/src/library/base/makebasedb.R
+	cp $(GNUR_HOME)/src/library/base/makebasedb.R $(GNUR_HOME)/src/library/base/makebasedb.R.tmp
+	sed 's|compress = TRUE|compress = FALSE|g' $(GNUR_HOME)/src/library/base/makebasedb.R.tmp > $(GNUR_HOME)/src/library/base/makebasedb.R
 	(cd $(GNUR_HOME); $(MAKE))
 	cp $(GNUR_HOME)/library/$(PKG)/R/base.rd* $(FASTR_LIBRARY_DIR)/base/R/
-	sed -i 's|compress = FALSE|compress = TRUE|g' $(GNUR_HOME)/src/library/base/makebasedb.R
+	mv $(GNUR_HOME)/src/library/base/makebasedb.R.tmp $(GNUR_HOME)/src/library/base/makebasedb.R
 	(cd $(GNUR_HOME); $(MAKE))
 endif
-- 
GitLab


From 027c8874ea142edb6ca01949945d37aaed71363a Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 21 Apr 2017 13:55:48 -0700
Subject: [PATCH 327/402] TruffleNFI: prevent RNull converting to null

---
 .../truffle/r/engine/interop/RNullMR.java     | 13 ++++-
 .../interop/ffi/nfi/TruffleNFI_Call.java      | 49 ++++++++++---------
 2 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
index be1ae97f40..4fa755eacc 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
@@ -32,6 +32,11 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 @MessageResolution(receiverType = RNull.class, language = TruffleRLanguage.class)
 public class RNullMR {
+    /**
+     * Workaround to avoid NFI converting {@link RNull} to {@code null}.
+     */
+    private static boolean isNull = true;
+
     @Resolve(message = "IS_BOXED")
     public abstract static class RNullIsBoxedNode extends Node {
         protected Object access(@SuppressWarnings("unused") RNull receiver) {
@@ -49,7 +54,7 @@ public class RNullMR {
     @Resolve(message = "IS_NULL")
     public abstract static class RNullIsNullNode extends Node {
         protected Object access(@SuppressWarnings("unused") RNull receiver) {
-            return true;
+            return isNull;
         }
     }
 
@@ -60,4 +65,10 @@ public class RNullMR {
             return receiver instanceof RNull;
         }
     }
+
+    public static boolean setIsNull(boolean value) {
+        boolean prev = isNull;
+        isNull = value;
+        return prev;
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
index cd65b42fb8..375711ebea 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
@@ -34,10 +34,12 @@ import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.interop.RNullMR;
 import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen;
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
 import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
@@ -234,7 +236,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
@@ -243,7 +245,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -253,7 +255,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object): object");
@@ -262,7 +264,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -272,7 +274,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object");
@@ -281,7 +283,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -291,7 +293,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object");
@@ -300,7 +302,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -310,7 +312,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object");
@@ -320,7 +322,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -330,7 +332,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object");
@@ -340,7 +342,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -350,7 +352,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object");
@@ -360,7 +362,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -370,7 +372,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object");
@@ -381,7 +383,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -391,7 +393,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object");
@@ -402,7 +404,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -423,7 +425,7 @@ public class TruffleNFI_Call implements CallRFFI {
         @Override
         public void execute(NativeCallInfo nativeCallInfo, Object[] args) {
             synchronized (TruffleNFI_Call.class) {
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     switch (args.length) {
                         case 0:
@@ -440,25 +442,28 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, null);
+                    prepareReturn(nativeCallInfo.name, null, isNullSetting);
                 }
             }
         }
     }
 
-    private static void prepareCall(String name, Object[] args) {
+    private static boolean prepareCall(String name, Object[] args) {
         if (traceEnabled()) {
             traceDownCall(name, args);
         }
+        boolean isNullSetting = RNullMR.setIsNull(false);
         TruffleNFI_NativeArray.callEnter(callDepth);
         callDepth++;
+        return isNullSetting;
     }
 
-    private static void prepareReturn(String name, Object result) {
+    private static void prepareReturn(String name, Object result, boolean isNullSetting) {
         if (traceEnabled()) {
             traceDownCallReturn(name, result);
         }
         TruffleNFI_NativeArray.callEnter(callDepth);
+        RNullMR.setIsNull(isNullSetting);
         callDepth--;
     }
 
-- 
GitLab


From 29dfad18c2dbb08b6ca6b065045fa6c856905b81 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 27 Apr 2017 15:26:13 +0200
Subject: [PATCH 328/402] Fix: Condition handler was called with wrong
 signature.

---
 .../com/oracle/truffle/r/runtime/RErrorHandling.java   |  2 +-
 .../com/oracle/truffle/r/test/ExpectedTestOutput.test  | 10 ++++++++++
 .../r/test/library/base/TestConditionHandling.java     |  2 ++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 6a5b182e76..ac0af78b88 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -388,7 +388,7 @@ public class RErrorHandling {
                     } else {
                         RFunction handler = (RFunction) entry.getDataAt(2);
                         RStringVector errorMsgVec = RDataFactory.createStringVectorFromScalar(fMsg);
-                        RContext.getRRuntimeASTAccess().callback(handler, new Object[]{errorMsgVec, call});
+                        RContext.getRRuntimeASTAccess().callback(handler, new Object[]{errorMsgVec});
                     }
                 } else {
                     throw gotoExitingHandler(RNull.instance, call, entry);
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 07a17a4a94..3ab87815de 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
@@ -77655,6 +77655,16 @@ Error in tryCatchList(expr, classes, parentenv, handlers) : fred
 #{ tryCatch(stop("xyz"), error=function(e) { cat("<error>");123L }, finally=function() { cat("<finally>")}) }
 <error>[1] 123
 
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#Output.IgnoreErrorContext#
+#withCallingHandlers(stop('error message'), error=function(e) {})
+Error in withCallingHandlers(stop("error message"), error = function(e) { :
+  error message
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#Output.IgnoreErrorMessage#
+#withCallingHandlers(unknownSymbol(), condition = function(e) {})
+Error in withCallingHandlers(unknownSymbol(), condition = function(e) { :
+  could not find function "unknownSymbol"
+
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#
 #withCallingHandlers({message("foo");123L},<<<NEWLINE>>> message=function(e) {<<<NEWLINE>>> cat("<msg>")<<<NEWLINE>>> invokeRestart("muffleMessage")<<<NEWLINE>>> })
 <msg>[1] 123
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
index 8d7b2dcf1a..c2c416bad7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
@@ -63,5 +63,7 @@ public class TestConditionHandling extends TestRBase {
         assertEval("withCallingHandlers({message(\"foo\");123L},\n message=function(e) {cat(\"<msg>\")})");
         assertEval("withCallingHandlers({message(\"foo\");123L},\n message=function(e) {\n cat(\"<msg>\")\n invokeRestart(\"muffleMessage\")\n })");
         assertEval("withCallingHandlers({message(\"foo\");packageStartupMessage(\"bar\");123L},\n packageStartupMessage=function(e) {\n cat(\"<msg>\")\n invokeRestart(\"muffleMessage\")\n })");
+        assertEval(Output.IgnoreErrorContext, "withCallingHandlers(stop('error message'), error=function(e) {})");
+        assertEval(Output.IgnoreErrorMessage, "withCallingHandlers(unknownSymbol(), condition = function(e) {})");
     }
 }
-- 
GitLab


From e4e90bd9b3ca264051589b5d9002f1878c9d289e Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 26 Apr 2017 16:57:27 -0700
Subject: [PATCH 329/402] Provide finer control over FastRConfig.

---
 .../src/com/oracle/truffle/r/runtime/FastRConfig.java      | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
index 6aef3d709e..8d6bbf8f1b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
@@ -38,7 +38,12 @@ public final class FastRConfig {
     static {
         String managedModeVal = System.getenv("FASTR_MANAGED");
         ManagedMode = managedModeVal != null && managedModeVal.equals("true");
-        InternalGridAwtSupport = !ManagedMode;
+        if (ManagedMode) {
+            InternalGridAwtSupport = false;
+        } else {
+            String val = System.getProperty("fastr.internal.grid.awt.support");
+            InternalGridAwtSupport = val == null || val.equals("true");
+        }
     }
 
     private FastRConfig() {
-- 
GitLab


From 28d55c98c21b5703c434d6b1f5a9355566784871 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Mon, 24 Apr 2017 16:18:45 -0700
Subject: [PATCH 330/402] complete TruffleNFI impls

---
 .../r/engine/interop/CaptureNamesImplMR.java  | 68 +++++++++++++++++++
 .../r/engine/interop/GlobUpCallImplMR.java    | 51 ++++++++++++++
 .../r/engine/interop/MakeResultImplMR.java    | 68 +++++++++++++++++++
 .../interop/RForeignAccessFactoryImpl.java    | 13 ++++
 .../r/engine/interop/SetResultImplMR.java     | 51 ++++++++++++++
 .../r/engine/interop/UnameUpCallImplMR.java   | 52 ++++++++++++++
 .../interop/ffi/nfi/TruffleNFI_Base.java      | 13 ++--
 .../engine/interop/ffi/nfi/TruffleNFI_C.java  | 66 ++++++++++++++++++
 .../interop/ffi/nfi/TruffleNFI_Call.java      |  1 -
 .../interop/ffi/nfi/TruffleNFI_Misc.java      | 59 ++++++++++++++++
 .../interop/ffi/nfi/TruffleNFI_PCRE.java      | 13 ++--
 .../interop/ffi/nfi/TruffleNFI_REmbed.java    | 59 ++++++++++++++++
 .../ffi/nfi/TruffleNFI_RFFIFactory.java       | 58 +++++++++++++++-
 .../interop/ffi/nfi/TruffleNFI_Tools.java     |  5 +-
 .../fficall/src/truffle_nfi/call_rffi.c.not   | 26 -------
 .../fficall/src/truffle_nfi/misc_rffi.c       | 50 ++++++++++++++
 16 files changed, 609 insertions(+), 44 deletions(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
 delete mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
new file mode 100644
index 0000000000..5063771196
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+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.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl.class, language = TruffleRLanguage.class)
+public class CaptureNamesImplMR {
+    @CanResolve
+    public abstract static class CaptureNamesImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class CaptureNamesImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl receiver, Object[] arguments) {
+            try {
+                Object arg1 = arguments[1];
+                if (arg1 instanceof TruffleObject) {
+                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                        arg1 = null;
+                    } else {
+                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                    }
+                }
+                receiver.addName((int) arguments[0], (String) arg1);
+                return receiver;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
new file mode 100644
index 0000000000..3a614c0a7b
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+
+@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl.class, language = TruffleRLanguage.class)
+public class GlobUpCallImplMR {
+    @CanResolve
+    public abstract static class GlobUpCallImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class GlobUpCallImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl receiver, Object[] arguments) {
+            receiver.addPath((String) arguments[0]);
+            return receiver;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
new file mode 100644
index 0000000000..34c97f9c38
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+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.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl.class, language = TruffleRLanguage.class)
+public class MakeResultImplMR {
+    @CanResolve
+    public abstract static class MakeResultImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class MakeResultImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl receiver, Object[] arguments) {
+            try {
+                Object arg1 = arguments[1];
+                if (arg1 instanceof TruffleObject) {
+                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                        arg1 = null;
+                    } else {
+                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                    }
+                }
+                receiver.makeresult((long) arguments[0], (String) arg1, (int) arguments[2]);
+                return receiver;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 428399f41f..2eb7170790 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -27,6 +27,8 @@ import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -95,6 +97,16 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return CharSXPWrapperMRForeign.ACCESS;
         } else if (obj instanceof RConnection) {
             return RConnectionMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl) {
+            return UnameUpCallImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl) {
+            return SetResultImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl) {
+            return GlobUpCallImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl) {
+            return MakeResultImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl) {
+            return CaptureNamesImplMRForeign.ACCESS;
         } else {
             if (obj instanceof RAbstractVector) {
                 return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
@@ -102,6 +114,7 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
                 throw RInternalError.unimplemented("missing foreign access factory for " + obj.getClass().getSimpleName());
             }
         }
+
     }
 
     @Override
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
new file mode 100644
index 0000000000..69cf410359
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+
+@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl.class, language = TruffleRLanguage.class)
+public class SetResultImplMR {
+    @CanResolve
+    public abstract static class SetResultImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class SetResultImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl receiver, Object[] arguments) {
+            receiver.setResult((String) arguments[0], (int) arguments[1]);
+            return receiver;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
new file mode 100644
index 0000000000..6382443b4f
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+
+@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl.class, language = TruffleRLanguage.class)
+public class UnameUpCallImplMR {
+    @CanResolve
+    public abstract static class UnameUpCallImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class UnameUpCallImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl receiver, Object[] arguments) {
+            receiver.unameUpCall((String) arguments[0], (String) arguments[1], (String) arguments[2], (String) arguments[3], (String) arguments[4]);
+            return receiver;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
index 33ab050e3c..7e9c053144 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
 public class TruffleNFI_Base implements BaseRFFI {
@@ -145,7 +146,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             void setResult(String link, int errno);
         }
 
-        private static class SetResultImpl implements SetResult {
+        public static class SetResultImpl implements SetResult, RTruffleObject {
             private String link;
             private int errno;
 
@@ -162,7 +163,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             Function.call_readlink.initialize();
             try {
                 SetResultImpl setResultImpl = new SetResultImpl();
-                ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, JavaInterop.asTruffleFunction(SetResult.class, setResultImpl), path);
+                ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, setResultImpl, path);
                 if (setResultImpl.link == null) {
                     if (setResultImpl.errno == EINVAL) {
                         return path;
@@ -256,7 +257,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             void unameUpCall(String sysname, String release, String version, String machine, String nodename);
         }
 
-        private class UnameUpCallImpl implements UnameUpCall, UtsName {
+        public static class UnameUpCallImpl implements UnameUpCall, UtsName, RTruffleObject {
             private String sysname;
             private String release;
             private String version;
@@ -305,7 +306,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             if (unameUpCallImpl == null) {
                 unameUpCallImpl = new UnameUpCallImpl();
                 try {
-                    ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, JavaInterop.asTruffleFunction(UnameUpCall.class, unameUpCallImpl));
+                    ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, unameUpCallImpl);
                 } catch (InteropException e) {
                     throw RInternalError.shouldNotReachHere(e);
                 }
@@ -319,7 +320,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             void addPath(String path);
         }
 
-        private static class GlobUpCallImpl implements GlobUpCall {
+        public static class GlobUpCallImpl implements GlobUpCall, RTruffleObject {
             private ArrayList<String> paths = new ArrayList<>();
 
             @Override
@@ -333,7 +334,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             Function.call_glob.initialize();
             GlobUpCallImpl globUpCallImpl = new GlobUpCallImpl();
             try {
-                ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, JavaInterop.asTruffleFunction(GlobUpCall.class, globUpCallImpl));
+                ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, globUpCallImpl);
             } catch (InteropException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
new file mode 100644
index 0000000000..dbb6ece117
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+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.nodes.Node;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CFactory.TruffleNFI_InvokeCNodeGen;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+
+public class TruffleNFI_C implements CRFFI {
+    public abstract static class TruffleNFI_InvokeCNode extends InvokeCNode {
+
+        @Child Node bindNode = Message.createInvoke(1).createNode();
+
+        @Specialization(guards = "args.length == 0")
+        protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
+                    ForeignAccess.sendExecute(executeNode, callFunction);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        public static Node createExecute(int n) {
+            return Message.createExecute(n).createNode();
+        }
+
+    }
+
+    @Override
+    public InvokeCNode createInvokeCNode() {
+        return TruffleNFI_InvokeCNodeGen.create();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
index 375711ebea..85f48b8d1d 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
@@ -39,7 +39,6 @@ import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CallFactory.Truffl
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
 import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
new file mode 100644
index 0000000000..9baa8a5011
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+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.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+
+public class TruffleNFI_Misc implements MiscRFFI {
+
+    private static class TruffleNFI_ExactSumNode extends ExactSumNode {
+        @Child Node messageNode = Message.createExecute(4).createNode();
+        private TruffleObject function;
+
+        @Override
+        public double execute(double[] values, boolean hasNa, boolean naRm) {
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind("exactSumFunc", false, "([double], sint32, sint32, sint32): double");
+            }
+            try {
+                return (double) ForeignAccess.sendExecute(messageNode, function, JavaInterop.asTruffleObject(values), values.length, hasNa ? 1 : 0, naRm ? 1 : 0);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    @Override
+    public ExactSumNode createExactSumNode() {
+        return new TruffleNFI_ExactSumNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
index f9a3e37eaa..50b713e962 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 
 public class TruffleNFI_PCRE implements PCRERFFI {
@@ -95,12 +96,12 @@ public class TruffleNFI_PCRE implements PCRERFFI {
         }
     }
 
-    private static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode {
+    public static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode {
         interface CaptureNames {
             void addName(int i, String name);
         }
 
-        final class CaptureNamesImpl implements CaptureNames {
+        public static final class CaptureNamesImpl implements CaptureNames, RTruffleObject {
             private final String[] captureNames;
 
             private CaptureNamesImpl(int captureCount) {
@@ -120,7 +121,7 @@ public class TruffleNFI_PCRE implements PCRERFFI {
             try {
                 CaptureNamesImpl captureNamesImpl = new CaptureNamesImpl(captureCount);
                 int result = (int) ForeignAccess.sendExecute(Function.getcapturenames.executeNode, Function.getcapturenames.function,
-                                JavaInterop.asTruffleFunction(CaptureNames.class, captureNamesImpl), code, extra);
+                                captureNamesImpl, code, extra);
                 if (result < 0) {
                     CompilerDirectives.transferToInterpreter();
                     throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result);
@@ -134,12 +135,12 @@ public class TruffleNFI_PCRE implements PCRERFFI {
 
     }
 
-    private static class TruffleNFI_CompileNode extends CompileNode {
+    public static class TruffleNFI_CompileNode extends CompileNode {
         interface MakeResult {
             void makeresult(long pcreResult, String errorMessage, int errOffset);
         }
 
-        private static class MakeResultImpl implements MakeResult {
+        public static class MakeResultImpl implements MakeResult, RTruffleObject {
             private PCRERFFI.Result result;
 
             @Override
@@ -153,7 +154,7 @@ public class TruffleNFI_PCRE implements PCRERFFI {
             Function.compile.initialize();
             try {
                 MakeResultImpl makeResultImpl = new MakeResultImpl();
-                ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, JavaInterop.asTruffleFunction(MakeResult.class, makeResultImpl),
+                ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, makeResultImpl,
                                 pattern, options, tables);
                 return makeResultImpl.result;
             } catch (InteropException e) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
new file mode 100644
index 0000000000..798001ff89
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+
+public class TruffleNFI_REmbed implements REmbedRFFI {
+
+    @Override
+    public void suicide(String x) {
+        throw RInternalError.unimplemented();
+
+    }
+
+    @Override
+    public void cleanUp(int type, int x, int y) {
+        throw RInternalError.unimplemented();
+
+    }
+
+    @Override
+    public String readConsole(String prompt) {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public void writeConsole(String x) {
+        throw RInternalError.unimplemented();
+
+    }
+
+    @Override
+    public void writeErrConsole(String x) {
+        throw RInternalError.unimplemented();
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
index d884490e87..fba810c5c1 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
@@ -27,21 +27,26 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.GridRFFI;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 import com.oracle.truffle.r.runtime.ffi.LibPaths;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid;
 
-public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
+public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI {
     private static class ContextStateImpl implements RContext.ContextState {
         @Override
         public ContextState initialize(RContext context) {
@@ -58,7 +63,21 @@ public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
         return new ContextStateImpl();
     }
 
-    @CompilationFinal private CallRFFI callRFFI;
+    @Override
+    protected RFFI createRFFI() {
+        return this;
+    }
+
+    @CompilationFinal private CRFFI cRFFI;
+
+    @Override
+    public CRFFI getCRFFI() {
+        if (cRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            cRFFI = new TruffleNFI_C();
+        }
+        return cRFFI;
+    }
 
     @CompilationFinal private BaseRFFI baseRFFI;
 
@@ -71,6 +90,8 @@ public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
         return baseRFFI;
     }
 
+    @CompilationFinal private CallRFFI callRFFI;
+
     @Override
     public CallRFFI getCallRFFI() {
         if (callRFFI == null) {
@@ -165,4 +186,35 @@ public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
         return toolsRFFI;
     }
 
+    private REmbedRFFI rEmbedRFFI;
+
+    @Override
+    public REmbedRFFI getREmbedRFFI() {
+        if (rEmbedRFFI == null) {
+            rEmbedRFFI = new TruffleNFI_REmbed();
+        }
+        return rEmbedRFFI;
+    }
+
+    @CompilationFinal private GridRFFI gridRFFI;
+
+    @Override
+    public GridRFFI getGridRFFI() {
+        if (gridRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            gridRFFI = new Generic_Grid();
+        }
+        return gridRFFI;
+    }
+
+    private MiscRFFI miscRFFI;
+
+    @Override
+    public MiscRFFI getMiscRFFI() {
+        if (miscRFFI == null) {
+            miscRFFI = new TruffleNFI_Misc();
+        }
+        return miscRFFI;
+    }
+
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
index 6eb12e4527..dd72b7e5e0 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
@@ -50,7 +51,7 @@ public class TruffleNFI_Tools implements ToolsRFFI {
             int getc(RConnection conn);
         }
 
-        private static class RConnGetCImpl implements RConnGetC {
+        private static class RConnGetCImpl implements RConnGetC, RTruffleObject {
             @Override
             public int getc(RConnection conn) {
                 RFFIUtils.traceUpCall("getc");
@@ -87,7 +88,7 @@ public class TruffleNFI_Tools implements ToolsRFFI {
             Node executeNode = Message.createExecute(1).createNode();
             try {
                 TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "((object): sint32): void");
-                ForeignAccess.sendExecute(executeNode, function, JavaInterop.asTruffleFunction(RConnGetC.class, new RConnGetCImpl()));
+                ForeignAccess.sendExecute(executeNode, function, new RConnGetCImpl());
             } catch (InteropException t) {
                 throw RInternalError.shouldNotReachHere(t);
             }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
deleted file mode 100644
index c52ed611c6..0000000000
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <rffiutils.h>
-
-typedef void (*callVoid0func)();
-
-Call_callVoid0(long address) {
-//	jmp_buf error_jmpbuf;
-//	callEnter(env, &error_jmpbuf);
-//	if (!setjmp(error_jmpbuf)) {
-		callVoid0func call1 = (callVoid0func) address;
-		(*call1)();
-//	}
-//	callExit(env);
-}
-
-typedef void (*callVoid1func)(SEXP arg1);
-
-
-Call_callVoid1(long address, TruffleObject *arg1) {
-//	jmp_buf error_jmpbuf;
-//	callEnter(env, &error_jmpbuf);
-//	if (!setjmp(error_jmpbuf)) {
-		callVoid0func call1 = (callVoid0func) address;
-		(*call1)(arg1);
-//	}
-//	callExit(env);
-}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c
new file mode 100644
index 0000000000..f5ccdf078a
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <rffiutils.h>
+
+double exactSumFunc(double* contents, int length, int hasNa, int naRm) {
+
+	long double sum = 0;
+	int i = 0;
+	if (!hasNa) {
+		for (; i < length - 3; i+= 4) {
+			sum += contents[i];
+			sum += contents[i + 1];
+			sum += contents[i + 2];
+			sum += contents[i + 3];
+		}
+	}
+	for (; i < length; i++) {
+		double value = contents[i];
+		if (R_IsNA(value)) {
+			if (!naRm) {
+				return R_NaReal;
+			}
+		} else {
+			sum += value;
+		}
+	}
+
+	return sum;
+}
-- 
GitLab


From dc8142b0b006bdb2065f6a4ad395ce085ee52257 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 18 Apr 2017 13:01:53 +0200
Subject: [PATCH 331/402] Remove obsoleted grid RFFI support

---
 .../ffi/nfi/TruffleNFI_RFFIFactory.java       |  13 ---
 .../truffle/r/library/grid/GridFunctions.java | 109 ------------------
 .../truffle/r/nodes/test/ExtBuiltinsList.java |   3 -
 .../r/runtime/ffi/generic/Generic_Grid.java   |  87 --------------
 .../r/runtime/ffi/jni/JNI_RFFIFactory.java    |  13 ---
 .../truffle/r/runtime/ffi/GridRFFI.java       |  49 --------
 .../oracle/truffle/r/runtime/ffi/RFFI.java    |   4 +-
 .../ffi/managed/Managed_RFFIFactory.java      |  17 ---
 mx.fastr/copyrights/overrides                 |   1 -
 9 files changed, 1 insertion(+), 295 deletions(-)
 delete mode 100644 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
 delete mode 100644 com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java
 delete mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
index fba810c5c1..a892fb8876 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.GridRFFI;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 import com.oracle.truffle.r.runtime.ffi.LibPaths;
 import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
@@ -44,7 +43,6 @@ import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid;
 
 public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI {
     private static class ContextStateImpl implements RContext.ContextState {
@@ -196,17 +194,6 @@ public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI {
         return rEmbedRFFI;
     }
 
-    @CompilationFinal private GridRFFI gridRFFI;
-
-    @Override
-    public GridRFFI getGridRFFI() {
-        if (gridRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            gridRFFI = new Generic_Grid();
-        }
-        return gridRFFI;
-    }
-
     private MiscRFFI miscRFFI;
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
deleted file mode 100644
index a5b48baf87..0000000000
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (C) 2001-3 Paul Murrell
- * Copyright (c) 1998-2013, The R Core Team
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.library.grid;
-
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.GridRFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-
-/**
- * The .Call support for the grid package.
- */
-public class GridFunctions {
-
-    public abstract static class InitGrid extends RExternalBuiltinNode.Arg1 {
-        @Child GridRFFI.InitGridNode initGridNode = RFFIFactory.getRFFI().getGridRFFI().createInitGridNode();
-
-        static {
-            Casts casts = new Casts(InitGrid.class);
-            casts.arg(0).mustBe(REnvironment.class);
-        }
-
-        @Specialization
-        @TruffleBoundary
-        protected Object initGrid(REnvironment gridEvalEnv) {
-            return initGridNode.execute(gridEvalEnv);
-        }
-
-        @Fallback
-        protected Object initGridFallback(@SuppressWarnings("unused") Object x) {
-            return RNull.instance;
-        }
-    }
-
-    public static final class KillGrid extends RExternalBuiltinNode {
-        @Child GridRFFI.KillGridNode killGridNode = RFFIFactory.getRFFI().getGridRFFI().createKillGridNode();
-
-        static {
-            Casts.noCasts(KillGrid.class);
-        }
-
-        @Override
-        @TruffleBoundary
-        public Object call(RArgsValuesAndNames args) {
-            return killGridNode.execute();
-        }
-    }
-
-    public abstract static class ValidUnits extends RExternalBuiltinNode.Arg1 {
-
-        static {
-            Casts casts = new Casts(ValidUnits.class);
-            casts.arg(0).mustBe(stringValue(), RError.Message.GENERIC, "'units' must be character").asStringVector().mustBe(notEmpty(), RError.Message.GENERIC, "'units' must be of length > 0");
-        }
-
-        @Specialization
-        protected RIntVector validUnits(RAbstractStringVector units) {
-            int[] data = new int[units.getLength()];
-            for (int i = 0; i < data.length; i++) {
-                int code = convertUnit(units.getDataAt(i));
-                if (code < 0) {
-                    throw error(RError.Message.GENERIC, "Invalid unit");
-                }
-                data[i] = code;
-            }
-            return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
-        }
-
-        private enum UnitTab {
-            npc(0);
-
-            private final int code;
-
-            UnitTab(int code) {
-                this.code = code;
-            }
-        }
-
-        private static int convertUnit(String unit) {
-            for (UnitTab unitTab : UnitTab.values()) {
-                if (unit.equals(unitTab.name())) {
-                    return unitTab.code;
-                }
-            }
-            return -1;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
index 1035f57473..f7488cc482 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ExtBuiltinsList.java
@@ -80,9 +80,6 @@ public class ExtBuiltinsList {
                     com.oracle.truffle.r.library.stats.CompleteCases.class,
                     com.oracle.truffle.r.library.stats.CdistNodeGen.class,
                     com.oracle.truffle.r.library.stats.BinDistNodeGen.class,
-                    com.oracle.truffle.r.library.grid.GridFunctionsFactory.InitGridNodeGen.class,
-                    com.oracle.truffle.r.library.grid.GridFunctionsFactory.ValidUnitsNodeGen.class,
-                    com.oracle.truffle.r.library.grid.GridFunctions.KillGrid.class,
                     com.oracle.truffle.r.library.methods.SubstituteDirectNodeGen.class,
                     com.oracle.truffle.r.library.methods.SlotFactory.R_getSlotNodeGen.class,
                     com.oracle.truffle.r.library.methods.SlotFactory.R_setSlotNodeGen.class,
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java
deleted file mode 100644
index 8aad787c55..0000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.ffi.generic;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.CallRFFI;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
-import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.ffi.GridRFFI;
-import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-
-public class Generic_Grid implements GridRFFI {
-    private static final String GRID = "grid";
-
-    private static class Generic_InitGridNode extends InitGridNode {
-        private static final String L_InitGrid = "L_initGrid";
-        @Child private CallRFFI.InvokeCallNode invokeCallNode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
-        @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
-        @CompilationFinal private NativeCallInfo initNativeCallInfo;
-
-        @Override
-        public Object execute(REnvironment gridEvalEnv) {
-            if (initNativeCallInfo == null) {
-                initNativeCallInfo = createNativeCallInfo(L_InitGrid, findSymbolNode);
-            }
-            return invokeCallNode.execute(initNativeCallInfo, new Object[]{gridEvalEnv});
-        }
-    }
-
-    private static class Generic_KillGridNode extends KillGridNode {
-        private static final String L_KillGrid = "L_killGrid";
-        @Child private CallRFFI.InvokeCallNode invokeCallNode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
-        @Child DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
-        @CompilationFinal private NativeCallInfo killNativeCallInfo;
-
-        @Override
-        public Object execute() {
-            if (killNativeCallInfo == null) {
-                killNativeCallInfo = createNativeCallInfo(L_KillGrid, findSymbolNode);
-            }
-            return invokeCallNode.execute(killNativeCallInfo, new Object[0]);
-        }
-
-    }
-
-    private static NativeCallInfo createNativeCallInfo(String call, DLL.RFindSymbolNode findSymbolNode) {
-        DLLInfo dllInfo = DLL.findLibrary(GRID);
-        assert dllInfo != null;
-        SymbolHandle symbolHandle = findSymbolNode.execute(call, GRID, DLL.RegisteredNativeSymbol.any());
-        assert symbolHandle != DLL.SYMBOL_NOT_FOUND;
-        return new NativeCallInfo(call, symbolHandle, dllInfo);
-    }
-
-    @Override
-    public InitGridNode createInitGridNode() {
-        return new Generic_InitGridNode();
-    }
-
-    @Override
-    public KillGridNode createKillGridNode() {
-        return new Generic_KillGridNode();
-    }
-
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
index 28f516f7c6..0ec293f8b1 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.GridRFFI;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 import com.oracle.truffle.r.runtime.ffi.LibPaths;
 import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
@@ -44,7 +43,6 @@ import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid;
 import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools;
 
 /**
@@ -146,17 +144,6 @@ public class JNI_RFFIFactory extends RFFIFactory implements RFFI {
         return toolsRFFI;
     }
 
-    @CompilationFinal private GridRFFI gridRFFI;
-
-    @Override
-    public GridRFFI getGridRFFI() {
-        if (gridRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            gridRFFI = new Generic_Grid();
-        }
-        return gridRFFI;
-    }
-
     @CompilationFinal private UserRngRFFI userRngRFFI;
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java
deleted file mode 100644
index 43082161ce..0000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/GridRFFI.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.ffi;
-
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-
-public interface GridRFFI {
-    abstract class InitGridNode extends Node {
-        public abstract Object execute(REnvironment gridEvalEnv);
-
-        public static InitGridNode create() {
-            return RFFIFactory.getRFFI().getGridRFFI().createInitGridNode();
-        }
-    }
-
-    abstract class KillGridNode extends Node {
-
-        public abstract Object execute();
-
-        public static KillGridNode create() {
-            return RFFIFactory.getRFFI().getGridRFFI().createKillGridNode();
-        }
-    }
-
-    InitGridNode createInitGridNode();
-
-    KillGridNode createKillGridNode();
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
index ccc6224ba1..12c23e7e6d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,8 +61,6 @@ public interface RFFI {
 
     ToolsRFFI getToolsRFFI();
 
-    GridRFFI getGridRFFI();
-
     CRFFI getCRFFI();
 
     CallRFFI getCallRFFI();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
index f5ec388349..36a30ba75a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.GridRFFI;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
@@ -109,22 +108,6 @@ public class Managed_RFFIFactory extends RFFIFactory implements RFFI {
         };
     }
 
-    // TODO: will be removed anyway
-    @Override
-    public GridRFFI getGridRFFI() {
-        return new GridRFFI() {
-            @Override
-            public InitGridNode createInitGridNode() {
-                return null;
-            }
-
-            @Override
-            public KillGridNode createKillGridNode() {
-                return null;
-            }
-        };
-    }
-
     @Override
     public CRFFI getCRFFI() {
         return new CRFFI() {
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 45a5520630..b767f7c545 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -1,6 +1,5 @@
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java,gnu_r_graphics.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java,gnu_r_graphics.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/grid/GridFunctions.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Arithmetic.java,gnu_r_gentleman_ihaka.copyright
-- 
GitLab


From dedb9c5029bb35e67eab22cf5f83599eb2c24b5e Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 27 Apr 2017 18:37:07 +0200
Subject: [PATCH 332/402] Fix: Typo in CURL library path.

---
 ci.hocon | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/ci.hocon b/ci.hocon
index 240265cada..7248925ba3 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -34,7 +34,7 @@ logfiles : [
 pkgEnvironment: {
   environment : {
     PKG_INCLUDE_FLAGS_OVERRIDE : """-I/cm/shared/apps/zlib/1.2.8/include -I/cm/shared/apps/bzip2/1.0.6/include -I/cm/shared/apps/xz/5.2.2/include -I/cm/shared/apps/pcre/8.38/include -I/cm/shared/apps/curl/7.50.1/include"""
-    PKG_LDFLAGS_OVERRIDE : """"-L/cm/shared/apps/zlib/1.2.8/lib -L/cm/shared/apps/bzip2/1.0.6/lib -L/cm/shared/apps/xz/5.2.2/lib -L/cm/shared/apps/pcre/8.38/lib -L/cm/shared/apps/curl/7.50.1//lib -L/cm/shared/apps/gcc/4.9.1/lib64""""
+    PKG_LDFLAGS_OVERRIDE : """"-L/cm/shared/apps/zlib/1.2.8/lib -L/cm/shared/apps/bzip2/1.0.6/lib -L/cm/shared/apps/xz/5.2.2/lib -L/cm/shared/apps/pcre/8.38/lib -L/cm/shared/apps/curl/7.50.1/lib -L/cm/shared/apps/gcc/4.9.1/lib64""""
   }
 }
 
@@ -49,6 +49,7 @@ packagesLinux : ${pkgEnvironment} {
     readline : "==6.3"
     pcre : ">=8.38"
     z : ">=1.2.8"
+    curl : ">=7.50.1"
   }
 }
 
@@ -58,6 +59,7 @@ packagesDarwin : {
   "xz" : ""
   "pcre" : ""
   "z" : ""
+  "curl" : ""
 }
 
 # Common settings for all builds but note that it uses the Linux package settings,
-- 
GitLab


From 25a3c0a41c94e376c819338a777bd5e6141544b3 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 28 Apr 2017 10:05:06 +0200
Subject: [PATCH 333/402] Add more truffle boundaries

---
 .../interop/ffi/nfi/TruffleNFI_Base.java      |  3 +
 .../interop/ffi/nfi/TruffleNFI_DLL.java       |  3 +-
 .../interop/ffi/nfi/TruffleNFI_Utils.java     |  4 +-
 .../truffle/r/library/fastrGrid/LNewPage.java |  8 ++-
 .../truffle/r/library/fastrGrid/LPretty.java  |  2 +
 .../r/library/fastrGrid/device/SVGDevice.java |  5 +-
 .../truffle/r/library/stats/deriv/Deriv.java  | 58 +++++++++++++++----
 .../base/infix/ProfiledSpecialsUtils.java     |  3 +
 .../variables/LocalReadVariableNode.java      |  1 +
 .../truffle/r/nodes/unary/ToStringNode.java   |  3 +-
 .../truffle/r/runtime/ffi/LibPaths.java       |  6 +-
 .../oracle/truffle/r/runtime/RDeparse.java    |  3 +-
 .../oracle/truffle/r/runtime/REnvVars.java    |  1 +
 .../com/oracle/truffle/r/runtime/RError.java  |  2 +-
 .../oracle/truffle/r/runtime/RProfile.java    |  2 +
 .../r/runtime/conn/DelegateRConnection.java   |  5 ++
 .../r/runtime/conn/FileConnections.java       |  2 +
 .../r/runtime/nmath/GammaFunctions.java       |  2 +-
 .../truffle/r/runtime/nmath/distr/Pnorm.java  | 37 +++++++++---
 .../truffle/r/runtime/nmath/distr/SNorm.java  |  3 +-
 20 files changed, 121 insertions(+), 32 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
index 7e9c053144..3ad8a7f1da 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.engine.interop.ffi.nfi;
 import java.io.IOException;
 import java.util.ArrayList;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
@@ -90,6 +91,7 @@ public class TruffleNFI_Base implements BaseRFFI {
     }
 
     public static class TruffleNFI_GetwdNode extends GetwdNode {
+        @TruffleBoundary
         @Override
         public String execute() {
             byte[] buf = new byte[4096];
@@ -180,6 +182,7 @@ public class TruffleNFI_Base implements BaseRFFI {
     }
 
     public static class TruffleNFI_MkdtempNode extends MkdtempNode {
+        @TruffleBoundary
         @Override
         public String execute(String template) {
             /*
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
index 36cfaaa2d3..fe390032a4 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,7 @@ public class TruffleNFI_DLL implements DLLRFFI {
 
     private static class TruffleNFI_DLOpenNode extends DLLRFFI.DLOpenNode {
 
+        @TruffleBoundary
         @Override
         public Object execute(String path, boolean local, boolean now) {
             String libName = DLL.libName(path);
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
index 92a0e6dcb4..55b6efe6d4 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 import java.nio.charset.StandardCharsets;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
@@ -57,6 +58,7 @@ public class TruffleNFI_Utils {
 
     private static TruffleObject defaultLibrary;
 
+    @TruffleBoundary
     private static void initDefaultLibrary() {
         if (defaultLibrary == null) {
             Env env = RContext.getInstance().getEnv();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 95c5e9bcfd..1b234eda3a 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -12,6 +12,7 @@
 package com.oracle.truffle.r.library.fastrGrid;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
@@ -29,7 +30,7 @@ final class LNewPage extends RExternalBuiltinNode {
     public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
         GridDevice device = GridContext.getContext().getCurrentDevice();
         if (GridContext.getContext().getGridState().isDeviceInitialized()) {
-            device.openNewPage();
+            openNewPage(device);
             return RNull.instance;
         }
         // There are some exceptions to the rule that any external call from grid R code is
@@ -38,6 +39,11 @@ final class LNewPage extends RExternalBuiltinNode {
         return gridDirty.call(frame, RArgsValuesAndNames.EMPTY);
     }
 
+    @TruffleBoundary
+    private static void openNewPage(GridDevice device) {
+        device.openNewPage();
+    }
+
     @Override
     protected Object call(RArgsValuesAndNames args) {
         assert false : "should be shadowed by the overload with frame";
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java
index 1ff6bb3f11..2d447deb2c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java
@@ -14,6 +14,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.nmath.TOMS708.fabs;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.PrettyIntevals;
@@ -42,6 +43,7 @@ public abstract class LPretty extends RExternalBuiltinNode.Arg1 {
         }
 
         if (Double.isInfinite(min) || Double.isInfinite(max)) {
+            CompilerDirectives.transferToInterpreter();
             throw error(Message.GENERIC, String.format("infinite axis extents [GEPretty(%g,%g,5)]", min, max));
         }
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
index 702a586e3c..063847725f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyl
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineEnd;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.Utils;
 
 public class SVGDevice implements GridDevice {
     private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000");
@@ -250,11 +251,11 @@ public class SVGDevice implements GridDevice {
     }
 
     private static String getStyleColor(String prefix, GridColor color) {
-        return String.format("%s:rgb(%d,%d,%d);%s-opacity:%.3f", prefix, color.getRed(), color.getGreen(), color.getBlue(), prefix, (double) color.getAlpha() / 255d);
+        return Utils.stringFormat("%s:rgb(%d,%d,%d);%s-opacity:%.3f", prefix, color.getRed(), color.getGreen(), color.getBlue(), prefix, color.getAlpha() / 255d);
     }
 
     private void append(String fmt, Object... args) {
-        data.append(String.format(fmt + "\n", args));
+        data.append(Utils.stringFormat(fmt + "\n", args));
     }
 
     private double transY(double y) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
index d822fac092..d3dad0bc79 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
@@ -27,8 +27,8 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.stream.Collectors;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -149,6 +149,43 @@ public abstract class Deriv extends RExternalBuiltinNode {
     }
 
     private Object derive(VirtualFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return findDerive(elem, names, functionArg, tag, hessian).getResult(frame);
+    }
+
+    private static final class DerivResult {
+        private final RExpression result;
+        private final RSyntaxNode blockCall;
+        private final List<Argument<RSyntaxNode>> targetArgs;
+
+        private DerivResult(RExpression result) {
+            this.result = result;
+            blockCall = null;
+            targetArgs = null;
+        }
+
+        private DerivResult(RSyntaxNode blockCall, List<Argument<RSyntaxNode>> targetArgs) {
+            this.blockCall = blockCall;
+            this.targetArgs = targetArgs;
+            result = null;
+        }
+
+        private Object getResult(VirtualFrame frame) {
+            if (result != null) {
+                return result;
+            }
+            RootCallTarget callTarget = getRootCallTarget();
+            FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame);
+            return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame.materialize());
+        }
+
+        @TruffleBoundary
+        private RootCallTarget getRootCallTarget() {
+            return RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
+        }
+    }
+
+    @TruffleBoundary
+    private DerivResult findDerive(RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
         LinkedList<RSyntaxNode> exprlist = new LinkedList<>();
         int fIndex = findSubexpression(elem, exprlist, tag);
 
@@ -275,7 +312,10 @@ public abstract class Deriv extends RExternalBuiltinNode {
         // prune exprlist
         exprlist.removeAll(Collections.singleton(null));
 
-        List<Argument<RSyntaxNode>> blockStatements = exprlist.stream().map(e -> RCodeBuilder.argument(e)).collect(Collectors.toList());
+        List<Argument<RSyntaxNode>> blockStatements = new ArrayList<>(exprlist.size());
+        for (RSyntaxNode e : exprlist) {
+            blockStatements.add(RCodeBuilder.argument(e));
+        }
         RSyntaxNode blockCall = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.create("{"), blockStatements);
 
         if (functionArg instanceof RAbstractStringVector) {
@@ -285,14 +325,14 @@ public abstract class Deriv extends RExternalBuiltinNode {
                 targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, funArgNames.getDataAt(i), ConstantNode.create(RMissing.instance)));
             }
 
-            return createFunction(frame, blockCall, targetArgs);
+            return new DerivResult(blockCall, targetArgs);
         } else if (functionArg == Boolean.TRUE) {
             List<Argument<RSyntaxNode>> targetArgs = new ArrayList<>();
             for (int i = 0; i < names.getLength(); i++) {
                 targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, names.getDataAt(i), ConstantNode.create(RMissing.instance)));
             }
 
-            return createFunction(frame, blockCall, targetArgs);
+            return new DerivResult(blockCall, targetArgs);
         } else if (functionArg instanceof RFunction) {
             RFunction funTemplate = (RFunction) functionArg;
             FormalArguments formals = ((RRootNode) funTemplate.getRootNode()).getFormalArguments();
@@ -302,21 +342,15 @@ public abstract class Deriv extends RExternalBuiltinNode {
                 targetArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, formals.getSignature().getName(i), cloneElement((RSyntaxNode) defArgs[i])));
             }
 
-            return createFunction(frame, blockCall, targetArgs);
+            return new DerivResult(blockCall, targetArgs);
         } else {
             RLanguage lan = RDataFactory.createLanguage(blockCall.asRNode());
             RExpression res = RDataFactory.createExpression(new Object[]{lan});
-            return res;
+            return new DerivResult(res);
         }
 
     }
 
-    private static RFunction createFunction(VirtualFrame frame, RSyntaxNode blockCall, List<Argument<RSyntaxNode>> targetArgs) {
-        RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
-        FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame);
-        return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame.materialize());
-    }
-
     private int findSubexpression(RBaseNode expr, List<RSyntaxNode> exprlist, String tag) {
         if (!(expr instanceof RSyntaxElement)) {
             throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
index fe6a876c60..4d9d655c07 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
@@ -62,6 +62,7 @@ public class ProfiledSpecialsUtils {
         @Specialization(replaces = "access")
         public Object accessGeneric(VirtualFrame frame, Object vector, Object index) {
             if (defaultAccessNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 defaultAccessNode = insert(createAccessNode());
             }
             return defaultAccessNode.execute(frame, vector, index);
@@ -120,6 +121,7 @@ public class ProfiledSpecialsUtils {
         @Specialization(replaces = "access")
         public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2) {
             if (defaultAccessNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 defaultAccessNode = insert(createAccessNode());
             }
             return defaultAccessNode.execute(frame, vector, index1, index2);
@@ -220,6 +222,7 @@ public class ProfiledSpecialsUtils {
         @Specialization(replaces = "access")
         public Object accessGeneric(VirtualFrame frame, Object vector, Object index1, Object index2, Object value) {
             if (defaultAccessNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 defaultAccessNode = insert(createAccessNode());
             }
             return defaultAccessNode.execute(frame, vector, index1, index2, value);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
index 5e1b476097..4ce17a2cce 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
@@ -101,6 +101,7 @@ public final class LocalReadVariableNode extends Node {
         }
         Object result = null;
         if (isMissingProfile == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
             seenValueKinds = new boolean[FrameSlotKind.values().length];
             valueProfile = ValueProfile.createClassProfile();
             isNullProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
index e4e82a96e6..ba6bf5714f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -148,7 +149,7 @@ public abstract class ToStringNode extends RBaseNode {
         } else {
             throw RInternalError.shouldNotReachHere("S4 object has no class");
         }
-        return String.format("<S4 object of class %s>", clazz);
+        return Utils.stringFormat("<S4 object of class %s>", clazz);
     }
 
     @FunctionalInterface
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java
index 2292780c3f..86b8d0a62c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.runtime.ffi;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RPlatform;
 import com.oracle.truffle.r.runtime.RPlatform.OSInfo;
@@ -34,6 +35,7 @@ public class LibPaths {
     /**
      * Returns the absolute path to the directory containing the builtin libraries.
      */
+    @TruffleBoundary
     public static String getBuiltinLibPath() {
         return FileSystems.getDefault().getPath(REnvVars.rHome(), "lib").toString();
     }
@@ -42,6 +44,7 @@ public class LibPaths {
      * Returns the absolute path to the builtin library {@code libName} for use with
      * {@link System#load}.
      */
+    @TruffleBoundary
     public static String getBuiltinLibPath(String libName) {
         String rHome = REnvVars.rHome();
         OSInfo osInfo = RPlatform.getOSInfo();
@@ -53,6 +56,7 @@ public class LibPaths {
      * Returns the absolute path to the shared library associated with package {@code name}. (Does
      * not check for existence).
      */
+    @TruffleBoundary
     public static String getPackageLibPath(String name) {
         String rHome = REnvVars.rHome();
         String packageDir = "library";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 9cd3ced303..03cdad3ac2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -871,7 +871,7 @@ public class RDeparse {
                     break;
                 case RAWSXP:
                     RRaw r = (RRaw) element;
-                    append(String.format("0x%02x", r.getValue()));
+                    append(Utils.stringFormat("0x%02x", r.getValue()));
                     break;
                 default:
                     throw RInternalError.shouldNotReachHere("unexpected SEXPTYPE: " + type);
@@ -987,6 +987,7 @@ public class RDeparse {
     /**
      * Ensure that {@code node} has a {@link SourceSection} by deparsing if necessary.
      */
+    @TruffleBoundary
     public static void ensureSourceSection(RSyntaxNode node) {
         SourceSection ss = node.getLazySourceSection();
         if (ss == RSyntaxNode.LAZY_DEPARSE) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index e0a2d61e83..87fcb60bbd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -217,6 +217,7 @@ public final class REnvVars implements RContext.ContextState {
     /**
      * Sanity check on the expected structure of an {@code R_HOME}.
      */
+    @TruffleBoundary
     private static boolean validateRHome(Path path, String markerFile) {
         if (path == null) {
             return false;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 0824d30cdd..e31111eb6f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -188,7 +188,7 @@ public final class RError extends RuntimeException {
             }
             current = current.getParent();
         }
-        throw new AssertionError("Could not find RBaseNode for given Node. Is it not adopted in the AST?");
+        throw RInternalError.shouldNotReachHere("Could not find RBaseNode for given Node. Is it not adopted in the AST?");
     }
 
     /**
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
index 50d4e6c01a..80a9f3cad8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
@@ -28,6 +28,7 @@ import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
@@ -45,6 +46,7 @@ public final class RProfile implements RContext.ContextState {
     }
 
     @Override
+    @TruffleBoundary
     public RContext.ContextState initialize(RContext context) {
         String rHome = REnvVars.rHome();
         FileSystem fileSystem = FileSystems.getDefault();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 74bc8391a0..437743ed51 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -230,6 +230,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
      * @return {@code true} if an incomplete line was written; {@code false} otherwise
      * @throws IOException
      */
+    @TruffleBoundary
     public static boolean writeStringHelper(WritableByteChannel out, String s, boolean nl, Charset encoding) throws IOException {
         boolean incomplete;
         final byte[] bytes = s.getBytes(encoding);
@@ -258,6 +259,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
      * @param eos The end-of-string terminator (may be {@code null}).
      * @throws IOException
      */
+    @TruffleBoundary
     public static void writeCharHelper(@NotNull WritableByteChannel channel, @NotNull String s, int pad, String eos) throws IOException {
 
         final byte[] bytes = s.getBytes();
@@ -394,6 +396,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
         }
     }
 
+    @TruffleBoundary
     public static boolean writeLinesHelper(WritableByteChannel out, RAbstractStringVector lines, String sep, Charset encoding) throws IOException {
         if (sep != null && sep.contains("\n")) {
             // fast path: we know that the line is complete
@@ -461,6 +464,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     }
 
     @Override
+    @TruffleBoundary
     public int read(ByteBuffer dst) throws IOException {
         if (cache != null) {
             final int bytesRequested = dst.remaining();
@@ -481,6 +485,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     }
 
     @Override
+    @TruffleBoundary
     public int write(ByteBuffer src) throws IOException {
         return getChannel().write(src);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index 51e1782e0d..b14529c998 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -624,6 +624,7 @@ public class FileConnections {
             return super.readBinChars();
         }
 
+        @TruffleBoundary
         private void setReadPosition() throws IOException {
             if (lastMode != SeekRWMode.READ) {
                 raf.seek(readOffset);
@@ -631,6 +632,7 @@ public class FileConnections {
             }
         }
 
+        @TruffleBoundary
         private void setWritePosition() throws IOException {
             if (lastMode != SeekRWMode.WRITE) {
                 raf.seek(writeOffset);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java
index 6145b2d5b4..8979aeef7d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java
@@ -1052,7 +1052,7 @@ public abstract class GammaFunctions {
         }
         f = res12 / elfb;
 
-        np = new Pnorm().evaluate(s2pt, 0.0, 1.0, !lowerTail, logp);
+        np = Pnorm.createTemp().evaluate(s2pt, 0.0, 1.0, !lowerTail, logp);
 
         if (logp) {
             double ndOverP = dpnorm(s2pt, !lowerTail, np);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java
index bf069e9a01..4bb9d06fc8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java
@@ -22,7 +22,22 @@ import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_2;
 
 public final class Pnorm implements Function3_2 {
 
-    private final BranchProfile nanProfile = BranchProfile.create();
+    private final BranchProfile nanProfile;
+
+    public Pnorm() {
+        this(BranchProfile.create());
+    }
+
+    private Pnorm(BranchProfile nanProfile) {
+        this.nanProfile = nanProfile;
+    }
+
+    /**
+     * For use in a temporary (non-Truffle Node) context.
+     */
+    public static Pnorm createTemp() {
+        return new Pnorm(null);
+    }
 
     @Override
     public double evaluate(double x, double mu, double sigma, boolean lowerTail, boolean logP) {
@@ -31,7 +46,9 @@ public final class Pnorm implements Function3_2 {
          * == mu and sigma == 0, we get the correct answer 1.
          */
         if (Double.isNaN(x) || Double.isNaN(mu) || Double.isNaN(sigma)) {
-            nanProfile.enter();
+            if (nanProfile != null) {
+                nanProfile.enter();
+            }
             return x + mu + sigma;
         }
         if (!Double.isFinite(x) && mu == x) {
@@ -40,7 +57,9 @@ public final class Pnorm implements Function3_2 {
         }
         if (sigma <= 0) {
             if (sigma < 0) {
-                nanProfile.enter();
+                if (nanProfile != null) {
+                    nanProfile.enter();
+                }
                 return Double.NaN;
             }
             /* sigma = 0 : */
@@ -170,24 +189,24 @@ public final class Pnorm implements Function3_2 {
                 /*
                  * else |x| > sqrt(32) = 5.657 : the next two case differentiations were really for
                  * lower=T, log=F Particularly *not* for log_p !
-                 * 
+                 *
                  * Cody had (-37.5193 < x && x < 8.2924) ; R originally had y < 50
-                 * 
+                 *
                  * Note that we do want symmetry(0), lower/upper -> hence use y
                  */
             } else if ((logP && y < 1e170) /* avoid underflow below */
             /*
              * ^^^^^ MM FIXME: can speedup for log_p and much larger |x| ! Then, make use of
              * Abramowitz & Stegun, 26.2.13, something like
-             * 
+             *
              * xsq = x*x;
-             * 
+             *
              * if(xsq * DBL_EPSILON < 1.) del = (1. - (1. - 5./(xsq+6.)) / (xsq+4.)) / (xsq+2.);
              * else del = 0.;cum = -.5*xsq - M_LN_SQRT_2PI - log(x) + log1p(-del);ccum =
              * log1p(-exp(*cum)); /.* ~ log(1) = 0 *./
-             * 
+             *
              * swap_tail;
-             * 
+             *
              * [Yes, but xsq might be infinite.]
              */
                             || (lower && -37.5193 < x && x < 8.2924) || (upper && -8.2924 < x && x < 37.5193)) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java
index 07ff51a339..7549bbc492 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java
@@ -351,7 +351,8 @@ public final class SNorm {
                 return 0d; // can NEVER reach here (infinite loop ahead)
 
             default:
-                throw new AssertionError();
+                assert false;
+                return 0d;
         }
     }
 }
-- 
GitLab


From 0c3fa14254ab98657f42ed37f6b8e4145a792f53 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Sat, 29 Apr 2017 12:07:52 -0700
Subject: [PATCH 334/402] [GR-3516] unset ENABLE_NLS for FastR; remove all
 native code build warnings

---
 .gitignore                                    |  4 +++-
 .../fficall/src/common/unimplemented.c        |  3 ++-
 .../fficall/src/jni/Connections.c             | 11 +++++----
 .../fficall/src/jni/Rdynload_fastr.c          |  4 ++--
 .../fficall/src/jni/Rinternals.c              | 24 ++++---------------
 .../fficall/src/jni/pcre_rffi.c               | 14 +++++------
 .../fficall/src/jni/rffiutils.c               |  2 --
 .../fficall/src/jni/rffiutils.h               |  4 ++--
 .../fficall/src/jni/variables.c               |  3 ++-
 com.oracle.truffle.r.native/include/Makefile  |  3 +--
 .../include/src/libintl.h                     |  1 -
 com.oracle.truffle.r.native/version.source    |  2 +-
 mx.fastr/copyrights/overrides                 |  1 -
 mx.fastr/mx_fastr_edinclude.py                | 17 +++++++++++++
 14 files changed, 47 insertions(+), 46 deletions(-)
 delete mode 100644 com.oracle.truffle.r.native/include/src/libintl.h

diff --git a/.gitignore b/.gitignore
index fa2967697f..0fb47b974b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,7 +28,7 @@
 /com.oracle.truffle.r.native/include/*.h
 /com.oracle.truffle.r.native/include/R_ext/*.h
 /com.oracle.truffle.r.native/include/linked
-/com.oracle.truffle.r.native/fficall/jni.done
+/com.oracle.truffle.r.native/fficall/fficall.done
 /com.oracle.truffle.r.native/fficall/jniboot.done
 /com.oracle.truffle.r.native.recommended/install.recommended
 /com.oracle.truffle.r.test.native/packages/copy_recommended
@@ -89,6 +89,7 @@ output.txt
 output.cfg
 .cfg
 **/nbproject/**
+
 **/build.xml
 /scratch/
 /test.fastr/
@@ -138,3 +139,4 @@ bench-results.json
 com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/asTests.R
 com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/coerceTests.R
 com.oracle.truffle.r.native/version.built
+documentation/.pydevproject
diff --git a/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c b/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c
index 28dc2ccca5..4dbe601ee0 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c
+++ b/com.oracle.truffle.r.native/fficall/src/common/unimplemented.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2015, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -142,6 +142,7 @@ void* PRIMFUN(SEXP x) {
 
 SEXP coerceToSymbol(SEXP v) {
 	unimplemented("coerceToSymbol");
+	return NULL;
 }
 
 int IntegerFromString(SEXP a, int* b) {
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 0cf9704787..5a7fbf2b02 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
@@ -46,14 +46,14 @@ static jbyteArray wrap(JNIEnv *thisenv, void* buf, size_t n) {
  * Otherwise an error is issued.
  */
 static int getFd(Rconnection con) {
-	return con->id;
+	return (int) con->id;
 }
 
 /*
  * Sets the file descriptor for the connection.
  */
 static void setFd(Rconnection con, jint fd) {
-	con->id = fd;
+	con->id = (void *) (jlong) fd;
 }
 
 
@@ -134,6 +134,7 @@ static void NORET null_truncate(Rconnection con)
 
 static int null_fflush(Rconnection con)
 {
+	return 0;
 }
 
 static size_t NORET null_read(void *ptr, size_t size, size_t nitems,
@@ -206,7 +207,7 @@ SEXP R_new_custom_connection(const char *description, const char *mode, const ch
 			free(new);
 			error(_("allocation of %s connection failed"), class_name);
 		}
-		init_con(new, description, CE_NATIVE, mode);
+		init_con(new, (char *) description, CE_NATIVE, mode);
 		/* all ptrs are init'ed to null_* so no need to repeat that,
 		 but the following two are useful tools which could not be accessed otherwise */
 		// TODO dummy_vfprintf and dummy_fgetc not implemented yet
@@ -271,7 +272,7 @@ SEXP __GetFlagNativeConnection(SEXP rConnAddrObj, jstring jname) {
 	}else if(strcmp(name, "blocking") == 0) {
 		result = con->blocking;
 	}
-	free(name);
+	free((char *)name);
 
 	return ScalarLogical(result);
 }
@@ -406,7 +407,7 @@ Rconnection R_GetConnection(SEXP sConn) {
 
 	init_con(new, sSummaryDesc, 0, sOpenMode);
 	free(sOpenMode);
-	new->class = sConnClass;
+	new->class = (char *) sConnClass;
 	new->canseek = seekable;
 
 	setFd(new, fd);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
index d6e16e35f3..ebf731f63f 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -151,5 +151,5 @@ DL_FUNC R_FindSymbol(char const *name, char const *pkg,
 
 DllInfo *R_getEmbeddingDllInfo(void) {
 	JNIEnv *thisenv = getEnv();
-	return (*thisenv)->CallStaticObjectMethod(thisenv, JNI_PkgInitClass, getEmbeddingDllInfoID);
+	return (DllInfo*) (*thisenv)->CallStaticObjectMethod(thisenv, JNI_PkgInitClass, getEmbeddingDllInfoID);
 }
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 7a21ecaa62..f2e058cf9e 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -616,7 +616,6 @@ void Rf_error(const char *format, ...) {
 	(*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_errorMethodID, string);
 	// just transfer back which will cleanup and exit the entire JNI call
 	longjmp(*getErrorJmpBuf(), 1);
-
 }
 
 void Rf_errorcall(SEXP x, const char *format, ...) {
@@ -1077,7 +1076,7 @@ SEXP PRVALUE(SEXP x) {
 
 int PRSEEN(SEXP x) {
     JNIEnv *thisenv = getEnv();
-    return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, PRSEENMethodID, x);
+    return (int) (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, PRSEENMethodID, x);
 }
 
 void SET_PRSEEN(SEXP x, int v) {
@@ -1099,7 +1098,7 @@ void SET_PRCODE(SEXP x, SEXP v) {
 int LENGTH(SEXP x) {
     TRACE(TARGp, x);
     JNIEnv *thisenv = getEnv();
-    return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, LENGTH_MethodID, x);
+    return (int) (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, LENGTH_MethodID, x);
 }
 
 int TRUELENGTH(SEXP x){
@@ -1218,9 +1217,8 @@ SEXP *STRING_PTR(SEXP x){
 }
 
 
-SEXP *VECTOR_PTR(SEXP x){
+SEXP * NORET VECTOR_PTR(SEXP x){
 	unimplemented("VECTOR_PTR");
-	return NULL;
 }
 
 SEXP Rf_asChar(SEXP x){
@@ -1335,20 +1333,6 @@ void DUPLICATE_ATTRIB(SEXP to, SEXP from){
     (*thisenv)->CallVoidMethod(thisenv, UpCallsRFFIObject, DUPLICATE_ATTRIB_MethodID, to, from);
 }
 
-char *dgettext(const char *domainname, const char *msgid) {
-	printf("dgettext: '%s'\n", msgid);
-	return (char*) msgid;
-}
-
-char *libintl_dgettext(const char *domainname, const char *msgid) {
-	return dgettext(domainname, msgid);
-}
-
-char *dngettext(const char *domainname, const char *msgid, const char * msgid_plural, unsigned long int n) {
-    printf("dngettext: singular - '%s' ; plural - '%s'\n", msgid, msgid_plural);
-    return (char*) (n == 1 ? msgid : msgid_plural);
-}
-
 const char *R_CHAR(SEXP charsxp) {
 	TRACE("%s(%p)", charsxp);
 	JNIEnv *thisenv = getEnv();
@@ -1637,7 +1621,7 @@ SEXP R_do_MAKE_CLASS(const char *what) {
 SEXP R_getClassDef (const char *what) {
 	return unimplemented("R_getClassDef");
 }
-    
+
 SEXP R_do_new_object(SEXP class_def) {
     JNIEnv *thisenv = getEnv();
     SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_do_new_object_MethodID, class_def);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
index 5b4f1bbbec..c8964b9ee0 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
  * Copyright (c) 1997-2015,  The R Core Team
- * Copyright (c) 2016, Oracle and/or its affiliates
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -41,7 +41,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, j
 	const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL);
 	char *errorMessage;
 	int errOffset;
-	void *pcre_result = pcre_compile(patternChars, options, &errorMessage, &errOffset, (char*) tables);
+	void *pcre_result = pcre_compile((char *) patternChars, options, &errorMessage, &errOffset, (char*) tables);
 	jstring stringErrorMessage = NULL;
 	if (pcre_result == NULL) {
 	    stringErrorMessage = (*env)->NewStringUTF(env, errorMessage);
@@ -53,7 +53,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, j
 JNIEXPORT jint JNICALL
 Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureCount(JNIEnv *env, jclass c, jlong code, jlong extra) {
     int captureCount;
-	int rc = pcre_fullinfo(code, extra, PCRE_INFO_CAPTURECOUNT, &captureCount);
+	int rc = pcre_fullinfo((void *)code, (void *)extra, PCRE_INFO_CAPTURECOUNT, &captureCount);
     return rc < 0 ? rc : captureCount;
 }
 
@@ -63,15 +63,15 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureNames(JNIEnv
     int nameEntrySize;
     char* nameTable;
     int res;
-	res = pcre_fullinfo(code, extra, PCRE_INFO_NAMECOUNT, &nameCount);
+	res = pcre_fullinfo((void *) code, (void *) extra, PCRE_INFO_NAMECOUNT, &nameCount);
     if (res < 0) {
         return res;
     }
-    res = pcre_fullinfo(code, extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize);
+    res = pcre_fullinfo((void *) code, (void *) extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize);
     if (res < 0) {
         return res;
     }
-	res = pcre_fullinfo(code, extra, PCRE_INFO_NAMETABLE, &nameTable);
+	res = pcre_fullinfo((void *) code,(void *) extra, PCRE_INFO_NAMETABLE, &nameTable);
     if (res < 0) {
         return res;
     }
@@ -91,7 +91,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeExec(JNIEnv *env, jcla
 	int subjectLength = (*env)->GetStringUTFLength(env, subject);
 	int* ovectorElems = (*env)->GetIntArrayElements(env, ovector, NULL);
 
-	int rc = pcre_exec(code, extra, subjectChars, subjectLength, startOffset, options,
+	int rc = pcre_exec((void *) code,(void *) extra, (char *) subjectChars, subjectLength, startOffset, options,
 			ovectorElems, ovectorLen);
 	(*env)->ReleaseIntArrayElements(env, ovector, ovectorElems, 0);
 	(*env)->ReleaseStringUTFChars(env, subject, subjectChars);
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 d7a786a49a..9df3ebbeaf 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -524,8 +524,6 @@ void *unimplemented(char *msg) {
     strcpy(buf, "unimplemented ");
     strcat(buf, msg);
     (*thisenv)->FatalError(thisenv, buf);
-    // to keep compiler happy
-    return NULL;
 }
 
 void fatalError(char *msg) {
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index e2dc370a32..91bd2d985d 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -41,9 +41,9 @@ jmethodID checkGetMethodID(JNIEnv *env, jclass klass, const char *name, const ch
 jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig, int isStatic);
 
 // use for an unimplemented API function
-void *unimplemented(char *msg);
+void *unimplemented(char *msg) __attribute__((noreturn));
 // use for any fatal error
-void fatalError(char *msg);
+void fatalError(char *msg) __attribute__((noreturn));
 // makes a call to the VM with x as an argument (for debugger validation)
 void validate(SEXP x);
 // checks x against the list of global JNI refs, returning the global version if x matches (IsSameObject)
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/variables.c b/com.oracle.truffle.r.native/fficall/src/jni/variables.c
index cbab66f68f..c66739f886 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/variables.c
@@ -149,7 +149,8 @@ char *FASTR_R_TempDir() {
 
 Rboolean FASTR_R_Interactive() {
 	JNIEnv *env = getEnv();
-	CTXT res = (*env)->CallObjectMethod(env, UpCallsRFFIObject, R_InteractiveMethodID);
+	int res = (int) (*env)->CallObjectMethod(env, UpCallsRFFIObject, R_InteractiveMethodID);
+	return (Rboolean) res;
 }
 
 SEXP FASTR_R_EmptyEnv() {
diff --git a/com.oracle.truffle.r.native/include/Makefile b/com.oracle.truffle.r.native/include/Makefile
index 2de8932ab1..b4b5ba423b 100644
--- a/com.oracle.truffle.r.native/include/Makefile
+++ b/com.oracle.truffle.r.native/include/Makefile
@@ -37,7 +37,7 @@ R_EXT_HEADERS_TO_LINK := $(filter-out $(notdir $(R_EXT_HEADERS_LOCAL)),$(R_EXT_H
 R_HEADERS := $(wildcard $(GNUR_HOME)/include/*.h)
 R_HEADERS_FILENAMES := $(notdir $(R_HEADERS))
 #$(info R_HEADERS_FILENAMES=$(R_HEADERS_FILENAMES))
-R_HEADERS_LOCAL := src/libintl.h src/Rinternals.h src/Rinterface.h
+R_HEADERS_LOCAL := src/Rinternals.h src/Rinterface.h
 #$(info R_HEADERS_LOCAL=$(R_HEADERS_LOCAL))>
 R_HEADERS_TO_LINK := $(filter-out $(notdir $(R_HEADERS_LOCAL)),$(R_HEADERS_FILENAMES))
 #$(info R_HEADERS_TO_LINK=$(R_HEADERS_TO_LINK))
@@ -47,7 +47,6 @@ all: linked
 linked:
 	mkdir -p R_ext
 	$(foreach file,$(R_HEADERS_TO_LINK),ln -sf $(GNUR_HOME)/include/$(file) $(file);)
-	ln -sf src/libintl.h
 	mx edinclude $(GNUR_HOME)/include
 	$(foreach file,$(R_EXT_HEADERS_TO_LINK),ln -sf $(GNUR_HOME)/include/R_ext/$(file) R_ext/$(file);)
 #	cp $(R_EXT_HEADERS_LOCAL) R_ext
diff --git a/com.oracle.truffle.r.native/include/src/libintl.h b/com.oracle.truffle.r.native/include/src/libintl.h
deleted file mode 100644
index fab17ac780..0000000000
--- a/com.oracle.truffle.r.native/include/src/libintl.h
+++ /dev/null
@@ -1 +0,0 @@
-// Empty file
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 209e3ef4b6..aabe6ec390 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-20
+21
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index b767f7c545..3479fff1b8 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -119,7 +119,6 @@ com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c,gnu_r.copyright
-com.oracle.truffle.r.native/include/src/libintl.h,no.copyright
 com.oracle.truffle.r.native/library/base/src/registration.c,no.copyright
 com.oracle.truffle.r.native/library/grDevices/src/gzio.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/library/methods/src/methods_dummy.c,no.copyright
diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py
index 3d329b13ac..dce5109799 100644
--- a/mx.fastr/mx_fastr_edinclude.py
+++ b/mx.fastr/mx_fastr_edinclude.py
@@ -47,6 +47,7 @@ def edinclude(args):
     ed_r_internals(args[0])
     ed_r_interface(args[0])
     ed_graphicsengine(args[0])
+    ed_rconfig(args[0])
 
 use_internals_section = '''#ifdef FASTR
 // packages defining USE_INTERNALS expect certain defs (e.g. isNull) to be there
@@ -219,3 +220,19 @@ def ed_graphicsengine(gnu_dir):
                 f.write(line.replace('24', '256'))
             else:
                 f.write(line)
+
+def ed_rconfig(gnu_dir):
+    '''
+    GNU R is built with ENABLE_NLS (internationalized strings) but FastR
+    does not do that in native code, so we disable it.
+    '''
+    rconfig_h = join(gnu_dir, 'Rconfig.h')
+    with open(rconfig_h) as f:
+        lines = f.readlines()
+
+    with open(join('Rconfig.h'), 'w') as f:
+        for line in lines:
+            if 'ENABLE_NLS' in line:
+                continue
+            else:
+                f.write(line)
-- 
GitLab


From 4ca5be551d29aaffe09ac554183f2a98c6571370 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 2 May 2017 15:27:47 +0200
Subject: [PATCH 335/402] Fix: append </svg> when generating SVG string

---
 .../r/library/fastrGrid/device/SVGDevice.java   | 17 +++++++++++------
 .../r/library/fastrGrid/grDevices/DevOff.java   |  2 +-
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
index 063847725f..baad5ebe41 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
@@ -53,7 +53,8 @@ public class SVGDevice implements GridDevice {
         this.height = height;
     }
 
-    public String getContents() {
+    public String closeAndGetContents() {
+        closeSVGDocument();
         return data.toString();
     }
 
@@ -73,11 +74,7 @@ public class SVGDevice implements GridDevice {
 
     @Override
     public void close() throws DeviceCloseException {
-        if (cachedCtx != null) {
-            // see #appendStyle
-            append("</g>");
-        }
-        append("</svg>");
+        closeSVGDocument();
         try {
             Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
         } catch (IOException e) {
@@ -176,6 +173,14 @@ public class SVGDevice implements GridDevice {
         data.append("' ").append(attributes).append(" />");
     }
 
+    private void closeSVGDocument() {
+        if (cachedCtx != null) {
+            // see #appendStyle
+            append("</g>");
+        }
+        append("</svg>");
+    }
+
     private void appendStyle(DrawingContext ctx) {
         if (cachedCtx == null || !DrawingContext.areSame(cachedCtx, ctx)) {
             if (cachedCtx != null) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
index 87f99d3561..8dc3209f96 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevOff.java
@@ -70,7 +70,7 @@ public abstract class DevOff extends RExternalBuiltinNode.Arg1 {
         GridDevice dev = ctx.getDevice(which);
         ctx.removeDevice(which);
         if ((dev instanceof SVGDevice)) {
-            return ((SVGDevice) dev).getContents();
+            return ((SVGDevice) dev).closeAndGetContents();
         } else {
             warning(Message.GENERIC, "The device was not SVG device.");
             return "";
-- 
GitLab


From a1fd76c7994e8de0d24725de3599617d7e5920b8 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 2 May 2017 09:48:15 -0700
Subject: [PATCH 336/402] [GR-3875] Remove override of mx gate command

---
 mx.fastr/mx_fastr.py | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index eb799067a5..4eac3bba91 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -295,10 +295,6 @@ def rgate(args):
     '''
     mx_gate.gate(args)
 
-def gate(args):
-    '''Run 'mx.gate' with some standard tasks excluded as they currently fail'''
-    mx_gate.gate(args + ['-x', '-t', 'FindBugs,Checkheaders,Distribution Overlap Check,BuildJavaWithEcj'])
-
 def _test_srcdir():
     tp = 'com.oracle.truffle.r.test'
     return join(mx.project(tp).dir, 'src', tp.replace('.', sep))
@@ -579,7 +575,6 @@ _commands = {
     'Rscript' : [rscript, '[options]'],
     'rtestgen' : [testgen, ''],
     'rgate' : [rgate, ''],
-    'gate' : [gate, ''],
     'junit' : [junit, ['options']],
     'junitsimple' : [junit_simple, ['options']],
     'junitdefault' : [junit_default, ['options']],
-- 
GitLab


From d463087d3c4ebad53ec53e78fa65b1b00f46c421 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 3 May 2017 08:51:50 -0700
Subject: [PATCH 337/402] [GR-2527] Bring NFI imple in sync with JNI; fix
 naming issues

---
 .../fficall/src/common/Rinternals_common.c    | 191 ++++++++++++
 .../fficall/src/common/Rinternals_common.h    |  26 ++
 .../fficall/src/jni/Makefile                  |   2 +-
 .../fficall/src/jni/Rinternals.c              | 213 ++------------
 .../fficall/src/truffle_nfi/Makefile          |   2 +-
 .../fficall/src/truffle_nfi/Memory.c          |   4 +-
 .../fficall/src/truffle_nfi/Rdynload_fastr.c  |   4 +-
 .../fficall/src/truffle_nfi/Rinternals.c      | 271 ++++++------------
 .../fficall/src/truffle_nfi/base_rffi.c       |   4 +-
 .../fficall/src/truffle_nfi/rffi_callbacks.h  |   7 +-
 .../src/truffle_nfi/rffi_callbacksindex.h     | 241 ++++++++--------
 .../fficall/src/truffle_nfi/rffiutils.c       |  29 ++
 .../fficall/src/truffle_nfi/rffiutils.h       |   5 +
 .../fficall/src/truffle_nfi/variables.c       |  15 +-
 com.oracle.truffle.r.native/version.source    |   2 +-
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |  18 +-
 .../truffle/r/nodes/ffi/RFFIUpCallMethod.java |  19 +-
 .../r/nodes/ffi/TracingUpCallsRFFIImpl.java   |  30 +-
 .../truffle/r/runtime/ffi/StdUpCallsRFFI.java |  16 +-
 mx.fastr/mx_fastr_mkgramrd.py                 |   2 +-
 20 files changed, 552 insertions(+), 549 deletions(-)
 create mode 100644 com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c
 create mode 100644 com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h
 create mode 100644 com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c

diff --git a/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c
new file mode 100644
index 0000000000..b4c88dff80
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <Rinternals.h>
+
+// This file includes all implementations that arise from Rinternals.h that
+// are independent, or largely independent, of the RFFI implementation.
+
+Rboolean Rf_isReal(SEXP x) {
+    return TYPEOF(x) == REALSXP;
+}
+
+Rboolean Rf_isSymbol(SEXP x) {
+    return TYPEOF(x) == SYMSXP;
+}
+
+Rboolean Rf_isComplex(SEXP x) {
+    return TYPEOF(x) == CPLXSXP;
+}
+
+Rboolean Rf_isEnvironment(SEXP x) {
+    return TYPEOF(x) == ENVSXP;
+}
+
+Rboolean Rf_isExpression(SEXP x) {
+    return TYPEOF(x) == EXPRSXP;
+}
+
+Rboolean Rf_isLogical(SEXP x) {
+    return TYPEOF(x) == LGLSXP;
+}
+
+SEXP GetOption(SEXP tag, SEXP rho)
+{
+    return GetOption1(tag); // RFFI impl dependent
+}
+
+int GetOptionCutoff(void)
+{
+    int w;
+    w = asInteger(GetOption1(install("deparse.cutoff")));
+    if (w == NA_INTEGER || w <= 0) {
+	warning("invalid 'deparse.cutoff', used 60");
+	w = 60;
+    }
+    return w;
+}
+
+#define R_MIN_WIDTH_OPT		10
+#define R_MAX_WIDTH_OPT		10000
+#define R_MIN_DIGITS_OPT	0
+#define R_MAX_DIGITS_OPT	22
+
+int GetOptionWidth(void)
+{
+    int w;
+    w = asInteger(GetOption1(install("width")));
+    if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) {
+	warning("invalid printing width, used 80");
+	return 80;
+    }
+    return w;
+}
+
+int GetOptionDigits(void)
+{
+    int d;
+    d = asInteger(GetOption1(install("digits")));
+    if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) {
+	warning("invalid printing digits, used 7");
+	return 7;
+    }
+    return d;
+}
+
+Rboolean Rf_GetOptionDeviceAsk(void)
+{
+    int ask;
+    ask = asLogical(GetOption1(install("device.ask.default")));
+    if(ask == NA_LOGICAL) {
+	warning("invalid value for \"device.ask.default\", using FALSE");
+	return FALSE;
+    }
+    return ask != 0;
+}
+
+void *DATAPTR(SEXP x) {
+	int type = TYPEOF(x);
+	if (type == INTSXP) {
+		return INTEGER(x);
+	} else if (type == REALSXP) {
+		return REAL(x);
+	} else if (type == LGLSXP) {
+		return LOGICAL(x);
+	} else {
+		printf("DATAPTR %d\n", type);
+		unimplemented("R_DATAPTR");
+		return NULL;
+	}
+}
+
+int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) {
+    int ans;
+    SEXP cl = PROTECT(asChar(getAttrib(x, R_ClassSymbol)));
+    const char *class = CHAR(cl);
+    for (ans = 0; ; ans++) {
+	if (!strlen(valid[ans])) // empty string
+	    break;
+	if (!strcmp(class, valid[ans])) {
+	    UNPROTECT(1); /* cl */
+	    return ans;
+	}
+    }
+    /* if not found directly, now search the non-virtual super classes :*/
+    if(IS_S4_OBJECT(x)) {
+	/* now try the superclasses, i.e.,  try   is(x, "....");  superCl :=
+	   .selectSuperClasses(getClass("....")@contains, dropVirtual=TRUE)  */
+	SEXP classExts, superCl, _call;
+        // install() results cached anyway so the following variables could be non-static if needed
+	static SEXP s_contains = NULL, s_selectSuperCl = NULL;
+	int i;
+	if(!s_contains) {
+	    s_contains      = install("contains");
+	    s_selectSuperCl = install(".selectSuperClasses");
+	}
+	SEXP classDef = PROTECT(R_getClassDef(class));
+	PROTECT(classExts = R_do_slot(classDef, s_contains));
+	PROTECT(_call = lang3(s_selectSuperCl, classExts,
+			      /* dropVirtual = */ ScalarLogical(1)));
+	superCl = eval(_call, rho);
+	UNPROTECT(3); /* _call, classExts, classDef */
+	PROTECT(superCl);
+	for(i=0; i < LENGTH(superCl); i++) {
+	    const char *s_class = CHAR(STRING_ELT(superCl, i));
+	    for (ans = 0; ; ans++) {
+		if (!strlen(valid[ans]))
+		    break;
+		if (!strcmp(s_class, valid[ans])) {
+		    UNPROTECT(2); /* superCl, cl */
+		    return ans;
+		}
+	    }
+	}
+	UNPROTECT(1); /* superCl */
+    }
+    UNPROTECT(1); /* cl */
+    return -1;
+}
+
+int R_check_class_etc_helper (SEXP x, const char **valid, SEXP (*getMethodsNamespace)()) {
+    // install() results cached anyway so the following variables could be non-static if needed
+    static SEXP meth_classEnv = NULL;
+    SEXP cl = getAttrib(x, R_ClassSymbol), rho = R_GlobalEnv, pkg;
+    if (!meth_classEnv)
+        meth_classEnv = install(".classEnv");
+
+    pkg = getAttrib(cl, R_PackageSymbol); /* ==R== packageSlot(class(x)) */
+    if (!isNull(pkg)) { /* find  rho := correct class Environment */
+        SEXP clEnvCall;
+        // FIXME: fails if 'methods' is not loaded.
+        PROTECT(clEnvCall = lang2(meth_classEnv, cl));
+        SEXP methodsNamespace = getMethodsNamespace();
+        rho = eval(clEnvCall, methodsNamespace);
+        UNPROTECT(1);
+        if (!isEnvironment(rho))
+            error(_("could not find correct environment; please report!"));
+    }
+    PROTECT(rho);
+    int res = R_check_class_and_super(x, valid, rho);
+    UNPROTECT(1);
+    return res;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h
new file mode 100644
index 0000000000..6d78b52544
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/common/Rinternals_common.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <Rinternals.h>
+
+// Factors out the RFFI mechanism for getting the methods namespace.
+int R_check_class_etc_helper (SEXP x, const char **valid, SEXP (*getMethodsNamespace)());
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Makefile b/com.oracle.truffle.r.native/fficall/src/jni/Makefile
index fbbb5f7439..1108df184f 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Makefile
@@ -38,7 +38,7 @@ C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(C_SOURCES))
 
 JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(JDK_OS_DIR)
 FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext
-LOCAL_INCLUDES = -I . -I $(abspath ../include)
+LOCAL_INCLUDES = -I . -I $(abspath ../include) -I $(abspath ../common)
 
 INCLUDES := $(LOCAL_INCLUDES) $(JNI_INCLUDES) $(FFI_INCLUDES)
 
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 f2e058cf9e..1f63778f8f 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -22,6 +22,7 @@
  */
 #include <rffiutils.h>
 #include <string.h>
+#include <Rinternals_common.h>
 
 // Most everything in RInternals.h
 
@@ -36,14 +37,14 @@ static jmethodID Rf_ScalarIntegerMethodID;
 static jmethodID Rf_ScalarDoubleMethodID;
 static jmethodID Rf_ScalarStringMethodID;
 static jmethodID Rf_ScalarLogicalMethodID;
-static jmethodID Rf_allocateVectorMethodID;
-static jmethodID Rf_allocateArrayMethodID;
-static jmethodID Rf_allocateMatrixMethodID;
+static jmethodID Rf_allocVectorMethodID;
+static jmethodID Rf_allocArrayMethodID;
+static jmethodID Rf_allocMatrixMethodID;
 static jmethodID Rf_duplicateMethodID;
-static jmethodID Rf_anyDuplicatedMethodID;
+static jmethodID Rf_any_duplicatedMethodID;
 static jmethodID Rf_consMethodID;
 static jmethodID Rf_evalMethodID;
-static jmethodID Rf_findfunMethodID;
+static jmethodID Rf_findFunMethodID;
 static jmethodID Rf_defineVarMethodID;
 static jmethodID Rf_findVarMethodID;
 static jmethodID Rf_findVarInFrameMethodID;
@@ -131,12 +132,12 @@ static jmethodID restoreHandlerStacksMethodID;
 static jmethodID R_MakeExternalPtrMethodID;
 static jmethodID R_ExternalPtrAddrMethodID;
 static jmethodID R_ExternalPtrTagMethodID;
-static jmethodID R_ExternalPtrProtMethodID;
+static jmethodID R_ExternalPtrProtectedMethodID;
 static jmethodID R_SetExternalPtrAddrMethodID;
 static jmethodID R_SetExternalPtrTagMethodID;
 static jmethodID R_SetExternalPtrProtMethodID;
 
-static jmethodID R_computeIdenticalMethodID;
+static jmethodID R_compute_identicalMethodID;
 static jmethodID Rf_copyListMatrixMethodID;
 static jmethodID Rf_copyMatrixMethodID;
 static jmethodID Rf_nrowsMethodID;
@@ -154,7 +155,7 @@ void init_internals(JNIEnv *env) {
 	Rf_ScalarLogicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_ScalarLogical", "(I)Lcom/oracle/truffle/r/runtime/data/RLogicalVector;", 0);
 	Rf_consMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_cons", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_evalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_eval", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	Rf_findfunMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findfun", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
+	Rf_findFunMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findFun", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_defineVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_defineVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 	Rf_findVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVar", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_findVarInFrameMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVarInFrame", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
@@ -168,11 +169,11 @@ void init_internals(JNIEnv *env) {
 	Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)V", 0);
 	Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 	Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)V", 0);
-	Rf_allocateVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateVector", "(II)Ljava/lang/Object;", 0);
-	Rf_allocateMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateMatrix", "(III)Ljava/lang/Object;", 0);
-	Rf_allocateArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0);
+	Rf_allocVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocVector", "(II)Ljava/lang/Object;", 0);
+	Rf_allocMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocMatrix", "(III)Ljava/lang/Object;", 0);
+	Rf_allocArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_duplicateMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_duplicate", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
-	Rf_anyDuplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_anyDuplicated", "(Ljava/lang/Object;I)I", 0);
+	Rf_any_duplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_any_duplicated", "(Ljava/lang/Object;I)I", 0);
 	R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0);
 	Rf_classgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_classgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)V", 0);
@@ -244,12 +245,12 @@ void init_internals(JNIEnv *env) {
 	R_MakeExternalPtrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_MakeExternalPtr", "(JLjava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 0);
 	R_ExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrAddr", "(Ljava/lang/Object;)J", 0);
 	R_ExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrTag", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	R_ExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrProt", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
+	R_ExternalPtrProtectedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrProtected", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_SetExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrAddr", "(Ljava/lang/Object;J)V", 0);
 	R_SetExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrTag", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
-	R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProt", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
+	R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProtected", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 
-    R_computeIdenticalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_computeIdentical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0);
+    R_compute_identicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_compute_identical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0);
     Rf_copyListMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyListMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0);
     Rf_copyMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0);
     Rf_nrowsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_nrows", "(Ljava/lang/Object;)I", 0);
@@ -296,14 +297,14 @@ SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
     }
     TRACE(TARGpd, t, len);
     JNIEnv *thisenv = getEnv();
-    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocateVectorMethodID, t, len);
+    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocVectorMethodID, t, len);
     return checkRef(thisenv, result);
 }
 
 SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
 	TRACE(TARGppd, t, dims);
 	JNIEnv *thisenv = getEnv();
-	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocateArrayMethodID, t, dims);
+	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocArrayMethodID, t, dims);
 	return checkRef(thisenv, result);
 }
 
@@ -314,7 +315,7 @@ SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
 SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
 	TRACE(TARGppd, mode, nrow, ncol);
 	JNIEnv *thisenv = getEnv();
-	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocateMatrixMethodID, mode, nrow, ncol);
+	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_allocMatrixMethodID, mode, nrow, ncol);
 	return checkRef(thisenv, result);
 }
 
@@ -363,7 +364,7 @@ SEXP Rf_eval(SEXP expr, SEXP env) {
 SEXP Rf_findFun(SEXP symbol, SEXP rho) {
 	TRACE(TARGpp, symbol, rho);
 	JNIEnv *thisenv = getEnv();
-	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_findfunMethodID, symbol, rho);
+	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_findFunMethodID, symbol, rho);
 	return checkRef(thisenv, result);
 }
 
@@ -420,7 +421,7 @@ R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
 	TRACE(TARGpd, x, from_last);
     if (!isVector(x)) error(_("'duplicated' applies only to vectors"));
 	JNIEnv *thisenv = getEnv();
-    return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_anyDuplicatedMethodID, x, from_last);
+    return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_any_duplicatedMethodID, x, from_last);
 }
 
 SEXP Rf_duplicated(SEXP x, Rboolean y) {
@@ -451,29 +452,6 @@ Rboolean Rf_inherits(SEXP x, const char * klass) {
     return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_inheritsMethodID, x, klazz);
 }
 
-Rboolean Rf_isReal(SEXP x) {
-    return TYPEOF(x) == REALSXP;
-}
-
-Rboolean Rf_isSymbol(SEXP x) {
-    return TYPEOF(x) == SYMSXP;
-}
-
-Rboolean Rf_isComplex(SEXP x) {
-    return TYPEOF(x) == CPLXSXP;
-}
-
-Rboolean Rf_isEnvironment(SEXP x) {
-    return TYPEOF(x) == ENVSXP;
-}
-
-Rboolean Rf_isExpression(SEXP x) {
-    return TYPEOF(x) == EXPRSXP;
-}
-
-Rboolean Rf_isLogical(SEXP x) {
-    return TYPEOF(x) == LGLSXP;
-}
 
 Rboolean Rf_isObject(SEXP s) {
 	unimplemented("Rf_isObject");
@@ -756,60 +734,6 @@ SEXP GetOption1(SEXP tag)
 	return checkRef(thisenv, result);
 }
 
-SEXP GetOption(SEXP tag, SEXP rho)
-{
-    return GetOption1(tag);
-}
-
-int GetOptionCutoff(void)
-{
-    int w;
-    w = asInteger(GetOption1(install("deparse.cutoff")));
-    if (w == NA_INTEGER || w <= 0) {
-	warning(_("invalid 'deparse.cutoff', used 60"));
-	w = 60;
-    }
-    return w;
-}
-
-#define R_MIN_WIDTH_OPT		10
-#define R_MAX_WIDTH_OPT		10000
-#define R_MIN_DIGITS_OPT	0
-#define R_MAX_DIGITS_OPT	22
-
-int GetOptionWidth(void)
-{
-    int w;
-    w = asInteger(GetOption1(install("width")));
-    if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) {
-	warning(_("invalid printing width, used 80"));
-	return 80;
-    }
-    return w;
-}
-
-int GetOptionDigits(void)
-{
-    int d;
-    d = asInteger(GetOption1(install("digits")));
-    if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) {
-	warning(_("invalid printing digits, used 7"));
-	return 7;
-    }
-    return d;
-}
-
-Rboolean Rf_GetOptionDeviceAsk(void)
-{
-    int ask;
-    ask = asLogical(GetOption1(install("device.ask.default")));
-    if(ask == NA_LOGICAL) {
-	warning(_("invalid value for \"device.ask.default\", using FALSE"));
-	return FALSE;
-    }
-    return ask != 0;
-}
-
 void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho)
 {
 	JNIEnv *thisenv = getEnv();
@@ -1271,7 +1195,7 @@ double Rf_asReal(SEXP x) {
 }
 
 Rcomplex Rf_asComplex(SEXP x){
-	unimplemented("Rf_asLogical");
+	unimplemented("Rf_asComplex");
 	Rcomplex c; return c;
 }
 
@@ -1341,21 +1265,6 @@ const char *R_CHAR(SEXP charsxp) {
 	return copyChars;
 }
 
-void *DATAPTR(SEXP x) {
-	int type = TYPEOF(x);
-	if (type == INTSXP) {
-		return INTEGER(x);
-	} else if (type == REALSXP) {
-		return REAL(x);
-	} else if (type == LGLSXP) {
-		return LOGICAL(x);
-	} else {
-		printf("DATAPTR %d\n", type);
-		unimplemented("R_DATAPTR");
-		return NULL;
-	}
-}
-
 void R_qsort_I  (double *v, int *II, int i, int j) {
 	unimplemented("R_qsort_I");
 }
@@ -1454,7 +1363,7 @@ Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
 }
 
 Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
-    // TODO: for now, I belive all bindings are false
+    // TODO: for now, I believe all bindings are false
     return (Rboolean)0;
 }
 
@@ -1531,7 +1440,7 @@ SEXP R_ExternalPtrTag(SEXP s) {
 
 SEXP R_ExternalPtrProt(SEXP s) {
 	JNIEnv *thisenv = getEnv();
-	SEXP result =  (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_ExternalPtrProtMethodID, s);
+	SEXP result =  (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_ExternalPtrProtectedMethodID, s);
     return checkRef(thisenv, result);
 }
 
@@ -1628,77 +1537,13 @@ SEXP R_do_new_object(SEXP class_def) {
     return checkRef(thisenv, result);
 }
 
-int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) {
-    int ans;
-    SEXP cl = PROTECT(asChar(getAttrib(x, R_ClassSymbol)));
-    const char *class = CHAR(cl);
-    for (ans = 0; ; ans++) {
-	if (!strlen(valid[ans])) // empty string
-	    break;
-	if (!strcmp(class, valid[ans])) {
-	    UNPROTECT(1); /* cl */
-	    return ans;
-	}
-    }
-    /* if not found directly, now search the non-virtual super classes :*/
-    if(IS_S4_OBJECT(x)) {
-	/* now try the superclasses, i.e.,  try   is(x, "....");  superCl :=
-	   .selectSuperClasses(getClass("....")@contains, dropVirtual=TRUE)  */
-	SEXP classExts, superCl, _call;
-        // install() results cached anyway so the following variables could be non-static if needed
-	static SEXP s_contains = NULL, s_selectSuperCl = NULL;
-	int i;
-	if(!s_contains) {
-	    s_contains      = install("contains");
-	    s_selectSuperCl = install(".selectSuperClasses");
-	}
-	SEXP classDef = PROTECT(R_getClassDef(class));
-	PROTECT(classExts = R_do_slot(classDef, s_contains));
-	PROTECT(_call = lang3(s_selectSuperCl, classExts,
-			      /* dropVirtual = */ ScalarLogical(1)));
-	superCl = eval(_call, rho);
-	UNPROTECT(3); /* _call, classExts, classDef */
-	PROTECT(superCl);
-	for(i=0; i < LENGTH(superCl); i++) {
-	    const char *s_class = CHAR(STRING_ELT(superCl, i));
-	    for (ans = 0; ; ans++) {
-		if (!strlen(valid[ans]))
-		    break;
-		if (!strcmp(s_class, valid[ans])) {
-		    UNPROTECT(2); /* superCl, cl */
-		    return ans;
-		}
-	    }
-	}
-	UNPROTECT(1); /* superCl */
-    }
-    UNPROTECT(1); /* cl */
-    return -1;
+static SEXP jniGetMethodsNamespace() {
+    JNIEnv *thisenv = getEnv();
+    return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_MethodsNamespaceMethodID);
 }
 
 int R_check_class_etc (SEXP x, const char **valid) {
-    // install() results cached anyway so the following variables could be non-static if needed
-    static SEXP meth_classEnv = NULL;
-    SEXP cl = getAttrib(x, R_ClassSymbol), rho = R_GlobalEnv, pkg;
-    if (!meth_classEnv)
-        meth_classEnv = install(".classEnv");
-
-    pkg = getAttrib(cl, R_PackageSymbol); /* ==R== packageSlot(class(x)) */
-    if (!isNull(pkg)) { /* find  rho := correct class Environment */
-        SEXP clEnvCall;
-        // FIXME: fails if 'methods' is not loaded.
-        PROTECT(clEnvCall = lang2(meth_classEnv, cl));
-        JNIEnv *thisenv = getEnv();
-        SEXP methodsNamespace = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_MethodsNamespaceMethodID);
-        rho = eval(clEnvCall, methodsNamespace);
-        UNPROTECT(1);
-        if (!isEnvironment(rho))
-            error(_("could not find correct environment; please report!"));
-    }
-    PROTECT(rho);
-    int res = R_check_class_and_super(x, valid, rho);
-    UNPROTECT(1);
-    return res;
+	return R_check_class_etc_helper(x, valid, jniGetMethodsNamespace);
 }
 
 SEXP R_PreserveObject(SEXP x) {
@@ -1717,7 +1562,7 @@ void R_dot_Last(void) {
 
 Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
 	JNIEnv *thisenv = getEnv();
-	return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, R_computeIdenticalMethodID, x, y, flags);
+	return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, R_compute_identicalMethodID, x, y, flags);
 }
 
 void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
index 8c9fb1057c..1d14ab2e86 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
@@ -38,7 +38,7 @@ C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(C_SOURCES))
 
 FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext
 #NFI_INCLUDES is set in environment (by mx)
-LOCAL_INCLUDES = -I . -I $(abspath ../include)
+LOCAL_INCLUDES = -I . -I $(abspath ../include) -I $(abspath ../common)
 
 INCLUDES := $(LOCAL_INCLUDES) $(FFI_INCLUDES) $(NFI_INCLUDES)
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c
index a12d66c3cf..e97023c600 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c
@@ -71,7 +71,7 @@ void *R_chk_calloc(size_t nelem, size_t elsize) {
 #endif
     p = calloc(nelem, elsize);
     if (!p) /* problem here is that we don't have a format for size_t. */
-	error(_("'Calloc' could not allocate memory (%.0f of %u bytes)"),
+	error("'Calloc' could not allocate memory (%.0f of %u bytes)",
 		(double) nelem, elsize);
     return (p);
 }
@@ -81,7 +81,7 @@ void *R_chk_realloc(void *ptr, size_t size) {
     /* Protect against broken realloc */
     if(ptr) p = realloc(ptr, size); else p = malloc(size);
     if(!p)
-	error(_("'Realloc' could not re-allocate memory (%.0f bytes)"),
+	error("'Realloc' could not re-allocate memory (%.0f bytes)",
 	      (double) size);
     return(p);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
index e9adb555cf..4a0ffaaae6 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
@@ -79,7 +79,7 @@ Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) {
 
 
 TruffleObject Rdynload_setSymbol(DllInfo *info, int nstOrd, long routinesAddr, int index) {
-	char *name;
+	const char *name;
 	long fun;
 	int numArgs;
 	switch (nstOrd) {
@@ -113,7 +113,7 @@ TruffleObject Rdynload_setSymbol(DllInfo *info, int nstOrd, long routinesAddr, i
 	}
 	}
 	//printf("call_setDotSymbolValues %p, %s, %p, %d\n", info, name, fun, numArgs);
-	TruffleObject result = call_setDotSymbolValues(info, name, fun, numArgs);
+	TruffleObject result = call_setDotSymbolValues(info, (char *)name, fun, numArgs);
 
 	return result;
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
index db41b21bcc..b3005b1448 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -23,6 +23,7 @@
 #include <Rinterface.h>
 #include <rffiutils.h>
 #include <rffi_callbacks.h>
+#include <Rinternals_common.h>
 
 void *callbacks[CALLBACK_TABLE_SIZE];
 
@@ -31,12 +32,6 @@ void Rinternals_addCallback(int index, void *closure) {
 	callbacks[index] = closure;
 }
 
-static SEXP unimplemented(char *f) {
-	printf("unimplemented %s\n", f);
-	exit(1);
-	return NULL;
-}
-
 static int* return_int;
 static double* return_double;
 static char* return_byte;
@@ -86,7 +81,7 @@ void return_FREE(void *address) {
 
 // R_GlobalEnv et al are not a variables in FASTR as they are RContext specific
 SEXP FASTR_R_GlobalEnv() {
-	return unimplemented("FASTR_R_GlobalEnv");
+	return ((call_R_GlobalEnv) callbacks[R_GlobalEnv_x])();
 }
 
 SEXP FASTR_R_BaseEnv() {
@@ -94,19 +89,19 @@ SEXP FASTR_R_BaseEnv() {
 }
 
 SEXP FASTR_R_BaseNamespace() {
-	return unimplemented("FASTR_R_BaseNamespace");
+	return ((call_R_BaseNamespace) callbacks[R_BaseNamespace_x])();
 }
 
 SEXP FASTR_R_NamespaceRegistry() {
-	return unimplemented("FASTR_R_NamespaceRegistry");
+	return ((call_R_NamespaceRegistry) callbacks[R_NamespaceRegistry_x])();
 }
 
 CTXT FASTR_GlobalContext() {
-	return unimplemented("FASTR_GlobalContext");
+	return ((call_R_GlobalContext) callbacks[R_GlobalContext_x])();
 }
 
 Rboolean FASTR_R_Interactive() {
-	return (int) unimplemented("FASTR_R_Interactive");
+	return (int) ((call_R_Interactive) callbacks[R_Interactive_x])();
 }
 
 SEXP CAR(SEXP e) {
@@ -134,7 +129,7 @@ double *REAL(SEXP x){
 
 Rbyte *RAW(SEXP x) {
 	((call_RAW) callbacks[RAW_x])(x);
-		return return_byte;
+		return (Rbyte *) return_byte;
 }
 
 int LENGTH(SEXP x) {
@@ -178,22 +173,10 @@ SEXP Rf_coerceVector(SEXP x, SEXPTYPE mode) {
 	return ((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode);
 }
 
-SEXP Rf_protect(SEXP x) {
-	return x;
-}
-
-void Rf_unprotect(int x) {
-	// nothing to do
-}
-
 SEXP Rf_cons(SEXP car, SEXP cdr) {
 	return ((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr);
 }
 
-SEXP R_FindNamespace(SEXP info) {
-	return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info);
-}
-
 SEXP Rf_GetOption1(SEXP tag) {
 	return ((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag);
 }
@@ -227,7 +210,8 @@ void Rf_error(const char *format, ...) {
 	((call_Rf_error) callbacks[Rf_error_x])(buf);
 	// just transfer back which will cleanup and exit the entire JNI call
 //	longjmp(*getErrorJmpBuf(), 1);
-
+	// Should not reach here
+	unimplemented("Rf_error");
 }
 
 void Rf_errorcall(SEXP x, const char *format, ...) {
@@ -246,7 +230,7 @@ void Rf_warningcall(SEXP x, const char *format, ...) {
 void Rf_warning(const char *format, ...) {
 	char buf[8192];
 	va_list(ap);
-	va_start(ap,format);
+	va_start(ap, format);
 	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
 	va_end(ap);
 	((call_Rf_warning) callbacks[Rf_warning_x])(buf);
@@ -302,11 +286,11 @@ SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
   	    unimplemented("RF_allocVector with custom allocator");
 	    return NULL;
     }
-    return ((call_Rf_allocateVector) callbacks[Rf_allocateVector_x])(t, len);
+    return ((call_Rf_allocVector) callbacks[Rf_allocVector_x])(t, len);
 }
 
 SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
-	unimplemented("Rf_allocArray");
+	return ((call_Rf_allocArray) callbacks[Rf_allocArray_x])(t, dims);
 }
 
 SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
@@ -314,7 +298,7 @@ SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
 }
 
 SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
-	unimplemented("Rf_allocMatrix");
+	return ((call_Rf_allocMatrix) callbacks[Rf_allocMatrix_x])(mode, nrow, ncol);
 }
 
 SEXP Rf_allocList(int x) {
@@ -343,11 +327,11 @@ SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
 }
 
 SEXP Rf_eval(SEXP expr, SEXP env) {
-	return unimplemented("Rf_eval");
+	return ((call_Rf_eval) callbacks[Rf_eval_x])(expr, env);
 }
 
 SEXP Rf_findFun(SEXP symbol, SEXP rho) {
-	return unimplemented("Rf_findFun");
+	return ((call_Rf_findFun) callbacks[Rf_findFun_x])(symbol, rho);
 }
 
 SEXP Rf_findVar(SEXP sym, SEXP rho) {
@@ -355,11 +339,11 @@ SEXP Rf_findVar(SEXP sym, SEXP rho) {
 }
 
 SEXP Rf_findVarInFrame(SEXP rho, SEXP sym) {
-	return unimplemented("Rf_findVarInFrame");
+	return ((call_Rf_findVarInFrame) callbacks[Rf_findVarInFrame_x])(rho, sym);
 }
 
 SEXP Rf_findVarInFrame3(SEXP rho, SEXP sym, Rboolean b) {
-	return unimplemented("Rf_findVarInFrame");
+	return ((call_Rf_findVarInFrame3) callbacks[Rf_findVarInFrame3_x])(rho, sym, b);
 }
 
 SEXP Rf_getAttrib(SEXP vec, SEXP name) {
@@ -373,15 +357,15 @@ SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
 }
 
 SEXP Rf_duplicate(SEXP x) {
-	return unimplemented("Rf_duplicate");
+	return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1);
 }
 
 SEXP Rf_shallow_duplicate(SEXP x) {
-	return unimplemented("Rf_shallow_duplicate");
+	return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0);
 }
 
 R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
-	return (R_xlen_t) unimplemented("Rf_any_duplicated");
+	return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
 }
 
 SEXP Rf_duplicated(SEXP x, Rboolean y) {
@@ -406,31 +390,7 @@ int Rf_countContexts(int x, int y) {
 }
 
 Rboolean Rf_inherits(SEXP x, const char * klass) {
-	return (Rboolean) unimplemented("Rf_inherits");
-}
-
-Rboolean Rf_isReal(SEXP x) {
-    return TYPEOF(x) == REALSXP;
-}
-
-Rboolean Rf_isSymbol(SEXP x) {
-    return TYPEOF(x) == SYMSXP;
-}
-
-Rboolean Rf_isComplex(SEXP x) {
-    return TYPEOF(x) == CPLXSXP;
-}
-
-Rboolean Rf_isEnvironment(SEXP x) {
-    return TYPEOF(x) == ENVSXP;
-}
-
-Rboolean Rf_isExpression(SEXP x) {
-    return TYPEOF(x) == EXPRSXP;
-}
-
-Rboolean Rf_isLogical(SEXP x) {
-    return TYPEOF(x) == LGLSXP;
+	return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, klass);
 }
 
 Rboolean Rf_isObject(SEXP s) {
@@ -443,7 +403,7 @@ void Rf_PrintValue(SEXP x) {
 }
 
 SEXP Rf_install(const char *name) {
-	((call_Rf_install) callbacks[Rf_install_x])(name);
+	return ((call_Rf_install) callbacks[Rf_install_x])(name);
 }
 
 SEXP Rf_installChar(SEXP charsxp) {
@@ -475,13 +435,20 @@ const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst)
 }
 
 int Rf_ncols(SEXP x) {
-	return (int) unimplemented("Rf_ncols");
+	return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
 }
 
 int Rf_nrows(SEXP x) {
-	return (int) unimplemented("Rf_nrows");
+	return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
+}
+
+
+SEXP Rf_protect(SEXP x) {
+	return x;
 }
 
+void Rf_unprotect(int x) {
+}
 
 void R_ProtectWithIndex(SEXP x, PROTECT_INDEX *y) {
 	//
@@ -511,7 +478,7 @@ SEXP R_NewHashedEnv(SEXP parent, SEXP size) {
 }
 
 SEXP Rf_classgets(SEXP vec, SEXP klass) {
-	return unimplemented("Rf_classgets");
+	return ((call_Rf_classgets) callbacks[Rf_classgets_x])(vec, klass);
 }
 
 const char *Rf_translateChar(SEXP x) {
@@ -533,7 +500,7 @@ const char *Rf_translateCharUTF8(SEXP x) {
 }
 
 SEXP Rf_lengthgets(SEXP x, R_len_t y) {
-	return unimplemented("Rf_lengthgets");
+	return ((call_Rf_lengthgets) callbacks[Rf_lengthgets_x])(x, y);
 }
 
 SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) {
@@ -545,68 +512,19 @@ SEXP R_lsInternal(SEXP env, Rboolean all) {
 }
 
 SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) {
-	return unimplemented("R_lsInternal3");
+	return ((call_R_lsInternal3) callbacks[R_lsInternal3_x])(env, all, sorted);
 }
 
 SEXP Rf_namesgets(SEXP x, SEXP y) {
 	return unimplemented("Rf_namesgets");
 }
 
-SEXP GetOption(SEXP tag, SEXP rho) {
-    return GetOption1(tag);
-}
-
-int GetOptionCutoff(void) {
-    int w;
-    w = asInteger(GetOption1(install("deparse.cutoff")));
-    if (w == NA_INTEGER || w <= 0) {
-	warning(_("invalid 'deparse.cutoff', used 60"));
-	w = 60;
-    }
-    return w;
-}
-
-#define R_MIN_WIDTH_OPT		10
-#define R_MAX_WIDTH_OPT		10000
-#define R_MIN_DIGITS_OPT	0
-#define R_MAX_DIGITS_OPT	22
-
-int GetOptionWidth(void) {
-    int w;
-    w = asInteger(GetOption1(install("width")));
-    if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) {
-	warning(_("invalid printing width, used 80"));
-	return 80;
-    }
-    return w;
-}
-
-int GetOptionDigits(void) {
-    int d;
-    d = asInteger(GetOption1(install("digits")));
-    if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) {
-	warning(_("invalid printing digits, used 7"));
-	return 7;
-    }
-    return d;
-}
-
-Rboolean Rf_GetOptionDeviceAsk(void) {
-    int ask;
-    ask = asLogical(GetOption1(install("device.ask.default")));
-    if(ask == NA_LOGICAL) {
-	warning(_("invalid value for \"device.ask.default\", using FALSE"));
-	return FALSE;
-    }
-    return ask != 0;
-}
-
 SEXP TAG(SEXP e) {
 	return ((call_TAG) callbacks[TAG_x])(e);
 }
 
 SEXP PRINTNAME(SEXP e) {
-	return unimplemented("PRINTNAME");
+	return ((call_PRINTNAME) callbacks[PRINTNAME_x])(e);
 }
 
 
@@ -634,7 +552,7 @@ SEXP CDDDR(SEXP e) {
 }
 
 SEXP CADDR(SEXP e) {
-	return unimplemented("CADDR");
+	return ((call_CADDR) callbacks[CADDR_x])(e);
 }
 
 SEXP CADDDR(SEXP e) {
@@ -669,7 +587,7 @@ SEXP SETCDR(SEXP x, SEXP y) {
 }
 
 SEXP SETCADR(SEXP x, SEXP y) {
-	return unimplemented("SETCADR");
+	return ((call_SETCADR) callbacks[SETCADR_x])(x, y);
 }
 
 SEXP SETCADDR(SEXP x, SEXP y) {
@@ -700,11 +618,11 @@ SEXP CLOENV(SEXP x) {
 }
 
 int RDEBUG(SEXP x) {
-    unimplemented("RDEBUG");
+	return ((call_RDEBUG) callbacks[RDEBUG_x])(x);
 }
 
 int RSTEP(SEXP x) {
-	unimplemented("RSTEP");
+	return ((call_RSTEP) callbacks[RSTEP_x])(x);
 }
 
 int RTRACE(SEXP x) {
@@ -713,11 +631,11 @@ int RTRACE(SEXP x) {
 }
 
 void SET_RDEBUG(SEXP x, int v) {
-	unimplemented("SET_RDEBUG");
+	((call_SET_RDEBUG) callbacks[SET_RDEBUG_x])(x, v);
 }
 
 void SET_RSTEP(SEXP x, int v) {
-	unimplemented("SET_RSTEP");
+	((call_SET_RSTEP) callbacks[SET_RSTEP_x])(x, v);
 }
 
 void SET_RTRACE(SEXP x, int v) {
@@ -737,7 +655,7 @@ void SET_CLOENV(SEXP x, SEXP v) {
 }
 
 SEXP SYMVALUE(SEXP x) {
-	return unimplemented("SYMVALUE");
+	return ((call_SYMVALUE) callbacks[SYMVALUE_x])(x);
 }
 
 SEXP INTERNAL(SEXP x) {
@@ -754,7 +672,7 @@ void SET_DDVAL(SEXP x, int v) {
 }
 
 void SET_SYMVALUE(SEXP x, SEXP v) {
-	unimplemented("SET_SYMVALUE");
+	((call_SET_SYMVALUE) callbacks[SET_SYMVALUE_x])(x, v);
 }
 
 void SET_INTERNAL(SEXP x, SEXP v) {
@@ -766,7 +684,7 @@ SEXP FRAME(SEXP x) {
 }
 
 SEXP ENCLOS(SEXP x) {
-	return unimplemented("ENCLOS");
+	return ((call_ENCLOS) callbacks[ENCLOS_x])(x);
 }
 
 SEXP HASHTAB(SEXP x) {
@@ -795,19 +713,19 @@ void SET_HASHTAB(SEXP x, SEXP v) {
 }
 
 SEXP PRCODE(SEXP x) {
-	return unimplemented("PRCODE");
+	return ((call_PRCODE) callbacks[PRCODE_x])(x);
 }
 
 SEXP PRENV(SEXP x) {
-	return unimplemented("PRENV");
+	return ((call_PRENV) callbacks[PRENV_x])(x);
 }
 
 SEXP PRVALUE(SEXP x) {
-	return unimplemented("PRVALUE");
+	return ((call_PRVALUE) callbacks[PRVALUE_x])(x);
 }
 
 int PRSEEN(SEXP x) {
-	return (int) unimplemented("PRSEEN");
+	return ((call_PRSEEN) callbacks[PRSEEN_x])(x);
 }
 
 void SET_PRSEEN(SEXP x, int v) {
@@ -900,9 +818,8 @@ SEXP *STRING_PTR(SEXP x){
 }
 
 
-SEXP *VECTOR_PTR(SEXP x){
+SEXP * NORET VECTOR_PTR(SEXP x){
 	unimplemented("VECTOR_PTR");
-	return NULL;
 }
 
 SEXP Rf_asChar(SEXP x){
@@ -949,7 +866,7 @@ SEXP ATTRIB(SEXP x){
 }
 
 int OBJECT(SEXP x){
-	return (int) unimplemented("OBJECT");
+	return (int) ((call_OBJECT) callbacks[OBJECT_x])(x);
 }
 
 int MARK(SEXP x){
@@ -958,7 +875,7 @@ int MARK(SEXP x){
 }
 
 int NAMED(SEXP x){
-	return (int) unimplemented("NAMED");
+	return (int) ((call_NAMED) callbacks[NAMED_x])(x);
 }
 
 int REFCNT(SEXP x){
@@ -975,6 +892,7 @@ void SET_TYPEOF(SEXP x, int v){
 }
 
 SEXP SET_TYPEOF_FASTR(SEXP x, int v){
+	return ((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v);
 }
 
 void SET_NAMED(SEXP x, int v){
@@ -986,36 +904,7 @@ void SET_ATTRIB(SEXP x, SEXP v){
 }
 
 void DUPLICATE_ATTRIB(SEXP to, SEXP from){
-	unimplemented("DUPLICATE_ATTRIB");
-}
-
-char *dgettext(const char *domainname, const char *msgid) {
-	printf("dgettext: '%s'\n", msgid);
-	return (char*) msgid;
-}
-
-char *libintl_dgettext(const char *domainname, const char *msgid) {
-	return dgettext(domainname, msgid);
-}
-
-char *dngettext(const char *domainname, const char *msgid, const char * msgid_plural, unsigned long int n) {
-    printf("dngettext: singular - '%s' ; plural - '%s'\n", msgid, msgid_plural);
-    return (char*) (n == 1 ? msgid : msgid_plural);
-}
-
-void *DATAPTR(SEXP x) {
-	int type = TYPEOF(x);
-	if (type == INTSXP) {
-		return INTEGER(x);
-	} else if (type == REALSXP) {
-		return REAL(x);
-	} else if (type == LGLSXP) {
-		return LOGICAL(x);
-	} else {
-		printf("DATAPTR %d\n", type);
-		unimplemented("R_DATAPTR");
-		return NULL;
-	}
+	((call_DUPLICATE_ATTRIB) callbacks[DUPLICATE_ATTRIB_x])(to, from);
 }
 
 void R_qsort_I  (double *v, int *II, int i, int j) {
@@ -1031,14 +920,15 @@ R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
 }
 
 int IS_S4_OBJECT(SEXP x) {
-	return (int) unimplemented("IS_S4_OBJECT");
+	return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
 }
 
 void SET_S4_OBJECT(SEXP x) {
-	unimplemented("SET_S4_OBJECT");
+	((call_SET_S4_OBJECT) callbacks[SET_S4_OBJECT_x])(x);
 }
+
 void UNSET_S4_OBJECT(SEXP x) {
-	unimplemented("UNSET_S4_OBJECT");
+	((call_UNSET_S4_OBJECT) callbacks[UNSET_S4_OBJECT_x])(x);
 }
 
 Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
@@ -1071,6 +961,10 @@ Rboolean R_IsNamespaceEnv(SEXP rho) {
 	return (Rboolean) unimplemented("R_IsNamespaceEnv");
 }
 
+SEXP R_FindNamespace(SEXP info) {
+	return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info);
+}
+
 SEXP R_NamespaceEnvSpec(SEXP rho) {
 	return unimplemented("R_NamespaceEnvSpec");
 }
@@ -1096,11 +990,11 @@ void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) {
 }
 
 Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
-	return (Rboolean) unimplemented("R_BindingIsLocked");
+	return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
 }
 
 Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
-    // TODO: for now, I belive all bindings are false
+    // TODO: for now, I believe all bindings are false
     return (Rboolean)0;
 }
 
@@ -1117,6 +1011,7 @@ SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
 }
 
 static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
+	unimplemented("R_tryEvalInternal");
 }
 
 SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) {
@@ -1138,7 +1033,7 @@ double R_strtod(const char *c, char **end) {
 }
 
 SEXP R_PromiseExpr(SEXP x) {
-	return unimplemented("R_PromiseExpr");
+	return ((call_R_PromiseExpr) callbacks[R_PromiseExpr_x])(x);
 }
 
 SEXP R_ClosureExpr(SEXP x) {
@@ -1150,31 +1045,31 @@ SEXP R_forceAndCall(SEXP e, int n, SEXP rho) {
 }
 
 SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) {
-	return unimplemented("R_MakeExternalPtr");
+	return ((call_R_MakeExternalPtr) callbacks[R_MakeExternalPtr_x])(p, tag, prot);
 }
 
 void *R_ExternalPtrAddr(SEXP s) {
-	return unimplemented("R_ExternalPtrAddr");
+	return ((call_R_ExternalPtrAddr) callbacks[R_ExternalPtrAddr_x])(s);
 }
 
 SEXP R_ExternalPtrTag(SEXP s) {
-	return unimplemented("R_ExternalPtrTag");
+	return ((call_R_ExternalPtrTag) callbacks[R_ExternalPtrTag_x])(s);
 }
 
-SEXP R_ExternalPtrProt(SEXP s) {
-	return unimplemented("R_ExternalPtrProt");
+SEXP R_ExternalPtrProtected(SEXP s) {
+	return ((call_R_ExternalPtrProtected) callbacks[R_ExternalPtrProtected_x])(s);
 }
 
 void R_SetExternalPtrAddr(SEXP s, void *p) {
-	unimplemented("R_SetExternalPtrAddr");
+	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
 }
 
 void R_SetExternalPtrTag(SEXP s, SEXP tag) {
-	unimplemented("R_SetExternalPtrTag");
+	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, tag);
 }
 
 void R_SetExternalPtrProtected(SEXP s, SEXP p) {
-	unimplemented("R_SetExternalPtrProtected");
+	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
 }
 
 void R_ClearExternalPtr(SEXP s) {
@@ -1222,11 +1117,11 @@ void R_RunWeakRefFinalizer(SEXP w) {
 }
 
 SEXP R_do_slot(SEXP obj, SEXP name) {
-	return unimplemented("R_do_slot");
+	return ((call_R_do_slot) callbacks[R_do_slot_x])(obj, name);
 }
 
 SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
-	return unimplemented("R_do_slot_assign");
+	return ((call_R_do_slot_assign) callbacks[R_do_slot_assign_x])(obj, name, value);
 }
 
 int R_has_slot(SEXP obj, SEXP name) {
@@ -1234,7 +1129,7 @@ int R_has_slot(SEXP obj, SEXP name) {
 }
 
 SEXP R_do_MAKE_CLASS(const char *what) {
-	return unimplemented("R_do_MAKE_CLASS");
+	return ((call_R_do_MAKE_CLASS) callbacks[R_do_MAKE_CLASS_x])(what);
 }
 
 SEXP R_getClassDef (const char *what) {
@@ -1242,15 +1137,15 @@ SEXP R_getClassDef (const char *what) {
 }
 
 SEXP R_do_new_object(SEXP class_def) {
-	return unimplemented("R_do_new_object");
+	return ((call_R_do_new_object) callbacks[R_do_new_object_x])(class_def);
 }
 
-int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) {
-	return (int) unimplemented("R_check_class_and_super");
+static SEXP nfiGetMethodsNamespace() {
+    return ((call_R_MethodsNamespace) callbacks[R_MethodsNamespace_x])();
 }
 
 int R_check_class_etc (SEXP x, const char **valid) {
-	return (int) unimplemented("R_check_class_etc");
+	return R_check_class_etc_helper(x, valid, nfiGetMethodsNamespace);
 }
 
 SEXP R_PreserveObject(SEXP x) {
@@ -1267,14 +1162,14 @@ void R_dot_Last(void) {
 
 
 Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
-	return (Rboolean) unimplemented("R_compute_identical");
+	return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
 }
 
 void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	unimplemented("Rf_copyListMatrix");
+	((call_Rf_copyListMatrix) callbacks[Rf_copyListMatrix_x])(s, t, byrow);
 }
 
 void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	unimplemented("Rf_copyMatrix");
+	((call_Rf_copyMatrix) callbacks[Rf_copyMatrix_x])(s, t, byrow);
 }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
index 2073ad00fe..93188c9e9e 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
@@ -51,7 +51,7 @@ void call_glob(char *pattern, void *closure) {
 	}
 }
 
-void call_readlink(void (*call_setresult)(char *link, int errno), char *path) {
+void call_readlink(void (*call_setresult)(char *link, int cerrno), char *path) {
 	char *link = NULL;
 	int cerrno = 0;
     char buf[4096];
@@ -65,7 +65,7 @@ void call_readlink(void (*call_setresult)(char *link, int errno), char *path) {
 	call_setresult(link, cerrno);
 }
 
-void call_strtol(void (*call_setresult)(long result, int errno), char *s, int base) {
+void call_strtol(void (*call_setresult)(long result, int cerrno), char *s, int base) {
     long rc = strtol(s, NULL, base);
 	call_setresult(rc, errno);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
index a03e58c1c2..94d50549cc 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
@@ -33,7 +33,7 @@ typedef SEXP (*call_Rf_ScalarInteger)(int value);
 typedef SEXP (*call_Rf_ScalarReal)(double value);
 typedef SEXP (*call_Rf_ScalarString)(SEXP value);
 typedef SEXP (*call_Rf_ScalarLogical)(int value);
-typedef SEXP (*call_Rf_allocateVector)(SEXPTYPE t, R_xlen_t len);
+typedef SEXP (*call_Rf_allocVector)(SEXPTYPE t, R_xlen_t len);
 typedef SEXP (*call_Rf_allocArray)(SEXPTYPE t, SEXP dims);
 typedef SEXP (*call_Rf_alloc3DArray)(SEXPTYPE t, int x, int y, int z);
 typedef SEXP (*call_Rf_allocMatrix)(SEXPTYPE mode, int nrow, int ncol);
@@ -52,7 +52,7 @@ typedef SEXP (*call_Rf_findVarInFrame3)(SEXP rho, SEXP sym, Rboolean b);
 typedef SEXP (*call_Rf_getAttrib)(SEXP vec, SEXP name);
 typedef SEXP (*call_Rf_GetOption1)(SEXP tag);
 typedef SEXP (*call_Rf_setAttrib)(SEXP vec, SEXP name, SEXP val);
-typedef SEXP (*call_Rf_duplicate)(SEXP x);
+typedef SEXP (*call_Rf_duplicate)(SEXP x, int v);
 typedef SEXP (*call_Rf_shallow_duplicate)(SEXP x);
 typedef SEXP (*call_Rf_coerceVector)(SEXP x, SEXPTYPE mode);
 typedef R_xlen_t (*call_Rf_any_duplicated)(SEXP x, Rboolean from_last);
@@ -234,7 +234,7 @@ typedef SEXP (*call_R_forceAndCall)(SEXP e, int n, SEXP rho);
 typedef SEXP (*call_R_MakeExternalPtr)(void *p, SEXP tag, SEXP prot);
 typedef void *(*call_R_ExternalPtrAddr)(SEXP s);
 typedef SEXP (*call_R_ExternalPtrTag)(SEXP s);
-typedef SEXP (*call_R_ExternalPtrProt)(SEXP s);
+typedef SEXP (*call_R_ExternalPtrProtected)(SEXP s);
 typedef void (*call_R_SetExternalPtrAddr)(SEXP s, void *p);
 typedef void (*call_R_SetExternalPtrTag)(SEXP s, SEXP tag);
 typedef void (*call_R_SetExternalPtrProtected)(SEXP s, SEXP p);
@@ -267,6 +267,7 @@ typedef void (*call_GetRNGstate)();
 typedef void (*call_PutRNGstate)();
 typedef SEXP (*call_R_BaseEnv)();
 typedef SEXP (*call_R_BaseNamespace)();
+typedef SEXP (*call_R_MethodsNamespace)();
 typedef SEXP (*call_R_GlobalEnv)();
 typedef SEXP (*call_R_NamespaceRegistry)();
 typedef SEXP (*call_R_Interactive)();
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
index 3fcb214834..0a457d98f0 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
@@ -36,125 +36,128 @@
 #define GetRNGstate_x 7
 #define INTEGER_x 8
 #define IS_S4_OBJECT_x 9
-#define LENGTH_x 10
-#define LOGICAL_x 11
-#define NAMED_x 12
-#define OBJECT_x 13
-#define PRCODE_x 14
-#define PRENV_x 15
-#define PRINTNAME_x 16
-#define PRSEEN_x 17
-#define PRVALUE_x 18
-#define PutRNGstate_x 19
-#define RAW_x 20
-#define RDEBUG_x 21
-#define REAL_x 22
-#define RSTEP_x 23
-#define R_BaseEnv_x 24
-#define R_BaseNamespace_x 25
-#define R_BindingIsLocked_x 26
-#define R_CHAR_x 27
-#define R_CleanUp_x 28
-#define R_ExternalPtrAddr_x 29
-#define R_ExternalPtrProt_x 30
-#define R_ExternalPtrTag_x 31
-#define R_FindNamespace_x 32
-#define R_GetConnection_x 33
-#define R_GlobalContext_x 34
-#define R_GlobalEnv_x 35
-#define R_HomeDir_x 36
-#define R_Interactive_x 37
-#define R_MakeExternalPtr_x 38
-#define R_NamespaceRegistry_x 39
-#define R_NewHashedEnv_x 40
-#define R_ParseVector_x 41
-#define R_PromiseExpr_x 42
-#define R_ReadConnection_x 43
-#define R_SetExternalPtrAddr_x 44
-#define R_SetExternalPtrProt_x 45
-#define R_SetExternalPtrTag_x 46
-#define R_ToplevelExec_x 47
-#define R_WriteConnection_x 48
-#define R_computeIdentical_x 49
-#define R_do_MAKE_CLASS_x 50
-#define R_do_new_object_x 51
-#define R_do_slot_x 52
-#define R_do_slot_assign_x 53
-#define R_getContextCall_x 54
-#define R_getContextEnv_x 55
-#define R_getContextFun_x 56
-#define R_getContextSrcRef_x 57
-#define R_getGlobalFunctionContext_x 58
-#define R_getParentFunctionContext_x 59
-#define R_insideBrowser_x 60
-#define R_isEqual_x 61
-#define R_isGlobal_x 62
-#define R_lsInternal3_x 63
-#define R_new_custom_connection_x 64
-#define R_tryEval_x 65
-#define Rf_GetOption1_x 66
-#define Rf_PairToVectorList_x 67
-#define Rf_ScalarDouble_x 68
-#define Rf_ScalarInteger_x 69
-#define Rf_ScalarLogical_x 70
-#define Rf_ScalarString_x 71
-#define Rf_allocateArray_x 72
-#define Rf_allocateMatrix_x 73
-#define Rf_allocateVector_x 74
-#define Rf_anyDuplicated_x 75
-#define Rf_asChar_x 76
-#define Rf_asInteger_x 77
-#define Rf_asLogical_x 78
-#define Rf_asReal_x 79
-#define Rf_classgets_x 80
-#define Rf_coerceVector_x 81
-#define Rf_cons_x 82
-#define Rf_copyListMatrix_x 83
-#define Rf_copyMatrix_x 84
-#define Rf_defineVar_x 85
-#define Rf_duplicate_x 86
-#define Rf_error_x 87
-#define Rf_eval_x 88
-#define Rf_findVar_x 89
-#define Rf_findVarInFrame_x 90
-#define Rf_findVarInFrame3_x 91
-#define Rf_findfun_x 92
-#define Rf_getAttrib_x 93
-#define Rf_gsetVar_x 94
-#define Rf_inherits_x 95
-#define Rf_install_x 96
-#define Rf_installChar_x 97
-#define Rf_isNull_x 98
-#define Rf_isString_x 99
-#define Rf_lengthgets_x 100
-#define Rf_mkCharLenCE_x 101
-#define Rf_ncols_x 102
-#define Rf_nrows_x 103
-#define Rf_setAttrib_x 104
-#define Rf_warning_x 105
-#define Rf_warningcall_x 106
-#define Rprintf_x 107
-#define SETCADR_x 108
-#define SETCAR_x 109
-#define SETCDR_x 110
-#define SET_RDEBUG_x 111
-#define SET_RSTEP_x 112
-#define SET_STRING_ELT_x 113
-#define SET_SYMVALUE_x 114
-#define SET_TAG_x 115
-#define SET_TYPEOF_FASTR_x 116
-#define SET_VECTOR_ELT_x 117
-#define STRING_ELT_x 118
-#define SYMVALUE_x 119
-#define TAG_x 120
-#define TYPEOF_x 121
-#define VECTOR_ELT_x 122
-#define getConnectionClassString_x 123
-#define getOpenModeString_x 124
-#define getSummaryDescription_x 125
-#define isSeekable_x 126
-#define unif_rand_x 127
+#define SET_S4_OBJECT_x 10
+#define UNSET_S4_OBJECT_x 11
+#define LENGTH_x 12
+#define LOGICAL_x 13
+#define NAMED_x 14
+#define OBJECT_x 15
+#define PRCODE_x 16
+#define PRENV_x 17
+#define PRINTNAME_x 18
+#define PRSEEN_x 19
+#define PRVALUE_x 20
+#define PutRNGstate_x 21
+#define RAW_x 22
+#define RDEBUG_x 23
+#define REAL_x 24
+#define RSTEP_x 25
+#define R_BaseEnv_x 26
+#define R_BaseNamespace_x 27
+#define R_BindingIsLocked_x 28
+#define R_CHAR_x 29
+#define R_CleanUp_x 30
+#define R_ExternalPtrAddr_x 31
+#define R_ExternalPtrProtected_x 32
+#define R_ExternalPtrTag_x 33
+#define R_FindNamespace_x 34
+#define R_GetConnection_x 35
+#define R_GlobalContext_x 36
+#define R_GlobalEnv_x 37
+#define R_HomeDir_x 38
+#define R_Interactive_x 39
+#define R_MakeExternalPtr_x 40
+#define R_MethodsNamespace_x 41
+#define R_NamespaceRegistry_x 42
+#define R_NewHashedEnv_x 43
+#define R_ParseVector_x 44
+#define R_PromiseExpr_x 45
+#define R_ReadConnection_x 46
+#define R_SetExternalPtrAddr_x 47
+#define R_SetExternalPtrProtected_x 48
+#define R_SetExternalPtrTag_x 49
+#define R_ToplevelExec_x 50
+#define R_WriteConnection_x 51
+#define R_compute_identical_x 52
+#define R_do_MAKE_CLASS_x 53
+#define R_do_new_object_x 54
+#define R_do_slot_x 55
+#define R_do_slot_assign_x 56
+#define R_getContextCall_x 57
+#define R_getContextEnv_x 58
+#define R_getContextFun_x 59
+#define R_getContextSrcRef_x 60
+#define R_getGlobalFunctionContext_x 61
+#define R_getParentFunctionContext_x 62
+#define R_insideBrowser_x 63
+#define R_isEqual_x 64
+#define R_isGlobal_x 65
+#define R_lsInternal3_x 66
+#define R_new_custom_connection_x 67
+#define R_tryEval_x 68
+#define Rf_GetOption1_x 69
+#define Rf_PairToVectorList_x 70
+#define Rf_ScalarDouble_x 71
+#define Rf_ScalarInteger_x 72
+#define Rf_ScalarLogical_x 73
+#define Rf_ScalarString_x 74
+#define Rf_allocArray_x 75
+#define Rf_allocMatrix_x 76
+#define Rf_allocVector_x 77
+#define Rf_any_duplicated_x 78
+#define Rf_asChar_x 79
+#define Rf_asInteger_x 80
+#define Rf_asLogical_x 81
+#define Rf_asReal_x 82
+#define Rf_classgets_x 83
+#define Rf_coerceVector_x 84
+#define Rf_cons_x 85
+#define Rf_copyListMatrix_x 86
+#define Rf_copyMatrix_x 87
+#define Rf_defineVar_x 88
+#define Rf_duplicate_x 89
+#define Rf_error_x 90
+#define Rf_eval_x 91
+#define Rf_findVar_x 92
+#define Rf_findVarInFrame_x 93
+#define Rf_findVarInFrame3_x 94
+#define Rf_findFun_x 95
+#define Rf_getAttrib_x 96
+#define Rf_gsetVar_x 97
+#define Rf_inherits_x 98
+#define Rf_install_x 99
+#define Rf_installChar_x 100
+#define Rf_isNull_x 101
+#define Rf_isString_x 102
+#define Rf_lengthgets_x 103
+#define Rf_mkCharLenCE_x 104
+#define Rf_ncols_x 105
+#define Rf_nrows_x 106
+#define Rf_setAttrib_x 107
+#define Rf_warning_x 108
+#define Rf_warningcall_x 109
+#define Rprintf_x 110
+#define SETCADR_x 111
+#define SETCAR_x 112
+#define SETCDR_x 113
+#define SET_RDEBUG_x 114
+#define SET_RSTEP_x 115
+#define SET_STRING_ELT_x 116
+#define SET_SYMVALUE_x 117
+#define SET_TAG_x 118
+#define SET_TYPEOF_FASTR_x 119
+#define SET_VECTOR_ELT_x 120
+#define STRING_ELT_x 121
+#define SYMVALUE_x 122
+#define TAG_x 123
+#define TYPEOF_x 124
+#define VECTOR_ELT_x 125
+#define getConnectionClassString_x 126
+#define getOpenModeString_x 127
+#define getSummaryDescription_x 128
+#define isSeekable_x 129
+#define unif_rand_x 130
 
-#define CALLBACK_TABLE_SIZE 128
+#define CALLBACK_TABLE_SIZE 131
 
 #endif // CALLBACKSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
new file mode 100644
index 0000000000..26a0c8bd18
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <rffiutils.h>
+
+void* unimplemented(char *f) {
+	printf("unimplemented %s\n", f);
+	exit(1);
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
index 4068091952..9a6c701305 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
@@ -32,4 +32,9 @@
 
 extern void init_memory();
 
+// use for an unimplemented API function
+void *unimplemented(char *msg) __attribute__((noreturn));
+// use for any fatal error
+void fatalError(char *msg) __attribute__((noreturn));
+
 #endif
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
index acd535c135..a16e5c6a92 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
@@ -20,19 +20,24 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#include <Rinternals.h>
+#include <string.h>
+#include <Rinterface.h>
 #include <trufflenfi.h>
+#include <rffiutils.h>
 
+// Indices into RFFIVariables enum
+// The commented out entries are not used as they are remapped
+// as functions and the name clashes with the callback index for that
 #define R_Home_x 0
 #define R_TempDir_x 1
 #define R_NilValue_x 2
 #define R_UnboundValue_x 3
 #define R_MissingArg_x 4
-#define R_GlobalEnv_x 5
+//#define R_GlobalEnv_x 5
 #define R_EmptyEnv_x 6
-#define R_BaseEnv_x 7
-#define R_BaseNamespace_x 8
-#define R_NamespaceRegistry_x 9
+//#define R_BaseEnv_x 7
+//#define R_BaseNamespace_x 8
+//#define R_NamespaceRegistry_x 9
 #define R_Srcref_x 10
 #define R_Bracket2Symbol_x 11
 #define R_BracketSymbol_x 12
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index aabe6ec390..2bd5a0a98a 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-21
+22
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 a980e216b3..a6e270047d 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
@@ -371,7 +371,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object Rf_allocateVector(int mode, int n) {
+    public Object Rf_allocVector(int mode, int n) {
         SEXPTYPE type = SEXPTYPE.mapInt(mode);
         if (n < 0) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED);
@@ -403,7 +403,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object Rf_allocateArray(int mode, Object dimsObj) {
+    public Object Rf_allocArray(int mode, Object dimsObj) {
         RIntVector dims = (RIntVector) dimsObj;
         int n = 1;
         int[] newDims = new int[dims.getLength()];
@@ -412,7 +412,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             newDims[i] = dims.getDataAt(i);
             n *= newDims[i];
         }
-        RAbstractVector result = (RAbstractVector) Rf_allocateVector(mode, n);
+        RAbstractVector result = (RAbstractVector) Rf_allocVector(mode, n);
         setDims(newDims, result);
         return result;
 
@@ -424,7 +424,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object Rf_allocateMatrix(int mode, int nrow, int ncol) {
+    public Object Rf_allocMatrix(int mode, int nrow, int ncol) {
         SEXPTYPE type = SEXPTYPE.mapInt(mode);
         if (nrow < 0 || ncol < 0) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_EXTENTS_TO_MATRIX);
@@ -601,7 +601,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int Rf_anyDuplicated(Object x, int fromLast) {
+    public int Rf_any_duplicated(Object x, int fromLast) {
         RAbstractVector vec = (RAbstractVector) x;
         if (vec.getLength() == 0) {
             return 0;
@@ -747,7 +747,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object Rf_findfun(Object symbolObj, Object envObj) {
+    public Object Rf_findFun(Object symbolObj, Object envObj) {
         guarantee(envObj instanceof REnvironment);
         REnvironment env = (REnvironment) envObj;
         guarantee(symbolObj instanceof RSymbol);
@@ -792,7 +792,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int R_computeIdentical(Object x, Object y, int flags) {
+    public int R_compute_identical(Object x, Object y, int flags) {
         RFunction indenticalBuiltin = RContext.lookupBuiltin("identical");
         Object res = RContext.getEngine().evalFunction(indenticalBuiltin, null, null, null, x, y, RRuntime.asLogical((!((flags & 1) == 0))),
                         RRuntime.asLogical((!((flags & 2) == 0))), RRuntime.asLogical((!((flags & 4) == 0))), RRuntime.asLogical((!((flags & 8) == 0))), RRuntime.asLogical((!((flags & 16) == 0))));
@@ -1279,7 +1279,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object R_ExternalPtrProt(Object x) {
+    public Object R_ExternalPtrProtected(Object x) {
         RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class);
         return p.getProt();
     }
@@ -1297,7 +1297,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void R_SetExternalPtrProt(Object x, Object prot) {
+    public void R_SetExternalPtrProtected(Object x, Object prot) {
         RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class);
         p.setProt(prot);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index 1b38154133..218f407e58 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -40,6 +40,8 @@ public enum RFFIUpCallMethod {
     GetRNGstate("() : void"),
     INTEGER("(object) : object"),
     IS_S4_OBJECT("(object) : sint32"),
+    SET_S4_OBJECT("(object) : void"),
+    UNSET_S4_OBJECT("(object) : void"),
     LENGTH("(object) : sint32"),
     LOGICAL("(object) : object"),
     NAMED("(object) : sint32"),
@@ -60,7 +62,7 @@ public enum RFFIUpCallMethod {
     R_CHAR("(object) : object"),
     R_CleanUp("(sint32, sint32, sint32) : void"),
     R_ExternalPtrAddr("(object) : object"),
-    R_ExternalPtrProt("(object) : object"),
+    R_ExternalPtrProtected("(object) : object"),
     R_ExternalPtrTag("(object) : object"),
     R_FindNamespace("(object) : object"),
     R_GetConnection("(sint32) : object"),
@@ -69,17 +71,18 @@ public enum RFFIUpCallMethod {
     R_HomeDir("() : object"),
     R_Interactive("() : sint32"),
     R_MakeExternalPtr("(object, object, object) : object"),
+    R_MethodsNamespace("() : object"),
     R_NamespaceRegistry("() : object"),
     R_NewHashedEnv("(object, object) : object"),
     R_ParseVector("(object, sint32, object) : object"),
     R_PromiseExpr("(object) : object"),
     R_ReadConnection("(sint32, object) : sint32"),
     R_SetExternalPtrAddr("(object, object) : void"),
-    R_SetExternalPtrProt("(object, object) : void"),
+    R_SetExternalPtrProtected("(object, object) : void"),
     R_SetExternalPtrTag("(object, object) : void"),
     R_ToplevelExec("() : object"),
     R_WriteConnection("(sint32, object) : sint32"),
-    R_computeIdentical("(object, object, sint32) : sint32"),
+    R_compute_identical("(object, object, sint32) : sint32"),
     R_do_MAKE_CLASS("(string) : object"),
     R_do_new_object("(object) : object"),
     R_do_slot("(object, object) : object"),
@@ -102,10 +105,10 @@ public enum RFFIUpCallMethod {
     Rf_ScalarInteger("(sint32) : object"),
     Rf_ScalarLogical("(sint32) : object"),
     Rf_ScalarString("(object) : object"),
-    Rf_allocateArray("(sint32, object) : object"),
-    Rf_allocateMatrix("(sint32, sint32, sint32) : object"),
-    Rf_allocateVector("(sint32, sint32) : object"),
-    Rf_anyDuplicated("(object, sint32) : sint32"),
+    Rf_allocArray("(sint32, object) : object"),
+    Rf_allocMatrix("(sint32, sint32, sint32) : object"),
+    Rf_allocVector("(sint32, sint32) : object"),
+    Rf_any_duplicated("(object, sint32) : sint32"),
     Rf_asChar("(object) : object"),
     Rf_asInteger("(object) : sint32"),
     Rf_asLogical("(object) : sint32"),
@@ -122,7 +125,7 @@ public enum RFFIUpCallMethod {
     Rf_findVar("(object, object) : object"),
     Rf_findVarInFrame("(object, object) : object"),
     Rf_findVarInFrame3("(object, object, sint32) : object"),
-    Rf_findfun("(object, object) : object"),
+    Rf_findFun("(object, object) : object"),
     Rf_getAttrib("(object, object) : object"),
     Rf_gsetVar("(object, object, object) : void"),
     Rf_inherits("(string, object) : sint32"),
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 9ad307eea7..2bf8a0d955 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
@@ -214,21 +214,21 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object Rf_allocateVector(int mode, int n) {
+    public Object Rf_allocVector(int mode, int n) {
         RFFIUtils.traceUpCall("Rf_allocateVector", mode, n);
-        return delegate.Rf_allocateVector(mode, n);
+        return delegate.Rf_allocVector(mode, n);
     }
 
     @Override
-    public Object Rf_allocateArray(int mode, Object dimsObj) {
+    public Object Rf_allocArray(int mode, Object dimsObj) {
         RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj);
         return null;
     }
 
     @Override
-    public Object Rf_allocateMatrix(int mode, int nrow, int ncol) {
+    public Object Rf_allocMatrix(int mode, int nrow, int ncol) {
         RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow);
-        return delegate.Rf_allocateMatrix(mode, nrow, ncol);
+        return delegate.Rf_allocMatrix(mode, nrow, ncol);
     }
 
     @Override
@@ -328,9 +328,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int Rf_anyDuplicated(Object x, int fromLast) {
+    public int Rf_any_duplicated(Object x, int fromLast) {
         RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast);
-        return delegate.Rf_anyDuplicated(x, fromLast);
+        return delegate.Rf_any_duplicated(x, fromLast);
     }
 
     @Override
@@ -430,9 +430,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object Rf_findfun(Object symbolObj, Object envObj) {
+    public Object Rf_findFun(Object symbolObj, Object envObj) {
         RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj);
-        return delegate.Rf_findfun(symbolObj, envObj);
+        return delegate.Rf_findFun(symbolObj, envObj);
     }
 
     @Override
@@ -454,9 +454,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int R_computeIdentical(Object x, Object y, int flags) {
+    public int R_compute_identical(Object x, Object y, int flags) {
         RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags);
-        return delegate.R_computeIdentical(x, y, flags);
+        return delegate.R_compute_identical(x, y, flags);
     }
 
     @Override
@@ -700,9 +700,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object R_ExternalPtrProt(Object x) {
+    public Object R_ExternalPtrProtected(Object x) {
         RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
-        return delegate.R_ExternalPtrProt(x);
+        return delegate.R_ExternalPtrProtected(x);
     }
 
     @Override
@@ -718,9 +718,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void R_SetExternalPtrProt(Object x, Object prot) {
+    public void R_SetExternalPtrProtected(Object x, Object prot) {
         RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
-        delegate.R_SetExternalPtrProt(x, prot);
+        delegate.R_SetExternalPtrProtected(x, prot);
     }
 
     @Override
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 6fe58f99a7..295eaa8c02 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
@@ -108,11 +108,11 @@ public interface StdUpCallsRFFI {
 
     void Rf_warningcall(Object call, @RFFICstring Object msg);
 
-    Object Rf_allocateVector(int mode, int n);
+    Object Rf_allocVector(int mode, int n);
 
-    Object Rf_allocateArray(int mode, Object dimsObj);
+    Object Rf_allocArray(int mode, Object dimsObj);
 
-    Object Rf_allocateMatrix(int mode, int nrow, int ncol);
+    Object Rf_allocMatrix(int mode, int nrow, int ncol);
 
     int Rf_nrows(Object x);
 
@@ -146,7 +146,7 @@ public interface StdUpCallsRFFI {
 
     Object Rf_duplicate(Object x, int deep);
 
-    int Rf_anyDuplicated(Object x, int fromLast);
+    int Rf_any_duplicated(Object x, int fromLast);
 
     Object PRINTNAME(Object x);
 
@@ -180,7 +180,7 @@ public interface StdUpCallsRFFI {
 
     Object Rf_eval(Object expr, Object env);
 
-    Object Rf_findfun(Object symbolObj, Object envObj);
+    Object Rf_findFun(Object symbolObj, Object envObj);
 
     Object Rf_GetOption1(Object tag);
 
@@ -188,7 +188,7 @@ public interface StdUpCallsRFFI {
 
     void DUPLICATE_ATTRIB(Object to, Object from);
 
-    int R_computeIdentical(Object x, Object y, int flags);
+    int R_compute_identical(Object x, Object y, int flags);
 
     void Rf_copyListMatrix(Object s, Object t, int byrow);
 
@@ -238,13 +238,13 @@ public interface StdUpCallsRFFI {
 
     Object R_ExternalPtrTag(Object x);
 
-    Object R_ExternalPtrProt(Object x);
+    Object R_ExternalPtrProtected(Object x);
 
     void R_SetExternalPtrAddr(Object x, long addr);
 
     void R_SetExternalPtrTag(Object x, Object tag);
 
-    void R_SetExternalPtrProt(Object x, Object prot);
+    void R_SetExternalPtrProtected(Object x, Object prot);
 
     void R_CleanUp(int sa, int status, int runlast);
 
diff --git a/mx.fastr/mx_fastr_mkgramrd.py b/mx.fastr/mx_fastr_mkgramrd.py
index a951e04a14..d01b63fc38 100644
--- a/mx.fastr/mx_fastr_mkgramrd.py
+++ b/mx.fastr/mx_fastr_mkgramrd.py
@@ -44,7 +44,7 @@ extern SEXP FASTR_R_EmptyEnv();
 extern SEXP R_NewHashedEnv(SEXP a, SEXP b);
 
 char *dgettext(const char *p, const char *msgid) {
-return msgid;
+return (char *)msgid;
 }
 
 int imax2(int x, int y)
-- 
GitLab


From 8f0bf1fa23d0e1ef751ed3e8d891b2e487d2a7be Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 4 May 2017 20:03:50 -0700
Subject: [PATCH 338/402] [GR-2311] Fix managed build Makefile

---
 ci.hocon                                      | 10 ++++++
 .../library/base/Makefile                     | 33 ++++++++++++-------
 2 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/ci.hocon b/ci.hocon
index 7248925ba3..ff92a88670 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -114,6 +114,15 @@ gateTestLinuxNFI : ${gateTestCommon} {
   }
 }
 
+gateTestManagedLinux: ${common} {
+  environment :  {
+      FASTR_MANAGED : "true"
+  }
+  run : [
+    ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac"]
+  ]
+}
+
 
 # This performs a number of "style" checks on the code to ensure it confirms to the project standards.
 
@@ -161,4 +170,5 @@ builds = [
   ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate], name: "gate-style-linux-amd64"}
   ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate], name: "gate-rbcheck-linux-amd64"}
   ${internalPkgtest}          {capabilities : [linux, amd64],  targets : [gate], name: "gate-internal-pkgtest-linux-amd64"}
+  ${gateTestManagedLinux}     {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-managed-linux-amd64"}
 ]
diff --git a/com.oracle.truffle.r.native/library/base/Makefile b/com.oracle.truffle.r.native/library/base/Makefile
index 997d0c4410..9e56056560 100644
--- a/com.oracle.truffle.r.native/library/base/Makefile
+++ b/com.oracle.truffle.r.native/library/base/Makefile
@@ -22,26 +22,37 @@
 #
 
 ifeq ($(FASTR_RFFI),managed)
-BASE_UNCOMPRESSED = $(addprefix $(FASTR_LIBRARY_DIR)/base/R/, base.rdb)
-BASE_SCRIPT = $(addprefix $(FASTR_LIBRARY_DIR)/base/R/, base)
-LIB_PKG_POST = $(BASE_UNCOMPRESSED) $(BASE_SCRIPT)
+# lib.mk copies the GNU R library/base dir to the FastR library dir
+# so we have to build the "uncompressed" variant of GNU R in the PRE phase.
+LIB_PKG_PRE = pre.done 
+LIB_PKG_POST = post.done
+CLEAN_PKG = clean.done
 endif
 
 include ../lib.mk
 
 ifeq ($(FASTR_RFFI),managed)
-# original base assumes that "base" DLL is loaded, we change it to check for that first
-$(BASE_SCRIPT): $(GNUR_HOME)/library/base/R/base
-	sed 's|## populate C\/Fortran symbols|if (length(getLoadedDLLs()) > 0)|g' $(FASTR_LIBRARY_DIR)/base/R/base > $(FASTR_LIBRARY_DIR)/base/R/base.tmp
-	mv $(FASTR_LIBRARY_DIR)/base/R/base.tmp $(FASTR_LIBRARY_DIR)/base/R/base
 # The following changes GnuR's build script makebasedb.R so that it does not
-# compress the lazy load database, then it builds GnuR and copies the
-# uncompressed base package database to FastR library location
-$(BASE_UNCOMPRESSED): $(GNUR_HOME)/src/library/base/all.R
+# compress the lazy load database, then it (re)builds GnuR 
+pre.done:
 	cp $(GNUR_HOME)/src/library/base/makebasedb.R $(GNUR_HOME)/src/library/base/makebasedb.R.tmp
 	sed 's|compress = TRUE|compress = FALSE|g' $(GNUR_HOME)/src/library/base/makebasedb.R.tmp > $(GNUR_HOME)/src/library/base/makebasedb.R
+# force a base rebuild
+	rm $(GNUR_HOME)/src/library/base/all.R
 	(cd $(GNUR_HOME); $(MAKE))
-	cp $(GNUR_HOME)/library/$(PKG)/R/base.rd* $(FASTR_LIBRARY_DIR)/base/R/
+	touch pre.done
+
+# original base assumes that "base" DLL is loaded, we change it to check for that first
+post.done:
+	sed 's|## populate C\/Fortran symbols|if (length(getLoadedDLLs()) > 0)|g' $(FASTR_LIBRARY_DIR)/base/R/base > $(FASTR_LIBRARY_DIR)/base/R/base.tmp
+	mv $(FASTR_LIBRARY_DIR)/base/R/base.tmp $(FASTR_LIBRARY_DIR)/base/R/base
 	mv $(GNUR_HOME)/src/library/base/makebasedb.R.tmp $(GNUR_HOME)/src/library/base/makebasedb.R
+# force a base rebuild
+	rm $(GNUR_HOME)/src/library/base/all.R
+# rebuild GNU R in compressed mode
 	(cd $(GNUR_HOME); $(MAKE))
+	touch post.done
+
+clean.done:
+	rm -f post.done pre.done
 endif
-- 
GitLab


From 626745660fb4e1f142829cdc7b62e7098a40130b Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 5 May 2017 09:58:32 -0700
Subject: [PATCH 339/402] [GR-3971] Update truffle import; stub out Tck test
 objectWithKeyInfoAttributes

---
 .../src/com/oracle/truffle/r/test/tck/FastRTckTest.java     | 6 ++++++
 mx.fastr/suite.py                                           | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 48193aea07..a19cf407da 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -285,6 +285,12 @@ public class FastRTckTest extends TruffleTCK {
         return "objectWithValueAndAddProperty";
     }
 
+    @Override
+    protected String objectWithKeyInfoAttributes() {
+        // TODO
+        return null;
+    }
+
     @Override
     protected String callMethod() {
         return "callMethod";
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 1e31f049ba..7c2d28b476 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "01a039cbfc6238fd78d9159292495f93d6428f2a",
+               "version" : "8ee92107d834749dc2355cf48062e08d49e02a67",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From 84c1962c2d8a22bc45f1b01af2f3f7de6761c65f Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 5 May 2017 10:33:55 -0700
Subject: [PATCH 340/402] Change to ForeignAccess.Factory26 in
 RAbstractVectorAccessFactory

---
 .../r/engine/interop/RAbstractVectorAccessFactory.java   | 9 +++++++--
 .../src/com/oracle/truffle/r/test/tck/FastRTckTest.java  | 2 +-
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
index f5b6dbbb1b..c5ee552ba3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
@@ -28,7 +28,7 @@ import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.ForeignAccess.Factory18;
+import com.oracle.truffle.api.interop.ForeignAccess.Factory26;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
-public final class RAbstractVectorAccessFactory implements Factory18 {
+public final class RAbstractVectorAccessFactory implements Factory26 {
 
     static class VectorSizeNode extends RootNode {
 
@@ -188,4 +188,9 @@ public final class RAbstractVectorAccessFactory implements Factory18 {
     public CallTarget accessKeys() {
         return null;
     }
+
+    @Override
+    public CallTarget accessKeyInfo() {
+        return null;
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index a19cf407da..1743604857 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
-- 
GitLab


From 884db05a82fa5552d5dc3cfbab06f196cda86c45 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Fri, 5 May 2017 14:10:06 +0200
Subject: [PATCH 341/402] support interop KEY_INFO message

---
 .../truffle/r/engine/interop/RListMR.java     |  50 ++++++++-
 .../r/test/engine/interop/RListMRTest.java    | 100 ++++++++++++++++++
 .../truffle/r/test/tck/FastRTckTest.java      |  11 +-
 mx.fastr/suite.py                             |   2 +-
 4 files changed, 154 insertions(+), 9 deletions(-)
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
index be2017c372..e48a1f20d3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
@@ -22,12 +22,14 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -36,7 +38,9 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNames
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 
 @MessageResolution(receiverType = RList.class, language = TruffleRLanguage.class)
 public class RListMR {
@@ -77,7 +81,7 @@ public class RListMR {
 
     @Resolve(message = "WRITE")
     public abstract static class RListWriteNode extends Node {
-        @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
+        @Child private ReplaceVectorNode replace = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
         @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
         @SuppressWarnings("try")
@@ -97,7 +101,7 @@ public class RListMR {
                 } else if (value instanceof Byte) {
                     value = (int) ((Byte) value).byteValue();
                 }
-                Object x = extract.apply(frame, receiver, new Object[]{field}, value);
+                Object x = replace.apply(frame, receiver, new Object[]{field}, value);
                 return x;
             }
         }
@@ -116,6 +120,48 @@ public class RListMR {
         }
     }
 
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RListKeyInfoNode extends Node {
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+        @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
+        @Child private ExtractVectorNode extractNode;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        private static final int READABLE = 1 << 1;
+        private static final int WRITABLE = 1 << 2;
+        private static final int INVOCABLE = 1 << 3;
+        private static final int INTERNAL = 1 << 4;
+
+        @SuppressWarnings("try")
+        protected Object access(VirtualFrame frame, RList receiver, String identifier) {
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                int info = 0;
+                RStringVector names = getNamesNode.getNames(receiver);
+                for (int i = 0; i < names.getLength(); i++) {
+                    if (identifier.equals(names.getDataAt(i))) {
+                        info = 1;
+                        break;
+                    }
+                }
+                if (unknownIdentifier.profile(info == 0)) {
+                    return info;
+                }
+
+                info = info + READABLE + WRITABLE;
+                if (extractNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+                }
+                Object value = extractNode.applyAccessField(frame, receiver, identifier);
+                if (value instanceof RFunction) {
+                    info = info + INVOCABLE;
+                }
+                return info;
+            }
+        }
+    }
+
     @CanResolve
     public abstract static class RListCheck extends Node {
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java
new file mode 100644
index 0000000000..a1af763c75
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.engine.interop;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+
+import org.junit.Test;
+
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class RListMRTest {
+
+    @Test
+    public void testKeysReadWrite() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
+        TruffleObject l = createRListTruffleObject("n1=1L, n2=2L, 3, 4");
+
+        TruffleObject keys = ForeignAccess.sendKeys(Message.KEYS.createNode(), l);
+        assertEquals("n1", ForeignAccess.sendRead(Message.READ.createNode(), keys, 0));
+        assertEquals("n2", ForeignAccess.sendRead(Message.READ.createNode(), keys, 1));
+        assertEquals("", ForeignAccess.sendRead(Message.READ.createNode(), keys, 2));
+        assertEquals("", ForeignAccess.sendRead(Message.READ.createNode(), keys, 3));
+
+        assertEquals(4, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), keys));
+        assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, "n1"));
+        assertEquals(2, ForeignAccess.sendRead(Message.READ.createNode(), l, "n2"));
+
+        // TODO fails - should this return NULL as in l[""] or 3 as in l$""
+        // ElementAccessMode.FIELD_SUBSCRIPT vs .SUBSCRIPT doesn't seem to have any effect
+        // assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), l, ""));
+
+        // TODO - more tests for NA, ... ?
+
+        l = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "n2", 123);
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), l, "n2"));
+    }
+
+    @Test
+    public void testKeysInfo() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
+        TruffleObject l = createRListTruffleObject("n1=1, n2=2");
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+        assertFalse(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "n2");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        l = createRListTruffleObject("f=function() {}");
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "f");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+    }
+
+    private TruffleObject createRListTruffleObject(String values) {
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
+        Source src = Source.newBuilder("list(" + values + ")").mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        return result.as(TruffleObject.class);
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 1743604857..967e2d5595 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -152,6 +152,7 @@ public class FastRTckTest extends TruffleTCK {
         "builtinFunctionValue <- function() `+`\n" +
         "builtinFunctionType <- function() 'builtin'\n" +
         "valueWithSource <- function() intValue\n" +
+        "objectWithKeyInfoAttributes <- function() { list(rw=1, invocable=function(){ 'invoked' }) }\n" +
         "for (name in ls()) .fastr.interop.export(name, get(name))\n",
         RSource.Internal.TCK_INIT
     );
@@ -285,12 +286,6 @@ public class FastRTckTest extends TruffleTCK {
         return "objectWithValueAndAddProperty";
     }
 
-    @Override
-    protected String objectWithKeyInfoAttributes() {
-        // TODO
-        return null;
-    }
-
     @Override
     protected String callMethod() {
         return "callMethod";
@@ -511,4 +506,8 @@ public class FastRTckTest extends TruffleTCK {
         return "valueWithSource";
     }
 
+    protected String objectWithKeyInfoAttributes() {
+        return "objectWithKeyInfoAttributes";
+    }
+
 }
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 7c2d28b476..3b6c062c36 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "8ee92107d834749dc2355cf48062e08d49e02a67",
+               "version" : "7d960d6682ef3636cc7455e28132c1e537ea81f0",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From 0cf42b8d07649fc218c7d6334789401f333bb16b Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Fri, 5 May 2017 15:25:09 +0200
Subject: [PATCH 342/402] Foreign access message resolution for RS4Object

---
 .../r/engine/interop/REnvironmentMR.java      |  18 +--
 .../interop/RForeignAccessFactoryImpl.java    |   3 +
 .../truffle/r/engine/interop/RListMR.java     |  18 +--
 .../truffle/r/engine/interop/RS4ObjectMR.java | 117 ++++++++++++++++++
 .../truffle/r/engine/interop/Utils.java       |  45 +++++++
 5 files changed, 171 insertions(+), 30 deletions(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
index 5372d38a23..c3e7e288f8 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive;
+
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
@@ -32,7 +34,6 @@ import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -82,20 +83,7 @@ public class REnvironmentMR {
         @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, REnvironment receiver, String field, Object valueObj) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object value = valueObj;
-                if (value instanceof Short) {
-                    value = (int) ((Short) value).shortValue();
-                } else if (value instanceof Float) {
-                    float floatValue = ((Float) value).floatValue();
-                    value = new Double(floatValue);
-                } else if (value instanceof Boolean) {
-                    boolean booleanValue = ((Boolean) value).booleanValue();
-                    value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE;
-                } else if (value instanceof Character) {
-                    value = (int) ((Character) value).charValue();
-                } else if (value instanceof Byte) {
-                    value = (int) ((Byte) value).byteValue();
-                }
+                Object value = javaToRPrimitive(valueObj);
                 Object x = extract.apply(frame, receiver, new Object[]{field}, value);
                 return x;
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 2eb7170790..887d3a7741 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
@@ -107,6 +108,8 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return MakeResultImplMRForeign.ACCESS;
         } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl) {
             return CaptureNamesImplMRForeign.ACCESS;
+        } else if (obj instanceof RS4Object) {
+            return RS4ObjectMRForeign.ACCESS;
         } else {
             if (obj instanceof RAbstractVector) {
                 return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
index e48a1f20d3..13c996f9c4 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive;
+
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
@@ -35,7 +37,6 @@ import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -87,20 +88,7 @@ public class RListMR {
         @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RList receiver, String field, Object valueObj) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object value = valueObj;
-                if (value instanceof Short) {
-                    value = (int) ((Short) value).shortValue();
-                } else if (value instanceof Float) {
-                    float floatValue = ((Float) value).floatValue();
-                    value = new Double(floatValue);
-                } else if (value instanceof Boolean) {
-                    boolean booleanValue = ((Boolean) value).booleanValue();
-                    value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE;
-                } else if (value instanceof Character) {
-                    value = (int) ((Character) value).charValue();
-                } else if (value instanceof Byte) {
-                    value = (int) ((Byte) value).byteValue();
-                }
+                Object value = javaToRPrimitive(valueObj);
                 Object x = replace.apply(frame, receiver, new Object[]{field}, value);
                 return x;
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
new file mode 100644
index 0000000000..0c62ef582b
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
+import com.oracle.truffle.r.runtime.data.RAttributesLayout.RAttribute;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RS4Object;
+
+@MessageResolution(receiverType = RS4Object.class, language = TruffleRLanguage.class)
+public class RS4ObjectMR {
+
+    @Resolve(message = "IS_BOXED")
+    public abstract static class RS4ObjectIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RS4Object receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class RS4ObjectHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RS4Object receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class RS4ObjectIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RS4Object receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "READ")
+    public abstract static class RS4ObjectReadNode extends Node {
+        @Child private GetAttributeNode getAttributeNode = GetAttributeNode.create();
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+
+        @SuppressWarnings("try")
+        protected Object access(VirtualFrame frame, RS4Object receiver, String field) {
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                return getAttributeNode.execute(receiver, field);
+            }
+        }
+    }
+
+    @Resolve(message = "WRITE")
+    public abstract static class RS4ObjectWriteNode extends Node {
+        @Child private SetAttributeNode setAttributeNode = SetAttributeNode.create();
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+
+        @SuppressWarnings("try")
+        protected Object access(VirtualFrame frame, RS4Object receiver, String field, Object valueObj) {
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                Object value = Utils.javaToRPrimitive(valueObj);
+                setAttributeNode.execute(receiver, field, value);
+                return value;
+            }
+        }
+    }
+
+    @Resolve(message = "KEYS")
+    public abstract static class RS4ObjectKeysNode extends Node {
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+        @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
+
+        @SuppressWarnings("try")
+        protected Object access(RS4Object receiver) {
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                RAttribute[] attributes = arrayAttrAccess.execute(receiver.getAttributes());
+                String[] data = new String[attributes.length];
+                for (int i = 0; i < data.length; i++) {
+                    data[i] = attributes[i].getName();
+                }
+                return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
+            }
+        }
+    }
+
+    @CanResolve
+    public abstract static class RS4ObjectCheck extends Node {
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RS4Object;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java
new file mode 100644
index 0000000000..6d04453954
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.r.runtime.RRuntime;
+
+class Utils {
+    static Object javaToRPrimitive(Object valueObj) {
+        Object value = valueObj;
+        if (value instanceof Short) {
+            value = (int) ((Short) value).shortValue();
+        } else if (value instanceof Float) {
+            float floatValue = ((Float) value).floatValue();
+            value = new Double(floatValue);
+        } else if (value instanceof Boolean) {
+            boolean booleanValue = ((Boolean) value).booleanValue();
+            value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE;
+        } else if (value instanceof Character) {
+            value = (int) ((Character) value).charValue();
+        } else if (value instanceof Byte) {
+            value = (int) ((Byte) value).byteValue();
+        }
+        return value;
+    }
+}
-- 
GitLab


From ae1fe095a14519e3af401982a442b1e85d1717e8 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Tue, 18 Apr 2017 16:42:59 +0200
Subject: [PATCH 343/402] FastR Grid emulation: window resizing using Truffle
 Executor feature

---
 .../truffle/r/engine/shell/RCommand.java      |  4 +-
 .../r/library/fastrGrid/WindowDevice.java     |  6 ++
 .../nodes/test/BinaryArithmeticNodeTest.java  | 56 ++++++++++---------
 .../r/nodes/test/BinaryBooleanNodeTest.java   | 23 ++++----
 .../truffle/r/nodes/test/SpecialCallTest.java |  7 ++-
 .../truffle/r/nodes/test/TestUtilities.java   | 17 ++++++
 .../r/nodes/test/UnaryArithmeticNodeTest.java | 20 ++++---
 .../r/runtime/context/ContextInfo.java        | 11 +++-
 .../truffle/r/runtime/context/RContext.java   | 11 ++++
 9 files changed, 103 insertions(+), 52 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index 44d6bba5c3..acf0b204e5 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -227,7 +227,7 @@ public class RCommand {
                         lastStatus = 0;
                         try {
                             try {
-                                vm.eval(source);
+                                vm.eval(source).get();
                                 // checked exceptions are wrapped in RuntimeExceptions
                             } catch (RuntimeException e) {
                                 if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) {
@@ -281,7 +281,7 @@ public class RCommand {
             // JumpToTopLevelException can happen if user profile invokes browser (unlikely but
             // possible)
             try {
-                vm.eval(QUIT_EOF);
+                vm.eval(QUIT_EOF).get();
             } catch (JumpToTopLevelException e) {
                 Utils.systemExit(0);
             } catch (ExitException e) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
index 6183981d46..a2c5077fa4 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedJFrameDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.awt.JFrameDevice;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
  * Contains code specific to FastR device that shows the graphical output interactively in a window.
@@ -42,6 +43,11 @@ public final class WindowDevice {
 
     public static GridDevice createWindowDevice(int width, int height) {
         JFrameDevice frameDevice = JFrameDevice.create(width, height);
+        frameDevice.setResizeListener(() -> {
+            RContext.getInstance().schedule(() -> {
+                GridContext.getContext().evalInternalRFunction("redrawAll");
+            });
+        });
         return new BufferedJFrameDevice(frameDevice);
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java
index 2b5c1143dd..6b8438ab47 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryArithmeticNodeTest.java
@@ -22,7 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import static com.oracle.truffle.r.nodes.test.TestUtilities.copy;
 import static com.oracle.truffle.r.nodes.test.TestUtilities.createHandle;
+import static com.oracle.truffle.r.nodes.test.TestUtilities.withinTestContext;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createDoubleSequence;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createDoubleVectorFromScalar;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createEmptyComplexVector;
@@ -92,8 +94,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testScalarUnboxing(BinaryArithmeticFactory factory, RScalarVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = withinTestContext(() -> aOrig.copy());
+        RAbstractVector b = copy(bOrig);
         // unboxing cannot work if length is 1
         assumeThat(b.getLength(), is(1));
 
@@ -107,8 +109,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testVectorResult(BinaryArithmeticFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         assumeThat(a, is(not(instanceOf(RScalarVector.class))));
         assumeThat(b, is(not(instanceOf(RScalarVector.class))));
         assumeArithmeticCompatible(factory, a, b);
@@ -124,8 +126,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testSharing(BinaryArithmeticFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         assumeArithmeticCompatible(factory, a, b);
 
         // not part of this test, see #testEmptyArrays
@@ -189,7 +191,7 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testEmptyArrays(BinaryArithmeticFactory factory, RAbstractVector originalVector) {
-        RAbstractVector vector = originalVector.copy();
+        RAbstractVector vector = withinTestContext(() -> originalVector.copy());
         testEmptyArray(factory, vector, createEmptyLogicalVector());
         testEmptyArray(factory, vector, createEmptyIntVector());
         testEmptyArray(factory, vector, createEmptyDoubleVector());
@@ -199,7 +201,7 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testRNullConstantResult(BinaryArithmeticFactory factory, RAbstractVector originalVector) {
-        RAbstractVector vector = originalVector.copy();
+        RAbstractVector vector = withinTestContext(() -> originalVector.copy());
 
         RType type = vector.getRType() == RType.Complex ? RType.Complex : RType.Double;
         assertThat(executeArithmetic(factory, vector, RNull.instance), isEmptyVectorOf(type));
@@ -213,8 +215,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testCompleteness(BinaryArithmeticFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         assumeArithmeticCompatible(factory, a, b);
 
         // disable division they might produce NA values by division with 0
@@ -239,8 +241,8 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
         assumeArithmeticCompatible(factory, aOrig, bOrig);
 
         // we have to e careful not to change mutable vectors
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         if (a instanceof RShareable) {
             assert ((RShareable) a).isTemporary();
             ((RShareable) a).incRefCount();
@@ -250,29 +252,29 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
             ((RShareable) b).incRefCount();
         }
 
-        RVector<?> aMaterialized = a.copy().materialize();
-        RVector<?> bMaterialized = b.copy().materialize();
+        RVector<?> aMaterialized = withinTestContext(() -> a.copy().materialize());
+        RVector<?> bMaterialized = withinTestContext(() -> b.copy().materialize());
 
         aMaterialized.setAttr("a", "a");
         bMaterialized.setAttr("b", "b");
 
         if (a.getLength() == 0 || b.getLength() == 0) {
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()));
-            assertAttributes(executeArithmetic(factory, a, bMaterialized.copy()));
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b));
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)));
+            assertAttributes(executeArithmetic(factory, a, copy(bMaterialized)));
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), b));
         } else if (a.getLength() == b.getLength()) {
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()), "a", "b");
-            assertAttributes(executeArithmetic(factory, a, bMaterialized.copy()), "b");
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b), "a");
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)), "a", "b");
+            assertAttributes(executeArithmetic(factory, a, copy(bMaterialized)), "b");
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), b), "a");
         } else if (a.getLength() > b.getLength()) {
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()), "a");
-            assertAttributes(executeArithmetic(factory, a, bMaterialized.copy()));
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b), "a");
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)), "a");
+            assertAttributes(executeArithmetic(factory, a, copy(bMaterialized)));
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), b), "a");
         } else {
             assert a.getLength() < b.getLength();
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), bMaterialized.copy()), "b");
-            assertAttributes(executeArithmetic(factory, a, bMaterialized.copy()), "b");
-            assertAttributes(executeArithmetic(factory, aMaterialized.copy(), b));
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), copy(bMaterialized)), "b");
+            assertAttributes(executeArithmetic(factory, a, copy(bMaterialized)), "b");
+            assertAttributes(executeArithmetic(factory, copy(aMaterialized), b));
         }
     }
 
@@ -300,7 +302,7 @@ public class BinaryArithmeticNodeTest extends BinaryVectorTest {
             } catch (AssumptionViolatedException e) {
                 continue;
             }
-            executeArithmetic(factory, vector.copy(), vector.copy());
+            executeArithmetic(factory, copy(vector), copy(vector));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java
index 71aab4eccf..cfcc786168 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/BinaryBooleanNodeTest.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import static com.oracle.truffle.r.nodes.test.TestUtilities.copy;
 import static com.oracle.truffle.r.nodes.test.TestUtilities.createHandle;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createEmptyComplexVector;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createEmptyDoubleVector;
@@ -91,8 +92,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testScalarUnboxing(BooleanOperationFactory factory, RScalarVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         // unboxing cannot work if length is 1
         assumeThat(b.getLength(), is(1));
 
@@ -106,8 +107,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testVectorResult(BooleanOperationFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         assumeThat(a, is(not(instanceOf(RScalarVector.class))));
         assumeThat(b, is(not(instanceOf(RScalarVector.class))));
         assumeArithmeticCompatible(factory, a, b);
@@ -123,8 +124,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testSharing(BooleanOperationFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         assumeArithmeticCompatible(factory, aOrig, bOrig);
 
         // not part of this test, see #testEmptyArrays
@@ -194,7 +195,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testEmptyArrays(BooleanOperationFactory factory, RAbstractVector originalVector) {
-        RAbstractVector vector = originalVector.copy();
+        RAbstractVector vector = copy(originalVector);
         assumeArithmeticCompatible(factory, vector, createEmptyLogicalVector());
         assumeArithmeticCompatible(factory, vector, createEmptyIntVector());
         assumeArithmeticCompatible(factory, vector, createEmptyDoubleVector());
@@ -209,7 +210,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testRNullConstantResult(BooleanOperationFactory factory, RAbstractVector originalVector) {
-        RAbstractVector vector = originalVector.copy();
+        RAbstractVector vector = copy(originalVector);
         assumeFalse(isLogicOp(factory));
         assumeFalse(vector.getRType() == RType.Raw);
         assertThat(executeArithmetic(factory, vector, RNull.instance), isEmptyVectorOf(RType.Logical));
@@ -224,8 +225,8 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testCompleteness(BooleanOperationFactory factory, RAbstractVector aOrig, RAbstractVector bOrig) {
-        RAbstractVector a = aOrig.copy();
-        RAbstractVector b = bOrig.copy();
+        RAbstractVector a = copy(aOrig);
+        RAbstractVector b = copy(bOrig);
         assumeArithmeticCompatible(factory, a, b);
 
         Object result = executeArithmetic(factory, a, b);
@@ -249,7 +250,7 @@ public class BinaryBooleanNodeTest extends BinaryVectorTest {
             } catch (AssumptionViolatedException e) {
                 continue;
             }
-            executeArithmetic(factory, vector.copy(), vector.copy());
+            executeArithmetic(factory, copy(vector), copy(vector));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
index 24af4e1560..ae709c5c8b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RootWithBody;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -259,6 +261,7 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("{}", test, initialSpecialCount, initialNormalCount, finalSpecialCount, finalNormalCount);
     }
 
+    @SuppressWarnings("try")
     private static void assertCallCounts(String setup, String test, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) {
         if (!FastROptions.UseSpecials.getBooleanValue()) {
             return;
@@ -273,7 +276,7 @@ public class SpecialCallTest extends TestBase {
         RootCallTarget setupCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) setupExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
         RootCallTarget testCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) testExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
 
-        try {
+        try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
             CountCallsVisitor count1 = new CountCallsVisitor(testCallTarget);
             Assert.assertEquals("initial special call count '" + setup + "; " + test + "': ", initialSpecialCount, count1.special);
             Assert.assertEquals("initial normal call count '" + setup + "; " + test + "': ", initialNormalCount, count1.normal);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
index 2785376e2c..819cf8c85c 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import java.util.function.Supplier;
+
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
@@ -148,6 +150,21 @@ public class TestUtilities {
         return list;
     }
 
+    public static RAbstractVector copy(RAbstractVector orig) {
+        return withinTestContext(() -> orig.copy());
+    }
+
+    /**
+     * Certain code needs to be run within valid RContext, e.g. copying, which tries to report to
+     * memory tracer taken from RContext.
+     */
+    @SuppressWarnings("try")
+    public static <T> T withinTestContext(Supplier<T> action) {
+        try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
+            return action.get();
+        }
+    }
+
     /**
      * Creates a handle that emulates the behavior as if this node would be executed inside of an R
      * call.
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
index d729c5df6d..c575efa26a 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
@@ -22,7 +22,9 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import static com.oracle.truffle.r.nodes.test.TestUtilities.copy;
 import static com.oracle.truffle.r.nodes.test.TestUtilities.createHandle;
+import static com.oracle.truffle.r.nodes.test.TestUtilities.withinTestContext;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createDoubleSequence;
 import static com.oracle.truffle.r.runtime.data.RDataFactory.createIntSequence;
 import static com.oracle.truffle.r.runtime.ops.UnaryArithmetic.NEGATE;
@@ -81,7 +83,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testVectorResult(UnaryArithmeticFactory factory, RAbstractVector originalOperand) {
-        RAbstractVector operand = originalOperand.copy();
+        RAbstractVector operand = copy(originalOperand);
         assumeThat(operand, is(not(instanceOf(RScalarVector.class))));
 
         Object result = executeArithmetic(factory, operand);
@@ -94,7 +96,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testSharing(UnaryArithmeticFactory factory, RAbstractVector originalOperand) {
-        RAbstractVector operand = originalOperand.copy();
+        RAbstractVector operand = copy(originalOperand);
         // sharing does not work if a is a scalar vector
         assumeThat(true, is(isShareable(operand, operand.getRType())));
 
@@ -128,7 +130,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testCompleteness(UnaryArithmeticFactory factory, RAbstractVector originalOperand) {
-        RAbstractVector operand = originalOperand.copy();
+        RAbstractVector operand = copy(originalOperand);
         Object result = executeArithmetic(factory, operand);
 
         boolean resultComplete = isPrimitive(result) ? true : ((RAbstractVector) result).isComplete();
@@ -143,21 +145,21 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
 
     @Theory
     public void testCopyAttributes(UnaryArithmeticFactory factory, RAbstractVector originalOperand) {
-        RAbstractVector operand = originalOperand.copy();
+        RAbstractVector operand = copy(originalOperand);
         // we have to e careful not to change mutable vectors
-        RAbstractVector a = operand.copy();
+        RAbstractVector a = copy(operand);
         if (a instanceof RShareable) {
             ((RShareable) a).incRefCount();
         }
 
-        RVector<?> aMaterialized = a.copy().materialize();
+        RVector<?> aMaterialized = withinTestContext(() -> a.copy().materialize());
         aMaterialized.setAttr("a", "a");
-        assertAttributes(executeArithmetic(factory, aMaterialized.copy()), "a");
+        assertAttributes(executeArithmetic(factory, copy(aMaterialized)), "a");
     }
 
     @Theory
     public void testPlusFolding(RAbstractVector originalOperand) {
-        RAbstractVector operand = originalOperand.copy();
+        RAbstractVector operand = copy(originalOperand);
         assumeThat(operand, is(not(instanceOf(RScalarVector.class))));
         if (operand.getRType() == getArgumentType(operand)) {
             assertFold(true, operand, PLUS);
@@ -178,7 +180,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
     public void testGeneric(UnaryArithmeticFactory factory) {
         // this should trigger the generic case
         for (RAbstractVector vector : ALL_VECTORS) {
-            executeArithmetic(factory, vector.copy());
+            executeArithmetic(factory, copy(vector));
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index 04862083a6..93ef3ba544 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -23,9 +23,12 @@
 package com.oracle.truffle.r.runtime.context;
 
 import java.util.TimeZone;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -58,6 +61,7 @@ public final class ContextInfo {
     private final int id;
     private final int multiSlotInd;
     private PolyglotEngine vm;
+    public Executor executor;
 
     private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id, int multiSlotInd) {
         this.startParams = startParams;
@@ -83,7 +87,12 @@ public final class ContextInfo {
     }
 
     public PolyglotEngine createVM() {
-        PolyglotEngine newVM = PolyglotEngine.newBuilder().config("application/x-r", CONFIG_KEY, this).build();
+        Builder builder = PolyglotEngine.newBuilder();
+        if (startParams.getInteractive()) {
+            this.executor = Executors.newSingleThreadExecutor();
+            builder = builder.executor(executor);
+        }
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
         return newVM;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 7866245493..9b6d4cf9b5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -821,6 +821,17 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext {
         return info.getEnv();
     }
 
+    /**
+     * Allows another thread to schedule some code to be run in this context's thread. The action is
+     * ignored if the current context does not support such scheduling, i.e. the polyglot engine was
+     * not created with an executor.
+     */
+    public void schedule(Runnable action) {
+        if (info.executor != null) {
+            info.executor.execute(action);
+        }
+    }
+
     @Override
     public String toString() {
         return "context: " + info.getId();
-- 
GitLab


From 61599e180325f7e97b26662479135c7b815e4b14 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Thu, 11 May 2017 11:05:38 -0700
Subject: [PATCH 344/402] add missing @Override

---
 .../src/com/oracle/truffle/r/test/tck/FastRTckTest.java          | 1 +
 1 file changed, 1 insertion(+)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 967e2d5595..15ec247889 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -506,6 +506,7 @@ public class FastRTckTest extends TruffleTCK {
         return "valueWithSource";
     }
 
+    @Override
     protected String objectWithKeyInfoAttributes() {
         return "objectWithKeyInfoAttributes";
     }
-- 
GitLab


From 49bca764e8f408bd70026312281cf0a1b6184012 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 5 May 2017 15:05:10 +0200
Subject: [PATCH 345/402] Fix: Nested loop handling during debugging and single
 statements as loop bodies.

---
 .../r/engine/RRuntimeASTAccessImpl.java       |  5 +-
 .../nodes/builtin/helpers/DebugHandling.java  | 10 ++-
 .../truffle/r/nodes/control/ForNode.java      | 13 +++
 .../truffle/r/test/ExpectedTestOutput.test    | 82 +++++++++++++++++++
 .../library/utils/TestInteractiveDebug.java   | 11 ++-
 5 files changed, 116 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index a5d042faf3..378c3219ae 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -54,6 +54,7 @@ import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling;
 import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling;
 import com.oracle.truffle.r.nodes.control.AbstractLoopNode;
 import com.oracle.truffle.r.nodes.control.BlockNode;
+import com.oracle.truffle.r.nodes.control.ForNode;
 import com.oracle.truffle.r.nodes.control.IfNode;
 import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
@@ -532,7 +533,9 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
                     return true;
                 } else {
                     // single statement block, variable parent
-                    return parent instanceof FunctionDefinitionNode || parent instanceof IfNode || parent instanceof AbstractLoopNode;
+                    // note: RepeatingNode is not a RSyntaxElement but the body of a loop is
+                    // under the repeating node !
+                    return parent instanceof FunctionDefinitionNode || parent instanceof IfNode || parent instanceof AbstractLoopNode || ForNode.isLoopBody(node);
                 }
             }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index 80f96d66aa..e0f7a1713e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -186,6 +186,7 @@ public class DebugHandling {
 
             @Override
             protected Void visit(RSyntaxFunction element) {
+                accept(element.getSyntaxBody());
                 return null;
             }
         }.accept(fdn);
@@ -511,6 +512,9 @@ public class DebugHandling {
         }
     }
 
+    /**
+     * Handles the loop header and there is one instance registered for each loop.
+     */
     private static class LoopStatementEventListener extends StatementEventListener {
 
         private boolean finishing;
@@ -529,7 +533,7 @@ public class DebugHandling {
 
         @Override
         public void onEnter(EventContext context, VirtualFrame frame) {
-            if (!disabled()) {
+            if (!disabled() && context.getInstrumentedNode() == loopNode) {
                 super.onEnter(context, frame);
             }
         }
@@ -544,7 +548,7 @@ public class DebugHandling {
 
         @Override
         public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
-            if (!disabled()) {
+            if (!disabled() && context.getInstrumentedNode() == loopNode) {
                 CompilerDirectives.transferToInterpreter();
                 returnCleanup();
             }
@@ -552,7 +556,7 @@ public class DebugHandling {
 
         @Override
         public void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
-            if (!disabled()) {
+            if (!disabled() && context.getInstrumentedNode() == loopNode) {
                 CompilerDirectives.transferToInterpreter();
                 returnCleanup();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
index d50558d620..27575a9f17 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.control;
 
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode;
 import com.oracle.truffle.api.nodes.LoopNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RepeatingNode;
@@ -159,4 +160,16 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
     public ArgumentsSignature getSyntaxSignature() {
         return ArgumentsSignature.empty(3);
     }
+
+    /**
+     * Tests if the provided node is a loop-body node (also considering wrappers).
+     */
+    public static boolean isLoopBody(Node n) {
+        Node parent = n.getParent();
+        if (parent instanceof WrapperNode) {
+            Node grandparent = parent.getParent();
+            return grandparent instanceof ForRepeatingNode && ((ForRepeatingNode) grandparent).body == parent;
+        }
+        return parent instanceof ForRepeatingNode && ((ForRepeatingNode) parent).body == n;
+    }
 }
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 3ab87815de..5897e35a44 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
@@ -143320,6 +143320,88 @@ debug at #4: `123t`
 exiting from: f(5)
 [1] 6
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop#
+#fun <- function(x) { for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debugging in: fun(3)
+debug at #1: {
+    for (i in seq(x)) cat(i)
+    cat(5)
+}
+debug at #1: for (i in seq(x)) cat(i)
+debug at #1: cat(i)
+1debug at #1: cat(i)
+2debug at #1: cat(i)
+3debug at #1: cat(5)
+5exiting from: fun(3)
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop#
+#fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debugging in: fun(3)
+debug at #1: {
+    for (i in seq(x)) {
+        cat(i)
+    }
+    cat(5)
+}
+debug at #1: for (i in seq(x)) {
+    cat(i)
+}
+debug at #1: cat(i)
+1debug at #1: cat(i)
+2debug at #1: cat(i)
+3debug at #1: cat(5)
+5exiting from: fun(3)
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop#
+#fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>>
+debugging in: fun(3)
+debug at #1: {
+    for (i in seq(x)) {
+        cat(i)
+    }
+    cat(5)
+}
+debug at #1: for (i in seq(x)) {
+    cat(i)
+}
+debug at #1: cat(i)
+1debug at #1: cat(i)
+23debug at #1: cat(5)
+5exiting from: fun(3)
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop#
+#fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debugging in: fun(3)
+debug at #1: {
+    for (j in seq(2)) for (i in seq(x)) cat(i)
+    cat(5)
+}
+debug at #1: for (j in seq(2)) for (i in seq(x)) cat(i)
+debug at #1: for (i in seq(x)) cat(i)
+debug at #1: cat(i)
+1debug at #1: cat(i)
+2debug at #1: cat(i)
+3debug at #1: for (i in seq(x)) cat(i)
+debug at #1: cat(i)
+1debug at #1: cat(i)
+2debug at #1: cat(i)
+3debug at #1: cat(5)
+5exiting from: fun(3)
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testLoop#
+#fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>>
+debugging in: fun(3)
+debug at #1: {
+    for (j in seq(2)) for (i in seq(x)) cat(i)
+    cat(5)
+}
+debug at #1: for (j in seq(2)) for (i in seq(x)) cat(i)
+debug at #1: for (i in seq(x)) cat(i)
+debug at #1: cat(i)
+123debug at #1: for (i in seq(x)) cat(i)
+123debug at #1: cat(5)
+5exiting from: fun(3)
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNoBracket#
 #f <- function(x) print(x)<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>
 debugging in: f(5)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index 7d32146ecb..31e9eb103e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,4 +41,13 @@ public class TestInteractiveDebug extends TestBase {
     public void testNoBracket() {
         assertEval("f <- function(x) print(x)\ndebug(f)\nf(5)\nx\nn\n");
     }
+
+    @Test
+    public void testLoop() {
+        assertEval("fun <- function(x) { for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n");
+        assertEval("fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n");
+        assertEval("fun <- function(x) { for(i in seq(x)) { cat(i) }; cat(5) }; debug(fun); fun(3)\n\n\n\nf\n\n");
+        assertEval("fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n\n\n\n\n\n");
+        assertEval("fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\nf\nf\n\n");
+    }
 }
-- 
GitLab


From 500e97a898c4affc067ed21c9dff05e2f2118e25 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 8 May 2017 17:06:12 +0200
Subject: [PATCH 346/402] Fixed step-into operation which automatically stepped
 into every call even if 'n' has been entered. Fixed some debugging output
 issues to enable unit testing.

---
 .../nodes/builtin/helpers/DebugHandling.java  |  9 +--
 .../com/oracle/truffle/r/runtime/RSource.java |  7 ++
 .../truffle/r/test/ExpectedTestOutput.test    | 68 +++++++++++++++++++
 .../truffle/r/test/generate/FastRSession.java |  6 +-
 .../library/utils/TestInteractiveDebug.java   |  7 ++
 5 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index e0f7a1713e..37dee9c75f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -197,7 +197,7 @@ public class DebugHandling {
         FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn);
         if (fser == null) {
             // attach a "once" listener
-            fser = attachDebugHandler(fdn, null, null, true, false);
+            fser = attachDebugHandler(fdn, null, null, true, true);
         } else {
             if (fser.disabled()) {
                 fser.enable();
@@ -294,8 +294,9 @@ public class DebugHandling {
 
         @TruffleBoundary
         private void attachStepInto() {
-            stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(),
-                            new StepIntoInstrumentListener(getFunctionStatementsEventListener(functionDefinitionNode)));
+            FunctionStatementsEventListener parentListener = getFunctionStatementsEventListener(functionDefinitionNode);
+            parentListener.stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(),
+                            new StepIntoInstrumentListener(parentListener));
 
         }
 
@@ -503,7 +504,7 @@ public class DebugHandling {
                     return;
                 }
                 printNode(node, false);
-                browserInteract(context.getInstrumentedNode(), frame);
+                browserInteract(node, frame);
             }
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
index 41ea6dacda..e1ef2d2fc9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
@@ -172,6 +172,13 @@ public class RSource {
         return Source.newBuilder(file).name(file.getName()).mimeType(RRuntime.R_APP_MIME).build();
     }
 
+    /**
+     * Create a source from the file system path denoted by {@code file}.
+     */
+    public static Source fromTempFile(File file) throws IOException {
+        return Source.newBuilder(file).name(file.getName()).mimeType(RRuntime.R_APP_MIME).internal().build();
+    }
+
     /**
      * Create an (external) source from {@code url}.
      */
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 5897e35a44..f14bbe9325 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
@@ -143427,6 +143427,74 @@ debug at #4: t
 exiting from: f(5)
 [1] 6
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
+#bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debugging in: foo(3)
+debug at #1: {
+    cat("foo entry\n")
+    bar(x)
+    cat("foo exit\n")
+}
+debug at #1: cat("foo entry\n")
+foo entry
+debug at #1: bar(x)
+debugging in: bar(x)
+debug at #1: {
+    cat(x)
+    cat("\n")
+}
+debug at #1: cat(x)
+3debug at #1: cat("\n")
+
+debug at #1: cat("foo exit\n")
+foo exit
+exiting from: foo(3)
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
+#bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>>Q<<<NEWLINE>>>
+debugging in: foo(3)
+debug at #1: {
+    cat("foo entry\n")
+    bar(x)
+    cat("foo exit\n")
+}
+debug at #1: cat("foo entry\n")
+foo entry
+debug at #1: bar(x)
+debugging in: bar(x)
+debug at #1: {
+    cat(x)
+    cat("\n")
+}
+debug at #1: cat(x)
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
+#bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(5)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>>
+debugging in: foo(5)
+debug at #1: {
+    cat("foo entry\n")
+    bar(x)
+    cat("foo exit\n")
+}
+debug at #1: cat("foo entry\n")
+foo entry
+debug at #1: bar(x)
+debugging in: bar(x)
+debug at #1: {
+    for (i in seq(x)) print(x)
+}
+debug at #1: for (i in seq(x)) print(x)
+debug at #1: print(x)
+[1] 5
+debug at #1: print(x)
+[1] 5
+[1] 5
+[1] 5
+[1] 5
+debug at #1: cat("foo exit\n")
+foo exit
+exiting from: foo(5)
+
 ##com.oracle.truffle.r.test.library.utils.TestTrace.testCondTrace#
 #f <- function(x) {}; (if (exists('.fastr.trace')) .fastr.trace else trace)(f, tracer=quote(if (x == 3 || x == 7) print(x))); g <- function() for (i in 1:10) f(i); g()
 [1] "f"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
index eec8974833..0b51a3d92d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.api.debug.SuspendedEvent;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ExitException;
+import com.oracle.truffle.r.runtime.JumpToTopLevelException;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RError;
@@ -224,8 +225,9 @@ public final class FastRSession implements RSession {
             }
         } catch (ParseException e) {
             e.report(consoleHandler);
-        } catch (ExitException e) {
-            // exit exceptions are legitimate if a test case calls "q()"
+        } catch (ExitException | JumpToTopLevelException e) {
+            // exit and jumpToTopLevel exceptions are legitimate if a test case calls "q()" or "Q"
+            // during debugging
         } catch (RError e) {
             // nothing to do
         } catch (Throwable t) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index 31e9eb103e..4cdca78ab9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -50,4 +50,11 @@ public class TestInteractiveDebug extends TestBase {
         assertEval("fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\n\n\n\n\n\n\n\n\n");
         assertEval("fun <- function(x) { for(j in seq(2)) for(i in seq(x)) cat(i); cat(5) }; debug(fun); fun(3)\n\n\n\nf\nf\n\n");
     }
+
+    @Test
+    public void testStepInto() {
+        assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\n\n\n\n");
+        assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\nQ\n");
+        assertEval("bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n");
+    }
 }
-- 
GitLab


From 9d0903b8cfdac182f34c64f9ad10dc854c492496 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 8 May 2017 17:47:54 +0200
Subject: [PATCH 347/402] Fix: Console output when exiting debugger.

---
 .../truffle/r/nodes/builtin/helpers/DebugHandling.java   | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index 37dee9c75f..bc3d382113 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -45,6 +45,7 @@ import com.oracle.truffle.r.nodes.control.AbstractLoopNode;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.nodes.instrumentation.RInstrumentation;
 import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags;
+import com.oracle.truffle.r.runtime.JumpToTopLevelException;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
@@ -428,7 +429,7 @@ public class DebugHandling {
         public void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
             if (!disabled()) {
                 CompilerDirectives.transferToInterpreter();
-                returnCleanup(frame);
+                returnCleanup(frame, false);
             }
         }
 
@@ -436,12 +437,12 @@ public class DebugHandling {
         public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
             if (!disabled()) {
                 CompilerDirectives.transferToInterpreter();
-                returnCleanup(frame);
+                returnCleanup(frame, exception instanceof JumpToTopLevelException);
             }
         }
 
-        private void returnCleanup(VirtualFrame frame) {
-            if (!implicit) {
+        private void returnCleanup(VirtualFrame frame, boolean jumpToTopLevel) {
+            if (!implicit && !jumpToTopLevel) {
                 print("exiting from: ", false);
                 printCall(frame);
             }
-- 
GitLab


From 1b3c812ea63090a778cc8c63e08cf85882e544b6 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 10 May 2017 08:49:55 +0200
Subject: [PATCH 348/402] Reverted implicit flag change.

---
 .../oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index bc3d382113..c8ed4121ea 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -198,7 +198,7 @@ public class DebugHandling {
         FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn);
         if (fser == null) {
             // attach a "once" listener
-            fser = attachDebugHandler(fdn, null, null, true, true);
+            fser = attachDebugHandler(fdn, null, null, true, false);
         } else {
             if (fser.disabled()) {
                 fser.enable();
-- 
GitLab


From 9ed877f4c8137be8b4b6809669fa41c7cf42e57a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 10 May 2017 16:15:50 +0200
Subject: [PATCH 349/402] Added test traits to ignore some unimportant
 differences in the debugger's output.

---
 .../com/oracle/truffle/r/test/TestBase.java   | 41 ++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index b0ed490c98..680a9ed672 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -77,7 +77,10 @@ public class TestBase {
         MayIgnoreWarningContext,
         ContainsReferences, // replaces references in form of 0xbcdef1 for numbers
         IgnoreWhitespace, // removes all whitespace from the whole output
-        IgnoreCase; // ignores upper/lower case differences
+        IgnoreCase, // ignores upper/lower case differences
+        IgnoreDebugPath, // ignores <path> in debug output like "debug at <path> #..."
+        IgnoreDebugDepth, // ignores call depth printed by the debugger ("Browse[<call depth>]")
+        IgnoreDebugExitFrom; // ignores the debugger's "exiting from ..."
 
         @Override
         public String getName() {
@@ -608,6 +611,15 @@ public class TestBase {
             if (output.contains(Output.ContainsReferences)) {
                 return convertReferencesInOutput(out);
             }
+            if (output.contains(Output.IgnoreDebugPath)) {
+                return convertDebugOutput(out);
+            }
+            if (output.contains(Output.IgnoreDebugExitFrom)) {
+                return removeExitingFrom(out);
+            }
+            if (output.contains(Output.IgnoreDebugDepth)) {
+                return removeDebugCallDepth(out);
+            }
             return out;
         }
     }
@@ -731,6 +743,33 @@ public class TestBase {
         return result;
     }
 
+    private static String convertDebugOutput(String out) {
+        String prefix = "debug at ";
+        return removeAllOccurrencesBetween(out, prefix, prefix.length(), "#", 0);
+    }
+
+    private static String removeExitingFrom(String out) {
+        return removeAllOccurrencesBetween(out, "exiting from:", 0, "\n", 1);
+    }
+
+    private static String removeDebugCallDepth(String out) {
+        String prefix = "Browse[";
+        return removeAllOccurrencesBetween(out, prefix, prefix.length(), "]", 0);
+    }
+
+    private static String removeAllOccurrencesBetween(String out, String prefix, int prefixOffset, String suffix, int suffixOffset) {
+        StringBuilder sb = new StringBuilder(out);
+
+        int idxPrefix = -1;
+        int idxSuffix = -1;
+
+        while ((idxPrefix = sb.indexOf(prefix, idxPrefix + 1)) > 0 && (idxSuffix = sb.indexOf(suffix, idxPrefix)) > idxPrefix) {
+            sb.replace(idxPrefix + prefixOffset, idxSuffix + suffixOffset, "");
+        }
+
+        return sb.toString();
+    }
+
     private boolean searchWhiteLists(WhiteList[] whiteLists, String input, String expected, String result, TestTraitsSet testTraits) {
         if (whiteLists == null) {
             return false;
-- 
GitLab


From cb853fd71a7f221e6dc1f5e33859660b9d4bbc69 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 10 May 2017 16:17:24 +0200
Subject: [PATCH 350/402] Added unit tests for interactive debugger concerning
 nested debugging and conditional breakpoints.

---
 .../truffle/r/test/ExpectedTestOutput.test    | 46 ++++++++++++++++++-
 .../library/utils/TestInteractiveDebug.java   | 20 +++++++-
 2 files changed, 62 insertions(+), 4 deletions(-)

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 f14bbe9325..b14bd57480 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
@@ -75880,6 +75880,9 @@ IgnoreWarningContext extra newline
 ##com.oracle.truffle.r.test.builtins.TestTestBase.testTraits#Output.IgnoreWarningContext#
 #if (exists('.fastr.identity')) { cat('Warning message: In .Internal(foo(42)) : IgnoreWarningContext') } else { cat('Warning message: In foo(42) : IgnoreWarningContext') }
 Warning message: In foo(42) : IgnoreWarningContext
+##com.oracle.truffle.r.test.builtins.TestTestBase.testTraits#Output.IgnoreDebugPath#
+#if (exists('.fastr.identity')) { cat('debug at <parse>#10') } else { cat('debug at <text>#10') }
+debug at <text>#10
 ##com.oracle.truffle.r.test.functions.TestFunctions.testArgEvaluationOrder#
 #v <- 1; class(v) <- 'foo'; `-.foo` <- function(x,y,...) { cat('[-.foo]'); 1234 }; g <- function(...) { cat('[ing]'); ({cat('[-]'); `-`})(...) }; ({cat('[g]'); g})({cat('[x]'); v},{cat('[y]'); 3},{cat('[z]'); 5})
 [g][ing][-][x][y][z][-.foo][1] 1234
@@ -143303,6 +143306,13 @@ x + x ~ y + log(y)
 #update.formula(x ~ y, ~ . + x2)
 x ~ y + x2
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testConditionalBreakpoint#
+#fun <- function(x) { cat('x='); cat(x); cat('\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)<<<NEWLINE>>>; fun(11)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+[1] "fun"
+Tracing fun(10) on entry
+x=10
+Error: unexpected ';' in ";"
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testInvalidName#
 #f <- function(x) {<<<NEWLINE>>>  `123t` <- x + 1<<<NEWLINE>>>  print(`123t`)<<<NEWLINE>>>  `123t`}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>`123t`<<<NEWLINE>>>n<<<NEWLINE>>>n
 debugging in: f(5)
@@ -143402,6 +143412,38 @@ debug at #1: cat(i)
 123debug at #1: cat(5)
 5exiting from: fun(3)
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNestedDebugging#Output.IgnoreDebugPath#
+#foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo("bar <- function() { print('bar') }; debug(bar); bar()")<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debugging in: foo("bar <- function() { print('bar') }; debug(bar); bar()")
+debug at #1: {
+    eval(parse(text = rCode))
+    print("foo done")
+}
+debug at #1: eval(parse(text = rCode))
+debugging in: bar()
+debug at <text>#1: {
+    print("bar")
+}
+debug at <text>#1: print("bar")
+[1] "bar"
+exiting from: bar()
+debug at #1: print("foo done")
+[1] "foo done"
+exiting from: foo("bar <- function() { print('bar') }; debug(bar); bar()")
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNestedDebugging#Output.IgnoreDebugPath#
+#foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo("bar <- function() { print('bar') }; debug(bar); bar()")<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>Q<<<NEWLINE>>>
+debugging in: foo("bar <- function() { print('bar') }; debug(bar); bar()")
+debug at #1: {
+    eval(parse(text = rCode))
+    print("foo done")
+}
+debug at #1: eval(parse(text = rCode))
+debugging in: bar()
+debug at <text>#1: {
+    print("bar")
+}
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testNoBracket#
 #f <- function(x) print(x)<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>
 debugging in: f(5)
@@ -143427,7 +143469,7 @@ debug at #4: t
 exiting from: f(5)
 [1] 6
 
-##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#Output.IgnoreDebugExitFrom#
 #bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
 debugging in: foo(3)
 debug at #1: {
@@ -143468,7 +143510,7 @@ debug at #1: {
 }
 debug at #1: cat(x)
 
-##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#Output.IgnoreDebugExitFrom#
 #bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(5)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>>
 debugging in: foo(5)
 debug at #1: {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index 4cdca78ab9..6fdc4d3262 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -26,6 +26,7 @@ import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
 
+// Checkstyle: stop line length check
 public class TestInteractiveDebug extends TestBase {
     @Test
     public void testSimple() {
@@ -53,8 +54,23 @@ public class TestInteractiveDebug extends TestBase {
 
     @Test
     public void testStepInto() {
-        assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\n\n\n\n");
+        assertEval(Output.IgnoreDebugExitFrom,
+                        "bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\n\n\n\n");
         assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\nQ\n");
-        assertEval("bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n");
+        assertEval(Output.IgnoreDebugExitFrom,
+                        "bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n");
+    }
+
+    @Test
+    public void testNestedDebugging() {
+        assertEval(Output.IgnoreDebugPath,
+                        "foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo(\"bar <- function() { print('bar') }; debug(bar); bar()\")\n\n\n\n\n\n");
+        assertEval(Output.IgnoreDebugPath,
+                        "foo <- function(rCode) { eval(parse(text=rCode)); print('foo done') }; debug(foo); foo(\"bar <- function() { print('bar') }; debug(bar); bar()\")\n\n\nQ\n");
+    }
+
+    @Test
+    public void testConditionalBreakpoint() {
+        assertEval("fun <- function(x) { cat('x='); cat(x); cat('\\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)\n; fun(11)\n\n\n\n\n\n");
     }
 }
-- 
GitLab


From 81ad4fe35a27d62599129d21ae5871fcd5728cb0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 11 May 2017 17:23:56 +0200
Subject: [PATCH 351/402] Fix: Debug continue did not work properly.

---
 .../nodes/builtin/helpers/DebugHandling.java  |  8 +++--
 .../truffle/r/test/ExpectedTestOutput.test    | 34 +++++++++++++++++--
 .../library/utils/TestInteractiveDebug.java   |  6 ++++
 3 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index c8ed4121ea..472c2d72c8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -194,7 +194,7 @@ public class DebugHandling {
         return fser;
     }
 
-    private static void ensureSingleStep(FunctionDefinitionNode fdn) {
+    private static FunctionStatementsEventListener ensureSingleStep(FunctionDefinitionNode fdn) {
         FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn);
         if (fser == null) {
             // attach a "once" listener
@@ -206,6 +206,7 @@ public class DebugHandling {
                 fser.enabledForStepInto = true;
             }
         }
+        return fser;
     }
 
     private abstract static class DebugEventListener implements ExecutionEventListener {
@@ -598,9 +599,10 @@ public class DebugHandling {
             if (!RContext.getInstance().stateInstrumentation.debugGloballyDisabled()) {
                 CompilerDirectives.transferToInterpreter();
                 FunctionDefinitionNode fdn = (FunctionDefinitionNode) context.getInstrumentedNode().getRootNode();
-                ensureSingleStep(fdn);
+                FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn);
+
                 functionStatementsEventListener.clearStepInstrument();
-                functionStatementsEventListener.onEnter(context, frame);
+                ensureSingleStep.onEnter(context, frame);
             }
         }
 
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 b14bd57480..092e0341e9 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
@@ -75880,9 +75880,6 @@ IgnoreWarningContext extra newline
 ##com.oracle.truffle.r.test.builtins.TestTestBase.testTraits#Output.IgnoreWarningContext#
 #if (exists('.fastr.identity')) { cat('Warning message: In .Internal(foo(42)) : IgnoreWarningContext') } else { cat('Warning message: In foo(42) : IgnoreWarningContext') }
 Warning message: In foo(42) : IgnoreWarningContext
-##com.oracle.truffle.r.test.builtins.TestTestBase.testTraits#Output.IgnoreDebugPath#
-#if (exists('.fastr.identity')) { cat('debug at <parse>#10') } else { cat('debug at <text>#10') }
-debug at <text>#10
 ##com.oracle.truffle.r.test.functions.TestFunctions.testArgEvaluationOrder#
 #v <- 1; class(v) <- 'foo'; `-.foo` <- function(x,y,...) { cat('[-.foo]'); 1234 }; g <- function(...) { cat('[ing]'); ({cat('[-]'); `-`})(...) }; ({cat('[g]'); g})({cat('[x]'); v},{cat('[y]'); 3},{cat('[z]'); 5})
 [g][ing][-][x][y][z][-.foo][1] 1234
@@ -143313,6 +143310,37 @@ Tracing fun(10) on entry
 x=10
 Error: unexpected ';' in ";"
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testContinue#Output.IgnoreDebugExitFrom#
+#fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>c<<<NEWLINE>>>c<<<NEWLINE>>>c<<<NEWLINE>>>
+debugging in: fun2()
+debug at #1: {
+    print("enter fun2")
+    fun1()
+    print("exit fun2")
+}
+debug at #1: print("enter fun2")
+[1] "enter fun2"
+debug at #1: fun1()
+debugging in: fun1()
+debug at #1: {
+    print("enter fun1")
+    fun0()
+    print("exit fun1")
+}
+debug at #1: print("enter fun1")
+[1] "enter fun1"
+debug at #1: fun0()
+debugging in: fun0()
+debug at #1: {
+    print("fun0")
+}
+[1] "fun0"
+debug at #1: print("exit fun1")
+[1] "exit fun1"
+debug at #1: print("exit fun2")
+[1] "exit fun2"
+exiting from: fun2()
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testInvalidName#
 #f <- function(x) {<<<NEWLINE>>>  `123t` <- x + 1<<<NEWLINE>>>  print(`123t`)<<<NEWLINE>>>  `123t`}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>`123t`<<<NEWLINE>>>n<<<NEWLINE>>>n
 debugging in: f(5)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index 6fdc4d3262..e61e4c0392 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -73,4 +73,10 @@ public class TestInteractiveDebug extends TestBase {
     public void testConditionalBreakpoint() {
         assertEval("fun <- function(x) { cat('x='); cat(x); cat('\\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)\n; fun(11)\n\n\n\n\n\n");
     }
+
+    @Test
+    public void testContinue() {
+        assertEval(Output.IgnoreDebugExitFrom,
+                        "fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()\n\n\ns\nn\n\ns\nc\nc\nc\n");
+    }
 }
-- 
GitLab


From 5af8f950e481500867c285e6f4236d153fb2f55c Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 11 May 2017 17:48:45 +0200
Subject: [PATCH 352/402] Refined 'debugonce': Does not print exiting from
 function message.

---
 .../nodes/builtin/helpers/DebugHandling.java  |  4 +--
 .../truffle/r/test/ExpectedTestOutput.test    | 25 ++++++++++++++++---
 .../library/utils/TestInteractiveDebug.java   | 15 ++++++-----
 3 files changed, 33 insertions(+), 11 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index 472c2d72c8..75684febae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -198,7 +198,7 @@ public class DebugHandling {
         FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn);
         if (fser == null) {
             // attach a "once" listener
-            fser = attachDebugHandler(fdn, null, null, true, false);
+            fser = attachDebugHandler(fdn, null, null, true, true);
         } else {
             if (fser.disabled()) {
                 fser.enable();
@@ -443,7 +443,7 @@ public class DebugHandling {
         }
 
         private void returnCleanup(VirtualFrame frame, boolean jumpToTopLevel) {
-            if (!implicit && !jumpToTopLevel) {
+            if (!implicit && !once && !jumpToTopLevel) {
                 print("exiting from: ", false);
                 printCall(frame);
             }
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 092e0341e9..9d4f0c63c3 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
@@ -143310,7 +143310,7 @@ Tracing fun(10) on entry
 x=10
 Error: unexpected ';' in ";"
 
-##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testContinue#Output.IgnoreDebugExitFrom#
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testContinue#
 #fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>c<<<NEWLINE>>>c<<<NEWLINE>>>c<<<NEWLINE>>>
 debugging in: fun2()
 debug at #1: {
@@ -143341,6 +143341,25 @@ debug at #1: print("exit fun2")
 [1] "exit fun2"
 exiting from: fun2()
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testDebugOnce#
+#fun0 <- function() { print('fun0') }; debugonce(fun0); fun0()<<<NEWLINE>>>c<<<NEWLINE>>>
+debugging in: fun0()
+debug at #1: {
+    print("fun0")
+}
+[1] "fun0"
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testDebugOnce#
+#fun0 <- function() { print('fun0') }; fun1 <- function() { print('en'); fun0(); fun0(); print('ex') }; debugonce(fun0); fun1()<<<NEWLINE>>>c<<<NEWLINE>>>
+[1] "en"
+debugging in: fun0()
+debug at #1: {
+    print("fun0")
+}
+[1] "fun0"
+[1] "fun0"
+[1] "ex"
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testInvalidName#
 #f <- function(x) {<<<NEWLINE>>>  `123t` <- x + 1<<<NEWLINE>>>  print(`123t`)<<<NEWLINE>>>  `123t`}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>`123t`<<<NEWLINE>>>n<<<NEWLINE>>>n
 debugging in: f(5)
@@ -143497,7 +143516,7 @@ debug at #4: t
 exiting from: f(5)
 [1] 6
 
-##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#Output.IgnoreDebugExitFrom#
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
 #bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
 debugging in: foo(3)
 debug at #1: {
@@ -143538,7 +143557,7 @@ debug at #1: {
 }
 debug at #1: cat(x)
 
-##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#Output.IgnoreDebugExitFrom#
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
 #bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(5)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>f<<<NEWLINE>>><<<NEWLINE>>>
 debugging in: foo(5)
 debug at #1: {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index e61e4c0392..e74647fcf2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -54,11 +54,9 @@ public class TestInteractiveDebug extends TestBase {
 
     @Test
     public void testStepInto() {
-        assertEval(Output.IgnoreDebugExitFrom,
-                        "bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\n\n\n\n");
+        assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\n\n\n\n");
         assertEval("bar <- function(x) { cat(x); cat('\\n') }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(3)\n\n\ns\nn\nQ\n");
-        assertEval(Output.IgnoreDebugExitFrom,
-                        "bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n");
+        assertEval("bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n");
     }
 
     @Test
@@ -76,7 +74,12 @@ public class TestInteractiveDebug extends TestBase {
 
     @Test
     public void testContinue() {
-        assertEval(Output.IgnoreDebugExitFrom,
-                        "fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()\n\n\ns\nn\n\ns\nc\nc\nc\n");
+        assertEval("fun0 <- function() { print('fun0') }; fun1 <- function() { print('enter fun1'); fun0(); print('exit fun1') }; fun2 <- function() { print('enter fun2'); fun1(); print('exit fun2') }; debug(fun2); fun2()\n\n\ns\nn\n\ns\nc\nc\nc\n");
+    }
+
+    @Test
+    public void testDebugOnce() {
+        assertEval("fun0 <- function() { print('fun0') }; fun1 <- function() { print('en'); fun0(); fun0(); print('ex') }; debugonce(fun0); fun1()\nc\n");
+        assertEval("fun0 <- function() { print('fun0') }; debugonce(fun0); fun0()\nc\n");
     }
 }
-- 
GitLab


From 4df6249054aa2f39ee25be8c666e6000cf3cd8e0 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 12 May 2017 13:59:22 +0200
Subject: [PATCH 353/402] Cleanup: Removed unnecessary trait.

---
 .../src/com/oracle/truffle/r/test/TestBase.java        | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 680a9ed672..21d6e39b32 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -79,8 +79,7 @@ public class TestBase {
         IgnoreWhitespace, // removes all whitespace from the whole output
         IgnoreCase, // ignores upper/lower case differences
         IgnoreDebugPath, // ignores <path> in debug output like "debug at <path> #..."
-        IgnoreDebugDepth, // ignores call depth printed by the debugger ("Browse[<call depth>]")
-        IgnoreDebugExitFrom; // ignores the debugger's "exiting from ..."
+        IgnoreDebugDepth; // ignores call depth printed by the debugger ("Browse[<call depth>]")
 
         @Override
         public String getName() {
@@ -614,9 +613,6 @@ public class TestBase {
             if (output.contains(Output.IgnoreDebugPath)) {
                 return convertDebugOutput(out);
             }
-            if (output.contains(Output.IgnoreDebugExitFrom)) {
-                return removeExitingFrom(out);
-            }
             if (output.contains(Output.IgnoreDebugDepth)) {
                 return removeDebugCallDepth(out);
             }
@@ -748,10 +744,6 @@ public class TestBase {
         return removeAllOccurrencesBetween(out, prefix, prefix.length(), "#", 0);
     }
 
-    private static String removeExitingFrom(String out) {
-        return removeAllOccurrencesBetween(out, "exiting from:", 0, "\n", 1);
-    }
-
     private static String removeDebugCallDepth(String out) {
         String prefix = "Browse[";
         return removeAllOccurrencesBetween(out, prefix, prefix.length(), "]", 0);
-- 
GitLab


From f01806434a2a6ae870048b02b383c78b0de2b902 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Thu, 11 May 2017 21:02:24 +0200
Subject: [PATCH 354/402] Changes to run FastR on JDK9.

---
 .../r/runtime/conn/DelegateRConnection.java   | 34 ++-----------------
 mx.fastr/suite.py                             |  8 -----
 2 files changed, 3 insertions(+), 39 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 437743ed51..d43eeb8e78 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -45,9 +45,6 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.sun.istack.internal.NotNull;
-
-import sun.nio.cs.StreamDecoder;
 
 /**
  * Actually performs the I/O operations for a connections.<br>
@@ -260,7 +257,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
      * @throws IOException
      */
     @TruffleBoundary
-    public static void writeCharHelper(@NotNull WritableByteChannel channel, @NotNull String s, int pad, String eos) throws IOException {
+    public static void writeCharHelper(WritableByteChannel channel, String s, int pad, String eos) throws IOException {
 
         final byte[] bytes = s.getBytes();
         final byte[] eosBytes = eos != null ? eos.getBytes() : null;
@@ -332,31 +329,6 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
         return new String(buf.array(), 0, j);
     }
 
-    /**
-     * Reads a specified number of characters (not bytes).<br>
-     * <p>
-     * This method is meant to be used if R's function {@code readChar} is called with parameter
-     * {@code useBytes=FALSE}.
-     * </p>
-     *
-     * @param nchars The number of characters to read.
-     * @param decoder The stream decoder to use (must not be {@code null}).
-     * @throws IOException
-     */
-    public static String readCharHelper(int nchars, StreamDecoder decoder) throws IOException {
-        // we need a decoder
-        char[] chars = new char[nchars];
-        decoder.read(chars);
-        int j = 0;
-        for (; j < chars.length; j++) {
-            // strings end at 0
-            if (chars[j] == 0) {
-                break;
-            }
-        }
-        return new String(chars, 0, j);
-    }
-
     /**
      * Implements standard seeking behavior.<br>
      * <p>
@@ -429,9 +401,9 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     /**
      * Creates the stream decoder on demand and returns it.
      */
-    protected StreamDecoder getDecoder(int bufSize) {
+    protected Reader getDecoder(int bufSize) {
         CharsetDecoder charsetEncoder = base.getEncoding().newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
-        return StreamDecoder.forDecoder(this, charsetEncoder, bufSize);
+        return Channels.newReader(this, charsetEncoder, bufSize);
     }
 
     @Override
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 3b6c062c36..75a963bb2e 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -80,11 +80,6 @@ suite = {
       "sha1" : "0baa82bff19059401e90e1b90020beb9c96305d7",
     },
 
-    "JDK_TOOLS" : {
-      "path" : "${JAVA_HOME}/lib/tools.jar",
-      "sha1" : "NOCHECK",
-    },
-
     "ANTLR-C-3.5" : {
       "path" : "libdownloads/antlr-complete-3.5.1.jar",
       "urls" : ["http://central.maven.org/maven2/org/antlr/antlr-complete/3.5.1/antlr-complete-3.5.1.jar"],
@@ -103,7 +98,6 @@ suite = {
     "com.oracle.truffle.r.parser.processor" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "JDK_TOOLS",
         "ANTLR-3.5",
         "ANTLR-C-3.5",
       ],
@@ -295,7 +289,6 @@ suite = {
       "subDir" : "truffle",
       "dependencies" : ["com.oracle.truffle.r.parser.processor"],
       "exclude" : [
-        "JDK_TOOLS",
         "ANTLR-3.5",
         "ANTLR-C-3.5",
        ],
@@ -308,7 +301,6 @@ suite = {
       "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.runtime.ffi"],
       "mainClass" : "com.oracle.truffle.r.engine.shell.RCommand",
       "exclude" : [
-        "JDK_TOOLS",
         "truffle:JLINE",
         "ANTLR-C-3.5",
         "ANTLR-3.5",
-- 
GitLab


From fc01a97b6c82637f11b5919476c9bccda79f2514 Mon Sep 17 00:00:00 2001
From: Miloslav Metelka <miloslav.metelka@oracle.com>
Date: Mon, 15 May 2017 16:55:21 +0200
Subject: [PATCH 355/402] Added test of rawConnection.

---
 .../src/com/oracle/truffle/r/test/ExpectedTestOutput.test     | 4 ++++
 .../oracle/truffle/r/test/library/base/TestConnections.java   | 1 +
 2 files changed, 5 insertions(+)

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 9d4f0c63c3..db2d6cfa5b 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
@@ -77781,6 +77781,10 @@ In fifo(fn, "r", blocking = TRUE) : cannot open fifo '___fifo_2367253765'
 #{ zz <- file("gzipped_____5137528280012599068___.gz", "r", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }
 Error in readBin(zz, raw(), 4) : can only read from a binary connection
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testFileOpenRaw#
+#{ zz <- rawConnection(as.raw(c(65, 66, 67, 0, 97, 98, 99))); readChar(zz, 6) }
+[1] "ABC"
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testFileSummary#
 #zz <- file('', 'w+'); summary(zz); close(zz)
 $description
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 7b8806d22c..2272c54b4b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -185,6 +185,7 @@ public class TestConnections extends TestRBase {
     public void testFileOpenRaw() {
         Assert.assertTrue("Could not create required temp file for test.", Files.exists(tempFileGzip));
         assertEval("{ zz <- file(\"" + tempFileGzip + "\", \"r\", raw=T); res <- readBin(zz, raw(), 4); close(zz); res }");
+        assertEval("{ zz <- rawConnection(as.raw(c(65, 66, 67, 0, 97, 98, 99))); readChar(zz, 6) }");
     }
 
     @Test
-- 
GitLab


From e818ca3de594d15dabad80e48ca06f90a41105a1 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 3 May 2017 16:06:33 +0200
Subject: [PATCH 356/402] Deparsed source code is now written to temporary
 files to ease debugging.

---
 .../truffle/r/runtime/FastROptions.java       |  2 ++
 .../oracle/truffle/r/runtime/RDeparse.java    | 29 +++++++++++++++++--
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 8c99eacf36..9258059341 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -57,6 +57,8 @@ public enum FastROptions {
     SharedContexts("Whether all child contexts are to be shared contexts", true),
     SearchPathForcePromises("Whether all promises for frames on shared path are forced in presence of shared contexts", false),
     LoadPackagesNativeCode("Load native code of packages, including builtin packages.", !FastRConfig.ManagedMode),
+    EmitTmpSource("Write deparsed source code to temporary files for better debugging.", true),
+    EmitTmpDir("The directory where to allocate temporary files with deparsed source code.", null, true),
 
     // Promises optimizations
     EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 03cdad3ac2..eb5e9f3c07 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -11,6 +11,12 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -317,9 +323,26 @@ public class RDeparse {
         }
 
         public void fixupSources() {
-            Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE);
-            for (SourceSectionElement s : sources) {
-                s.element.setSourceSection(source.createSection(s.start, s.length));
+            if (FastROptions.EmitTmpSource.getBooleanValue()) {
+                String tmpDirStr = FastROptions.EmitTmpDir.getStringValue();
+                Path tmpDir = tmpDirStr != null ? Paths.get(tmpDirStr) : null;
+                for (SourceSectionElement s : sources) {
+                    try {
+                        Path path = Files.createTempFile(tmpDir, "deparse-", ".r");
+                        try (BufferedWriter bw = Files.newBufferedWriter(path, StandardOpenOption.WRITE)) {
+                            bw.write(sb.toString());
+                        }
+                        Source source = RSource.fromFile(path.toFile());
+                        s.element.setSourceSection(source.createSection(s.start, s.length));
+                    } catch (IOException e) {
+                        RInternalError.reportError(e);
+                    }
+                }
+            } else {
+                Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE);
+                for (SourceSectionElement s : sources) {
+                    s.element.setSourceSection(source.createSection(s.start, s.length));
+                }
             }
         }
 
-- 
GitLab


From 11b325b76db7e4f56606ffe57601ddf51dc50ca7 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 4 May 2017 11:52:52 +0200
Subject: [PATCH 357/402] Implemented basic message resolution for some classes
 needed for debugging.

---
 .../engine/interop/RArgsValuesAndNamesMR.java | 63 +++++++++++++++++
 .../interop/RForeignAccessFactoryImpl.java    |  6 ++
 .../truffle/r/engine/interop/RPromiseMR.java  | 70 +++++++++++++++++++
 3 files changed, 139 insertions(+)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
new file mode 100644
index 0000000000..5eafbc04ce
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+
+@MessageResolution(receiverType = RArgsValuesAndNames.class, language = TruffleRLanguage.class)
+public class RArgsValuesAndNamesMR {
+    @Resolve(message = "IS_BOXED")
+    public abstract static class RArgsValuesAndNamesIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class RArgsValuesAndNamesHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class RArgsValuesAndNamesIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) {
+            return false;
+        }
+    }
+
+    @CanResolve
+    public abstract static class RArgsValuesAndNamesCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RArgsValuesAndNames;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 887d3a7741..0c7f6bcb20 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RForeignAccessFactory;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -41,6 +42,7 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RS4Object;
+import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
@@ -110,6 +112,10 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return CaptureNamesImplMRForeign.ACCESS;
         } else if (obj instanceof RS4Object) {
             return RS4ObjectMRForeign.ACCESS;
+        } else if (obj instanceof RPromise) {
+            return RPromiseMRForeign.ACCESS;
+        } else if (obj instanceof RArgsValuesAndNames) {
+            return RArgsValuesAndNamesMRForeign.ACCESS;
         } else {
             if (obj instanceof RAbstractVector) {
                 return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
new file mode 100644
index 0000000000..257848ba02
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.data.RPromise;
+
+@MessageResolution(receiverType = RPromise.class, language = TruffleRLanguage.class)
+public class RPromiseMR {
+    @Resolve(message = "IS_BOXED")
+    public abstract static class RPromiseIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RPromise receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class RPromiseHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RPromise receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class RPromiseIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RPromise receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "UNBOX")
+    public abstract static class RPromiseUnboxNode extends Node {
+        protected Object access(RPromise receiver) {
+            return receiver.getValue();
+        }
+    }
+
+    @CanResolve
+    public abstract static class RPromiseCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RPromise;
+        }
+    }
+}
-- 
GitLab


From dbd886d11c94917decf2c841313399f8b60890ea Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 4 May 2017 11:53:34 +0200
Subject: [PATCH 358/402] Fixed bug in message resolution of RList: Did return
 Java null which is not allowed.

---
 .../src/com/oracle/truffle/r/engine/interop/RListMR.java   | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
index 13c996f9c4..f75ff54701 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
@@ -41,6 +41,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 
 @MessageResolution(receiverType = RList.class, language = TruffleRLanguage.class)
@@ -75,7 +76,8 @@ public class RListMR {
         @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RList receiver, String field) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return extract.applyAccessField(frame, receiver, field);
+                Object applyAccessField = extract.applyAccessField(frame, receiver, field);
+                return applyAccessField;
             }
         }
     }
@@ -103,7 +105,8 @@ public class RListMR {
         @SuppressWarnings("try")
         protected Object access(RList receiver) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return getNamesNode.getNames(receiver);
+                RStringVector names = getNamesNode.getNames(receiver);
+                return names != null ? names : RNull.instance;
             }
         }
     }
-- 
GitLab


From dd1de0d16e158f3c1381d6f5257fe828ac26d310 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 4 May 2017 11:54:11 +0200
Subject: [PATCH 359/402] Improvement: Generating fewer files for deparsed
 source code.

---
 .../oracle/truffle/r/runtime/RDeparse.java    | 21 ++++++++-----------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index eb5e9f3c07..147efcf77d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -15,7 +15,6 @@ import java.io.BufferedWriter;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -324,19 +323,17 @@ public class RDeparse {
 
         public void fixupSources() {
             if (FastROptions.EmitTmpSource.getBooleanValue()) {
-                String tmpDirStr = FastROptions.EmitTmpDir.getStringValue();
-                Path tmpDir = tmpDirStr != null ? Paths.get(tmpDirStr) : null;
-                for (SourceSectionElement s : sources) {
-                    try {
-                        Path path = Files.createTempFile(tmpDir, "deparse-", ".r");
-                        try (BufferedWriter bw = Files.newBufferedWriter(path, StandardOpenOption.WRITE)) {
-                            bw.write(sb.toString());
-                        }
-                        Source source = RSource.fromFile(path.toFile());
+                try {
+                    Path path = Files.createTempFile("deparse-", ".r");
+                    try (BufferedWriter bw = Files.newBufferedWriter(path, StandardOpenOption.WRITE)) {
+                        bw.write(sb.toString());
+                    }
+                    Source source = RSource.fromFile(path.toFile());
+                    for (SourceSectionElement s : sources) {
                         s.element.setSourceSection(source.createSection(s.start, s.length));
-                    } catch (IOException e) {
-                        RInternalError.reportError(e);
                     }
+                } catch (IOException e) {
+                    RInternalError.reportError(e);
                 }
             } else {
                 Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE);
-- 
GitLab


From 52fd370127fa5bec044a924a5c54e99fd32429ea Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 4 May 2017 15:36:14 +0200
Subject: [PATCH 360/402] Further tried to reduce temporarily generated files
 from deparsed source by using a hash on the source.

---
 .../truffle/r/runtime/FastROptions.java       |  1 +
 .../oracle/truffle/r/runtime/RDeparse.java    | 40 ++++++++++++++++---
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index 9258059341..ad7e272e91 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -59,6 +59,7 @@ public enum FastROptions {
     LoadPackagesNativeCode("Load native code of packages, including builtin packages.", !FastRConfig.ManagedMode),
     EmitTmpSource("Write deparsed source code to temporary files for better debugging.", true),
     EmitTmpDir("The directory where to allocate temporary files with deparsed source code.", null, true),
+    EmitTmpHashed("Use an SHA-256 hash as file name to reduce temporary file creation.", true),
 
     // Promises optimizations
     EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 147efcf77d..05e90e6a62 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -11,16 +11,22 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import static java.nio.file.StandardOpenOption.CREATE_NEW;
+import static java.nio.file.StandardOpenOption.WRITE;
+
 import java.io.BufferedWriter;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 
+import javax.xml.bind.DatatypeConverter;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.object.DynamicObject;
@@ -321,19 +327,43 @@ public class RDeparse {
             }
         }
 
+        private static Path tmpDir = null;
+        private static MessageDigest digest = null;
+
+        private Path emitToFile() throws IOException, NoSuchAlgorithmException {
+            Path path;
+            if (FastROptions.EmitTmpHashed.getBooleanValue()) {
+                if (tmpDir == null) {
+                    tmpDir = Files.createTempDirectory("deparse");
+                }
+                if (digest == null) {
+                    digest = MessageDigest.getInstance("SHA-256");
+                }
+                String printHexBinary = DatatypeConverter.printHexBinary(digest.digest(sb.toString().getBytes()));
+                path = tmpDir.resolve(printHexBinary + ".r");
+            } else {
+                path = Files.createTempFile("deparse-", ".r");
+            }
+            if (!Files.exists(path)) {
+                try (BufferedWriter bw = Files.newBufferedWriter(path, CREATE_NEW, WRITE)) {
+                    bw.write(sb.toString());
+                }
+            }
+            return path;
+        }
+
         public void fixupSources() {
             if (FastROptions.EmitTmpSource.getBooleanValue()) {
                 try {
-                    Path path = Files.createTempFile("deparse-", ".r");
-                    try (BufferedWriter bw = Files.newBufferedWriter(path, StandardOpenOption.WRITE)) {
-                        bw.write(sb.toString());
-                    }
+                    Path path = emitToFile();
                     Source source = RSource.fromFile(path.toFile());
                     for (SourceSectionElement s : sources) {
                         s.element.setSourceSection(source.createSection(s.start, s.length));
                     }
                 } catch (IOException e) {
                     RInternalError.reportError(e);
+                } catch (NoSuchAlgorithmException e) {
+                    throw RInternalError.shouldNotReachHere("SHA-256 is an unknown algorithm");
                 }
             } else {
                 Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE);
-- 
GitLab


From 80b653870774bc19831660a9d339af249386de30 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 10 May 2017 13:56:21 +0200
Subject: [PATCH 361/402] Changed temporary source file generation to be
 generated in 'Rtmp...' folder.

---
 .../com/oracle/truffle/r/engine/interop/RListMR.java   |  6 ++----
 .../src/com/oracle/truffle/r/runtime/RDeparse.java     | 10 +++++++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
index f75ff54701..c202c48960 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
@@ -76,8 +76,7 @@ public class RListMR {
         @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RList receiver, String field) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object applyAccessField = extract.applyAccessField(frame, receiver, field);
-                return applyAccessField;
+                return extract.applyAccessField(frame, receiver, field);
             }
         }
     }
@@ -91,8 +90,7 @@ public class RListMR {
         protected Object access(VirtualFrame frame, RList receiver, String field, Object valueObj) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
                 Object value = javaToRPrimitive(valueObj);
-                Object x = replace.apply(frame, receiver, new Object[]{field}, value);
-                return x;
+                return replace.apply(frame, receiver, new Object[]{field}, value);
             }
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 05e90e6a62..6a208d6181 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -18,6 +18,7 @@ import java.io.BufferedWriter;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -332,10 +333,13 @@ public class RDeparse {
 
         private Path emitToFile() throws IOException, NoSuchAlgorithmException {
             Path path;
-            if (FastROptions.EmitTmpHashed.getBooleanValue()) {
-                if (tmpDir == null) {
-                    tmpDir = Files.createTempDirectory("deparse");
+            if (tmpDir == null) {
+                tmpDir = Paths.get(TempPathName.tempDirPath()).resolve("deparse");
+                if (!Files.exists(tmpDir)) {
+                    Files.createDirectory(tmpDir);
                 }
+            }
+            if (FastROptions.EmitTmpHashed.getBooleanValue()) {
                 if (digest == null) {
                     digest = MessageDigest.getInstance("SHA-256");
                 }
-- 
GitLab


From b09b89d1c786e8b85764193701a0f9b562f80807 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 15 May 2017 13:15:47 +0200
Subject: [PATCH 362/402] Modified taggging semantics to be able to register
 breakpoints to top-level call statements.

---
 .../com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java  | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index 378c3219ae..8a329dc6d3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -72,6 +72,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.ReturnException;
+import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -520,7 +521,8 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         String className = tag.getSimpleName();
         switch (className) {
             case "CallTag":
-                return node instanceof RCallNode;
+                // TODO: should just mark calls to other languages
+                return false;
 
             case "StatementTag": {
                 Node parent = ((RInstrumentableNode) node).unwrapParent();
@@ -541,7 +543,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
 
             case "RootTag": {
                 Node parent = ((RInstrumentableNode) node).unwrapParent();
-                return parent instanceof FunctionDefinitionNode;
+                return parent instanceof FunctionDefinitionNode || parent instanceof RootWithBody;
             }
 
             case "LoopTag":
-- 
GitLab


From 58f0502b25cea09be5cba2b555c6614822ae61bc Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 15 May 2017 19:03:15 +0200
Subject: [PATCH 363/402] Implemented message resolution for RLanguage.

---
 .../interop/RForeignAccessFactoryImpl.java    |   4 +
 .../truffle/r/engine/interop/RLanguageMR.java | 111 ++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 0c7f6bcb20..02bfc4dcdd 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -116,6 +117,9 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RPromiseMRForeign.ACCESS;
         } else if (obj instanceof RArgsValuesAndNames) {
             return RArgsValuesAndNamesMRForeign.ACCESS;
+        } else if (obj instanceof RLanguage) {
+            return RLanguageMRForeign.ACCESS;
+
         } else {
             if (obj instanceof RAbstractVector) {
                 return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
new file mode 100644
index 0000000000..e28a0e957d
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+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.engine.TruffleRLanguage;
+import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
+import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+@MessageResolution(receiverType = RLanguage.class, language = TruffleRLanguage.class)
+public class RLanguageMR {
+
+    @Resolve(message = "IS_BOXED")
+    public abstract static class RLanguageIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class RLanguageHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class RLanguageIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "READ")
+    public abstract static class RLanguageReadNode extends Node {
+        @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+
+        protected Object access(VirtualFrame frame, RLanguage receiver, int label) {
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE);
+            }
+        }
+    }
+
+    @Resolve(message = "WRITE")
+    public abstract static class RLanguageWriteNode extends Node {
+
+        @SuppressWarnings("unused")
+        protected Object access(VirtualFrame frame, RLanguage receiver, int label, Object valueObj) {
+            throw UnsupportedMessageException.raise(Message.WRITE);
+        }
+    }
+
+    @Resolve(message = "KEYS")
+    public abstract static class RLanguageKeysNode extends Node {
+
+        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
+            return RNull.instance;
+        }
+    }
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RLanguageKeyInfoNode extends Node {
+
+        @SuppressWarnings("unused")
+        protected Object access(VirtualFrame frame, RLanguage receiver, String identifier) {
+            return 0;
+        }
+    }
+
+    @CanResolve
+    public abstract static class RLanguageCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RLanguage;
+        }
+    }
+}
-- 
GitLab


From 9dce00c199b3f90ac098acb4e8b74b39fd963e1d Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 15 May 2017 19:04:08 +0200
Subject: [PATCH 364/402] Improved string representation for debugging for
 RLanguage and RS4Object.

---
 .../src/com/oracle/truffle/r/runtime/RRuntime.java        | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 0f5b22a965..abef457ba1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,13 +21,16 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -654,6 +657,10 @@ public class RRuntime {
             return Double.toString((double) object);
         } else if (object instanceof Byte) {
             return logicalToString((byte) object);
+        } else if (object instanceof RS4Object) {
+            return String.format("<RS4Object of class %s>", RContext.getRRuntimeASTAccess().getClassHierarchy((RS4Object) object));
+        } else if (object instanceof RLanguage) {
+            return RDeparse.deparse(object);
         }
 
         return String.valueOf(object);
@@ -918,4 +925,5 @@ public class RRuntime {
     private static boolean hasDims(RAbstractContainer xa) {
         return xa.hasDimensions();
     }
+
 }
-- 
GitLab


From 20095732599a0b5240a3fa7fbdd99a26e738774f Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Mon, 15 May 2017 19:05:17 +0200
Subject: [PATCH 365/402] Generating temporary source files using a qualified
 function name when possible.

---
 .../r/engine/RRuntimeASTAccessImpl.java       | 23 +++++++++++++
 .../oracle/truffle/r/runtime/RDeparse.java    | 33 +++++++++++++++++--
 .../truffle/r/runtime/RRuntimeASTAccess.java  |  7 ++++
 3 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index 8a329dc6d3..8eae3e3e08 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
@@ -89,6 +90,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
@@ -731,4 +733,25 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     public RAbstractStringVector getClassHierarchy(RAttributable value) {
         return ClassHierarchyNode.getClassHierarchy(value);
     }
+
+    @Override
+    public String getQualifiedFunctionName(RootNode n) {
+
+        if (n instanceof FunctionDefinitionNode && n.getName() != null) {
+            FunctionDefinitionNode fdn = (FunctionDefinitionNode) n;
+            StringBuilder qname = new StringBuilder(n.getName());
+            MaterializedFrame frame = (MaterializedFrame) Utils.getCallerFrame(Utils.getActualCurrentFrame(), FrameAccess.MATERIALIZE);
+            REnvironment env = REnvironment.frameToEnvironment(frame);
+
+            while (env != null && env.getPrintName() != null) {
+                qname.insert(0, '.');
+                qname.insert(0, env.getPrintName());
+                env = env.getParent();
+            }
+            return qname.toString();
+
+        }
+        return null;
+
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 6a208d6181..d6025670c0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -30,6 +30,8 @@ import javax.xml.bind.DatatypeConverter;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
@@ -331,7 +333,7 @@ public class RDeparse {
         private static Path tmpDir = null;
         private static MessageDigest digest = null;
 
-        private Path emitToFile() throws IOException, NoSuchAlgorithmException {
+        private Path emitToFile(String qualifiedFunctionName) throws IOException, NoSuchAlgorithmException {
             Path path;
             if (tmpDir == null) {
                 tmpDir = Paths.get(TempPathName.tempDirPath()).resolve("deparse");
@@ -344,7 +346,14 @@ public class RDeparse {
                     digest = MessageDigest.getInstance("SHA-256");
                 }
                 String printHexBinary = DatatypeConverter.printHexBinary(digest.digest(sb.toString().getBytes()));
-                path = tmpDir.resolve(printHexBinary + ".r");
+                assert printHexBinary.length() > 10;
+
+                // just use the first 10 hex digits to have a nicer file name
+                if (qualifiedFunctionName != null) {
+                    path = tmpDir.resolve(qualifiedFunctionName + "-" + printHexBinary.substring(0, 10) + ".r");
+                } else {
+                    path = tmpDir.resolve(printHexBinary.substring(0, 10) + ".r");
+                }
             } else {
                 path = Files.createTempFile("deparse-", ".r");
             }
@@ -359,7 +368,10 @@ public class RDeparse {
         public void fixupSources() {
             if (FastROptions.EmitTmpSource.getBooleanValue()) {
                 try {
-                    Path path = emitToFile();
+                    RootNode rn = getRootNode();
+                    String qualifiedFunctionName = RContext.getRRuntimeASTAccess().getQualifiedFunctionName(rn);
+
+                    Path path = emitToFile(qualifiedFunctionName);
                     Source source = RSource.fromFile(path.toFile());
                     for (SourceSectionElement s : sources) {
                         s.element.setSourceSection(source.createSection(s.start, s.length));
@@ -377,6 +389,21 @@ public class RDeparse {
             }
         }
 
+        private RootNode getRootNode() {
+            RootNode rn = null;
+            for (SourceSectionElement s : sources) {
+                if (s.element instanceof Node) {
+                    Node n = (Node) s.element;
+                    if (rn == null) {
+                        rn = n.getRootNode();
+                    } else {
+                        assert rn == n.getRootNode();
+                    }
+                }
+            }
+            return rn;
+        }
+
         @SuppressWarnings("try")
         private DeparseVisitor append(String str, RSyntaxElement... context) {
             try (C c = withContext(context)) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
index 15c84e15e2..13f1f0abb1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
@@ -204,4 +204,11 @@ public interface RRuntimeASTAccess {
     void checkDebugRequest(RFunction func);
 
     RAbstractStringVector getClassHierarchy(RAttributable value);
+
+    /**
+     * Creates a qualified name of an R function.
+     *
+     * @param n The root node of the function (i.e. the function definition node).
+     */
+    String getQualifiedFunctionName(RootNode n);
 }
-- 
GitLab


From 140a6936ccd3bb830725e26ea86465b2a85a689a Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 12:34:18 +0200
Subject: [PATCH 366/402] Write source of whole function to file if possible.

---
 .../r/engine/RRuntimeASTAccessImpl.java       | 23 -----------
 .../oracle/truffle/r/runtime/RDeparse.java    | 41 +++++++++++--------
 .../truffle/r/runtime/RRuntimeASTAccess.java  |  7 ----
 3 files changed, 23 insertions(+), 48 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index 8eae3e3e08..8a329dc6d3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
-import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
@@ -90,7 +89,6 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
@@ -733,25 +731,4 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     public RAbstractStringVector getClassHierarchy(RAttributable value) {
         return ClassHierarchyNode.getClassHierarchy(value);
     }
-
-    @Override
-    public String getQualifiedFunctionName(RootNode n) {
-
-        if (n instanceof FunctionDefinitionNode && n.getName() != null) {
-            FunctionDefinitionNode fdn = (FunctionDefinitionNode) n;
-            StringBuilder qname = new StringBuilder(n.getName());
-            MaterializedFrame frame = (MaterializedFrame) Utils.getCallerFrame(Utils.getActualCurrentFrame(), FrameAccess.MATERIALIZE);
-            REnvironment env = REnvironment.frameToEnvironment(frame);
-
-            while (env != null && env.getPrintName() != null) {
-                qname.insert(0, '.');
-                qname.insert(0, env.getPrintName());
-                env = env.getParent();
-            }
-            return qname.toString();
-
-        }
-        return null;
-
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index d6025670c0..c84b208bba 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -30,7 +30,6 @@ import javax.xml.bind.DatatypeConverter;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
@@ -349,7 +348,7 @@ public class RDeparse {
                 assert printHexBinary.length() > 10;
 
                 // just use the first 10 hex digits to have a nicer file name
-                if (qualifiedFunctionName != null) {
+                if (qualifiedFunctionName != null && !qualifiedFunctionName.isEmpty() && !qualifiedFunctionName.equals("<no source>")) {
                     path = tmpDir.resolve(qualifiedFunctionName + "-" + printHexBinary.substring(0, 10) + ".r");
                 } else {
                     path = tmpDir.resolve(printHexBinary.substring(0, 10) + ".r");
@@ -368,10 +367,9 @@ public class RDeparse {
         public void fixupSources() {
             if (FastROptions.EmitTmpSource.getBooleanValue()) {
                 try {
-                    RootNode rn = getRootNode();
-                    String qualifiedFunctionName = RContext.getRRuntimeASTAccess().getQualifiedFunctionName(rn);
-
-                    Path path = emitToFile(qualifiedFunctionName);
+                    RootNode rootNode = getRootNode();
+                    String name = rootNode != null ? rootNode.getName() : null;
+                    Path path = emitToFile(name);
                     Source source = RSource.fromFile(path.toFile());
                     for (SourceSectionElement s : sources) {
                         s.element.setSourceSection(source.createSection(s.start, s.length));
@@ -390,18 +388,12 @@ public class RDeparse {
         }
 
         private RootNode getRootNode() {
-            RootNode rn = null;
-            for (SourceSectionElement s : sources) {
-                if (s.element instanceof Node) {
-                    Node n = (Node) s.element;
-                    if (rn == null) {
-                        rn = n.getRootNode();
-                    } else {
-                        assert rn == n.getRootNode();
-                    }
-                }
+            // the last element in the list is the top-most one
+            RSyntaxElement n = sources.get(sources.size() - 1).element;
+            if (n instanceof RootNode) {
+                return (RootNode) n;
             }
-            return rn;
+            return null;
         }
 
         @SuppressWarnings("try")
@@ -1072,7 +1064,20 @@ public class RDeparse {
     public static void ensureSourceSection(RSyntaxNode node) {
         SourceSection ss = node.getLazySourceSection();
         if (ss == RSyntaxNode.LAZY_DEPARSE) {
-            new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
+            RSyntaxElement nodeToFixup = node;
+            if (FastROptions.EmitTmpSource.getBooleanValue()) {
+                RootNode rootNode = node.asNode().getRootNode();
+                if (RContext.getRRuntimeASTAccess().isFunctionDefinitionNode(rootNode)) {
+                    nodeToFixup = (RSyntaxElement) rootNode;
+                }
+            }
+            // try to generate the source from the root node and hopefully it includes this node
+            new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(nodeToFixup).fixupSources();
+
+            // if not, we have to deparse the node in isolation
+            if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
+                new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
+            }
             assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE;
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
index 13f1f0abb1..15c84e15e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
@@ -204,11 +204,4 @@ public interface RRuntimeASTAccess {
     void checkDebugRequest(RFunction func);
 
     RAbstractStringVector getClassHierarchy(RAttributable value);
-
-    /**
-     * Creates a qualified name of an R function.
-     *
-     * @param n The root node of the function (i.e. the function definition node).
-     */
-    String getQualifiedFunctionName(RootNode n);
 }
-- 
GitLab


From 110923b849dabc7f55a17131c58c98bb23e103cd Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 13:28:15 +0200
Subject: [PATCH 367/402] Fixed TCK unit test.

---
 .../truffle/r/engine/RRuntimeASTAccessImpl.java   |  3 +--
 .../com/oracle/truffle/r/runtime/RDeparse.java    | 15 ++++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index 8a329dc6d3..b264cb5476 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -521,8 +521,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         String className = tag.getSimpleName();
         switch (className) {
             case "CallTag":
-                // TODO: should just mark calls to other languages
-                return false;
+                return node instanceof RCallNode;
 
             case "StatementTag": {
                 Node parent = ((RInstrumentableNode) node).unwrapParent();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index c84b208bba..530ac3fcda 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -329,17 +329,15 @@ public class RDeparse {
             }
         }
 
-        private static Path tmpDir = null;
         private static MessageDigest digest = null;
 
         private Path emitToFile(String qualifiedFunctionName) throws IOException, NoSuchAlgorithmException {
-            Path path;
-            if (tmpDir == null) {
-                tmpDir = Paths.get(TempPathName.tempDirPath()).resolve("deparse");
-                if (!Files.exists(tmpDir)) {
-                    Files.createDirectory(tmpDir);
-                }
+            Path tmpDir = Paths.get(TempPathName.tempDirPath()).resolve("deparse");
+            if (!Files.exists(tmpDir)) {
+                Files.createDirectory(tmpDir);
             }
+
+            Path path;
             if (FastROptions.EmitTmpHashed.getBooleanValue()) {
                 if (digest == null) {
                     digest = MessageDigest.getInstance("SHA-256");
@@ -1078,6 +1076,9 @@ public class RDeparse {
             if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
                 new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
             }
+            if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
+                new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
+            }
             assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE;
         }
     }
-- 
GitLab


From e4490194c461926c3e21bb1b74ab955a32acc05b Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 15:23:50 +0200
Subject: [PATCH 368/402] Fixes making FastRDebugTest and FastRTckTest pass.

---
 .../com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java  | 2 +-
 .../src/com/oracle/truffle/r/runtime/RDeparse.java          | 6 +-----
 .../src/com/oracle/truffle/r/test/tck/FastRDebugTest.java   | 3 ++-
 3 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index b264cb5476..ed08560e6b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -536,7 +536,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
                     // single statement block, variable parent
                     // note: RepeatingNode is not a RSyntaxElement but the body of a loop is
                     // under the repeating node !
-                    return parent instanceof FunctionDefinitionNode || parent instanceof IfNode || parent instanceof AbstractLoopNode || ForNode.isLoopBody(node);
+                    return parent instanceof FunctionDefinitionNode || parent instanceof RootWithBody || parent instanceof IfNode || parent instanceof AbstractLoopNode || ForNode.isLoopBody(node);
                 }
             }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 530ac3fcda..950a3662ad 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -18,7 +18,6 @@ import java.io.BufferedWriter;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -332,7 +331,7 @@ public class RDeparse {
         private static MessageDigest digest = null;
 
         private Path emitToFile(String qualifiedFunctionName) throws IOException, NoSuchAlgorithmException {
-            Path tmpDir = Paths.get(TempPathName.tempDirPath()).resolve("deparse");
+            Path tmpDir = Files.createTempDirectory("deparse-");
             if (!Files.exists(tmpDir)) {
                 Files.createDirectory(tmpDir);
             }
@@ -1076,9 +1075,6 @@ public class RDeparse {
             if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
                 new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
             }
-            if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
-                new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
-            }
             assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE;
         }
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 131551f152..5edb60b06f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -161,6 +161,7 @@ public class FastRDebugTest {
             debuggerSession.suspendNextExecution();
         });
 
+        stepInto(1);
         assertLocation(2, "res = fac(2)");
         stepInto(2);
         assertLocation(9, "nMinusOne = n - 1",
@@ -218,7 +219,7 @@ public class FastRDebugTest {
 
         stepInto(1);
         stepOver(3);
-        assertLocation(6, "i", "i", 4, "n", 15.0, "str", "hello");
+        assertLocation(5, "i <- i + 1L", "i", 3, "n", 15.0, "str", "hello");
         assertMetaObjects(source, "i", "integer", "n", "double", "str", "character");
         stepOut();
         performWork();
-- 
GitLab


From 90d34a180c401af72507f57350ebf0e6fb24f072 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 17:05:26 +0200
Subject: [PATCH 369/402] Implemented message resolution for ActiveBinding.

---
 .../r/engine/interop/ActiveBindingMR.java     | 76 +++++++++++++++++++
 .../interop/RForeignAccessFactoryImpl.java    |  3 +
 .../r/runtime/env/frame/ActiveBinding.java    |  3 +-
 3 files changed, 81 insertions(+), 1 deletion(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
new file mode 100644
index 0000000000..98b6e9728a
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
+
+@MessageResolution(receiverType = ActiveBinding.class, language = TruffleRLanguage.class)
+public class ActiveBindingMR {
+    @Resolve(message = "IS_BOXED")
+    public abstract static class ActiveBindingIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class ActiveBindingHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class ActiveBindingIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "UNBOX")
+    public abstract static class ActiveBindingUnboxNode extends Node {
+        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+
+        protected Object access(ActiveBinding receiver) {
+            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+                return receiver.readValue();
+            }
+        }
+    }
+
+    @CanResolve
+    public abstract static class ActiveBindingCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof ActiveBinding;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 02bfc4dcdd..d9f4321f1a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -49,6 +49,7 @@ import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 
@@ -119,6 +120,8 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RArgsValuesAndNamesMRForeign.ACCESS;
         } else if (obj instanceof RLanguage) {
             return RLanguageMRForeign.ACCESS;
+        } else if (obj instanceof ActiveBinding) {
+            return ActiveBindingMRForeign.ACCESS;
 
         } else {
             if (obj instanceof RAbstractVector) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
index 694e6332c5..f44d5c5222 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
@@ -29,13 +29,14 @@ import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
  * Represent an active binding of a function. This requires special treatment when reading and
  * writing variables.
  */
-public class ActiveBinding {
+public class ActiveBinding implements RTruffleObject {
 
     private final RType expectedType;
     private final RFunction function;
-- 
GitLab


From fb91e5c1c12e3dbd6f964776426c24f1c06a38a1 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 17:13:26 +0200
Subject: [PATCH 370/402] Now using RPairList for OnExit handlers instead of
 ArrayList to avoid interop problems.

---
 .../truffle/r/nodes/builtin/base/OnExit.java  | 19 ++++++++++---------
 .../function/FunctionDefinitionNode.java      | 19 +++++++++++--------
 2 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index 4dabafd778..3f472f67aa 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -27,8 +27,6 @@ import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import java.util.ArrayList;
-
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -42,7 +40,9 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
@@ -66,7 +66,6 @@ public abstract class OnExit extends RBuiltinNode.Arg2 {
         return new Object[]{RNull.instance, RRuntime.LOGICAL_FALSE};
     }
 
-    @SuppressWarnings("unchecked")
     @Specialization
     protected Object onExit(VirtualFrame frame, RPromise expr, boolean add) {
 
@@ -78,7 +77,7 @@ public abstract class OnExit extends RBuiltinNode.Arg2 {
         // the empty (RNull.instance) expression is used to clear on.exit
         if (emptyPromiseProfile.profile(expr.isDefaultArgument())) {
             assert expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise";
-            frame.setObject(onExitSlot, new ArrayList<>());
+            frame.setObject(onExitSlot, RDataFactory.createPairList());
         } else {
             assert !expr.isEvaluated() : "promise cannot already be evaluated";
             Object value;
@@ -87,18 +86,20 @@ public abstract class OnExit extends RBuiltinNode.Arg2 {
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere();
             }
-            ArrayList<Object> list;
+            RPairList list;
             if (newProfile.profile(value == null)) {
                 // initialize the list of exit handlers
-                frame.setObject(onExitSlot, list = new ArrayList<>());
+                frame.setObject(onExitSlot, list = RDataFactory.createPairList());
             } else {
-                list = (ArrayList<Object>) value;
+                list = (RPairList) value;
                 if (addProfile.profile(!add)) {
                     // add is false, so clear the existing list
-                    list.clear();
+                    assert !list.isShared();
+                    list.setCdr(RNull.instance);
+                    list.setCar(RNull.instance);
                 }
             }
-            list.add(expr.getRep());
+            list.appendToEnd(RDataFactory.createPairList(expr.getRep()));
         }
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 2c87c80b61..b815e59a2a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -68,6 +68,8 @@ import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.Utils.DebugExitException;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
@@ -339,17 +341,19 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
                         CompilerDirectives.transferToInterpreterAndInvalidate();
                         onExitExpressionCache = insert(InlineCacheNode.createExpression(3));
                     }
-                    ArrayList<Object> current = getCurrentOnExitList(frame, onExitSlot.executeFrameSlot(frame));
+                    RPairList current = getCurrentOnExitList(frame, onExitSlot.executeFrameSlot(frame));
                     /*
                      * We do not need to preserve visibility, since visibility.executeEndOfFunction
                      * was already called.
                      */
                     try {
-                        for (Object expr : current) {
-                            if (!(expr instanceof RNode)) {
-                                RInternalError.shouldNotReachHere("unexpected type for on.exit entry");
+                        for (RPairList expr : current) {
+                            if (expr.car() != RNull.instance) {
+                                if (!(expr.car() instanceof RNode)) {
+                                    RInternalError.shouldNotReachHere("unexpected type for on.exit entry: " + expr.car());
+                                }
+                                onExitExpressionCache.execute(frame, expr.car());
                             }
-                            onExitExpressionCache.execute(frame, expr);
                         }
                     } catch (ReturnException ex) {
                         if (returnTopLevelProfile.profile(ex.getTarget() == RArguments.getCall(frame))) {
@@ -448,10 +452,9 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         }
     }
 
-    @SuppressWarnings("unchecked")
-    private static ArrayList<Object> getCurrentOnExitList(VirtualFrame frame, FrameSlot slot) {
+    private static RPairList getCurrentOnExitList(VirtualFrame frame, FrameSlot slot) {
         try {
-            return (ArrayList<Object>) FrameSlotChangeMonitor.getObject(slot, frame);
+            return (RPairList) FrameSlotChangeMonitor.getObject(slot, frame);
         } catch (FrameSlotTypeException e) {
             throw RInternalError.shouldNotReachHere();
         }
-- 
GitLab


From 523e6a0b4e3bc54111c8e7b27aecbc7af48a6c7e Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 17:14:23 +0200
Subject: [PATCH 371/402] Improved string output of variables for debugging.

---
 .../src/com/oracle/truffle/r/engine/TruffleRLanguage.java | 4 ++++
 .../src/com/oracle/truffle/r/runtime/RRuntime.java        | 8 --------
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index 1e282c0909..6c98e3dd2b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -43,6 +43,7 @@ import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags;
 import com.oracle.truffle.r.runtime.ExitException;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RAccuracyInfo;
+import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
@@ -141,6 +142,9 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
         if (unwrapped instanceof String) {
             return (String) unwrapped;
         }
+        if (unwrapped instanceof RTypedValue) {
+            return RDeparse.deparse(unwrapped);
+        }
         return RRuntime.toString(unwrapped);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index abef457ba1..542a7976db 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,16 +21,13 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
-import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
@@ -657,12 +654,7 @@ public class RRuntime {
             return Double.toString((double) object);
         } else if (object instanceof Byte) {
             return logicalToString((byte) object);
-        } else if (object instanceof RS4Object) {
-            return String.format("<RS4Object of class %s>", RContext.getRRuntimeASTAccess().getClassHierarchy((RS4Object) object));
-        } else if (object instanceof RLanguage) {
-            return RDeparse.deparse(object);
         }
-
         return String.valueOf(object);
     }
 
-- 
GitLab


From e880bbeab9304dd4c8b417c5c8d1f9b01adfce08 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 17:37:58 +0200
Subject: [PATCH 372/402] Moved testChannelConnection from TestConnections to
 TestInterop.

---
 .../r/test/library/base/TestConnections.java  | 48 -------------------
 .../r/test/library/fastr/TestInterop.java     | 44 +++++++++++++++++
 2 files changed, 44 insertions(+), 48 deletions(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index 2272c54b4b..f1aeb3cf9e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.test.library.base;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.nio.ByteBuffer;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -36,16 +35,11 @@ import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
-import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel;
 import com.oracle.truffle.r.test.TestBase;
 import com.oracle.truffle.r.test.TestRBase;
 
 // Checkstyle: stop line length check
 public class TestConnections extends TestRBase {
-    private static final String CHANNEL_NAME = "_fastr_channel0";
-
     private static final class TestDir {
         private final Path testDirPath;
 
@@ -276,46 +270,4 @@ public class TestConnections extends TestRBase {
     private static String[] arr(String... args) {
         return args;
     }
-
-    private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel();
-
-    @Test
-    public void testChannelConnection() throws IOException {
-
-        final String line0 = "Hello, World!\n";
-        final String line1 = "second line\n";
-        CHANNEL.write(line0.getBytes());
-        CHANNEL.write(line1.getBytes());
-        long oldPos = CHANNEL.position();
-        CHANNEL.position(0);
-        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res",
-                        CHANNEL_NAME),
-                        "c('Hello, World!', 'second line')");
-
-        if (!generatingExpected()) {
-            // test if FastR consumed the data
-            Assert.assertEquals(oldPos, CHANNEL.position());
-
-            // re-open channel
-            CHANNEL.setOpen(true);
-            CHANNEL.position(0);
-        }
-
-        final String response = "hi there";
-        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('%s', zz); close(zz); NULL ", CHANNEL_NAME, response),
-                        "NULL");
-
-        if (!generatingExpected()) {
-            ByteBuffer buf = ByteBuffer.allocate(response.length());
-            CHANNEL.setOpen(true);
-            CHANNEL.position(0);
-            CHANNEL.read(buf);
-            Assert.assertEquals(response, new String(buf.array()));
-        }
-    }
-
-    @Override
-    public void addPolyglotSymbols(Builder builder) {
-        builder.globalSymbol(CHANNEL_NAME, JavaInterop.asTruffleObject(CHANNEL));
-    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index 35c727bf15..aa9ffbca00 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -22,14 +22,22 @@
  */
 package com.oracle.truffle.r.test.library.fastr;
 
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.junit.Assert;
 import org.junit.Test;
 
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel;
 import com.oracle.truffle.r.test.TestBase;
 
 public class TestInterop extends TestBase {
 
+    private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel();
+    private static final String CHANNEL_NAME = "_fastr_channel0";
+
     @Test
     public void testInteropEval() {
         assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16");
@@ -85,6 +93,7 @@ public class TestInterop extends TestBase {
         for (TestJavaObject t : TestInterop.testJavaObjects) {
             builder.globalSymbol(t.name, JavaInterop.asTruffleObject(t.object));
         }
+        builder.globalSymbol(CHANNEL_NAME, JavaInterop.asTruffleObject(CHANNEL));
     }
 
     @Test
@@ -120,4 +129,39 @@ public class TestInterop extends TestBase {
                         "[1] TRUE\\n')");
         assertEvalFastR("v <- .fastr.interop.import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')");
     }
+
+    @Test
+    public void testChannelConnection() throws IOException {
+
+        final String line0 = "Hello, World!\n";
+        final String line1 = "second line\n";
+        CHANNEL.write(line0.getBytes());
+        CHANNEL.write(line1.getBytes());
+        long oldPos = CHANNEL.position();
+        CHANNEL.position(0);
+        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res",
+                        CHANNEL_NAME),
+                        "c('Hello, World!', 'second line')");
+
+        if (!generatingExpected()) {
+            // test if FastR consumed the data
+            Assert.assertEquals(oldPos, CHANNEL.position());
+
+            // re-open channel
+            CHANNEL.setOpen(true);
+            CHANNEL.position(0);
+        }
+
+        final String response = "hi there";
+        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('%s', zz); close(zz); NULL ", CHANNEL_NAME, response),
+                        "NULL");
+
+        if (!generatingExpected()) {
+            ByteBuffer buf = ByteBuffer.allocate(response.length());
+            CHANNEL.setOpen(true);
+            CHANNEL.position(0);
+            CHANNEL.read(buf);
+            Assert.assertEquals(response, new String(buf.array()));
+        }
+    }
 }
-- 
GitLab


From 64ac4e4259d9ada6cbb3c04381f89e7656340bed Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Tue, 16 May 2017 17:32:28 +0200
Subject: [PATCH 373/402] Suppress warning to pass gate.

---
 .../src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java | 1 +
 .../src/com/oracle/truffle/r/engine/interop/RLanguageMR.java     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
index 98b6e9728a..b028bd676d 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
@@ -59,6 +59,7 @@ public class ActiveBindingMR {
     public abstract static class ActiveBindingUnboxNode extends Node {
         @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
+        @SuppressWarnings("try")
         protected Object access(ActiveBinding receiver) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
                 return receiver.readValue();
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
index e28a0e957d..df173b4679 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
@@ -68,6 +68,7 @@ public class RLanguageMR {
         @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
         @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
+        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RLanguage receiver, int label) {
             try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
                 return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE);
-- 
GitLab


From 87b2d566dce2ade276758437d78d4334cf36512f Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 17 May 2017 12:05:13 +0200
Subject: [PATCH 374/402] Using a constant name for the temp directory where to
 dump temp source files into.

---
 .../oracle/truffle/r/runtime/RDeparse.java    |  3 ++-
 .../truffle/r/runtime/TempPathName.java       | 17 +--------------
 .../com/oracle/truffle/r/runtime/Utils.java   | 21 +++++++++++++++++++
 3 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 950a3662ad..7c250e88e7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -18,6 +18,7 @@ import java.io.BufferedWriter;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
@@ -331,7 +332,7 @@ public class RDeparse {
         private static MessageDigest digest = null;
 
         private Path emitToFile(String qualifiedFunctionName) throws IOException, NoSuchAlgorithmException {
-            Path tmpDir = Files.createTempDirectory("deparse-");
+            Path tmpDir = Paths.get(Utils.getUserTempDir()).resolve("deparse");
             if (!Files.exists(tmpDir)) {
                 Files.createDirectory(tmpDir);
             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
index 7ce064541e..822fd6f26e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
@@ -58,17 +58,7 @@ public class TempPathName implements RContext.ContextState {
             tempDirPath = context.getParent().stateTempPath.tempDirPath;
             return this;
         }
-        final String[] envVars = new String[]{"TMPDIR", "TMP", "TEMP"};
-        String startingTempDir = null;
-        for (String envVar : envVars) {
-            String value = System.getenv(envVar);
-            if (value != null && isWriteableDirectory(value)) {
-                startingTempDir = value;
-            }
-        }
-        if (startingTempDir == null) {
-            startingTempDir = "/tmp";
-        }
+        String startingTempDir = Utils.getUserTempDir();
         Path startingTempDirPath = FileSystems.getDefault().getPath(startingTempDir, "Rtmp");
         // ensure absolute, to avoid problems with R code does a setwd
         if (!startingTempDirPath.isAbsolute()) {
@@ -96,11 +86,6 @@ public class TempPathName implements RContext.ContextState {
         }
     }
 
-    private static boolean isWriteableDirectory(String path) {
-        File f = new File(path);
-        return f.exists() && f.isDirectory() && f.canWrite();
-    }
-
     public static String tempDirPath() {
         String result = RContext.getInstance().stateTempPath.tempDirPath;
         return result;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index a5ac484ad1..a511ed9689 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.runtime;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -697,4 +698,24 @@ public final class Utils {
     public static String stringFormat(String format, Object... objects) {
         return String.format(format, objects);
     }
+
+    private static boolean isWriteableDirectory(String path) {
+        File f = new File(path);
+        return f.exists() && f.isDirectory() && f.canWrite();
+    }
+
+    public static String getUserTempDir() {
+        final String[] envVars = new String[]{"TMPDIR", "TMP", "TEMP"};
+        String startingTempDir = null;
+        for (String envVar : envVars) {
+            String value = System.getenv(envVar);
+            if (value != null && isWriteableDirectory(value)) {
+                startingTempDir = value;
+            }
+        }
+        if (startingTempDir == null) {
+            startingTempDir = "/tmp";
+        }
+        return startingTempDir;
+    }
 }
-- 
GitLab


From c68efee2053c4c8e5435792915202dcd3c0ee76c Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Wed, 17 May 2017 13:16:44 +0200
Subject: [PATCH 375/402] Pending cast pipelines issues fixed

---
 .../builtin/base/ConnectionFunctions.java     | 13 +---
 .../r/nodes/builtin/base/LaFunctions.java     |  6 +-
 .../r/nodes/builtin/base/SeqFunctions.java    | 59 ++++++++-----------
 .../truffle/r/nodes/builtin/base/Switch.java  | 10 +---
 .../nodes/builtin/base/TrigExpFunctions.java  |  6 +-
 .../r/nodes/builtin/fastr/FastrDqrls.java     |  8 ++-
 .../r/nodes/unary/CastLogicalNode.java        |  5 --
 .../com/oracle/truffle/r/runtime/RError.java  |  2 +-
 8 files changed, 45 insertions(+), 64 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 976df1b8bd..272c1ea4e8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -70,7 +70,6 @@ import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.ConnectionFunctionsFactory.WriteDataNodeGen;
 import com.oracle.truffle.r.nodes.builtin.casts.fluent.HeadPhaseBuilder;
-import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder;
 import com.oracle.truffle.r.runtime.RCompression;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -153,15 +152,7 @@ public abstract class ConnectionFunctions {
 
     public static final class CastsHelper {
         private static HeadPhaseBuilder<String> description(Casts casts) {
-            return descriptionInternal(casts.arg("description"));
-        }
-
-        private static HeadPhaseBuilder<String> descriptionNull(Casts casts) {
-            return descriptionInternal(casts.arg("description").allowNull());
-        }
-
-        private static HeadPhaseBuilder<String> descriptionInternal(InitialPhaseBuilder<Object> casts) {
-            return casts.mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
+            return casts.arg("description").mustBe(stringValue()).asStringVector().shouldBe(singleElement(), RError.Message.ARGUMENT_ONLY_FIRST_1, "description").findFirst().mustNotBeNA();
         }
 
         private static HeadPhaseBuilder<String> open(Casts casts) {
@@ -351,7 +342,7 @@ public abstract class ConnectionFunctions {
 
         static {
             Casts casts = new Casts(TextConnection.class);
-            CastsHelper.descriptionNull(casts);
+            CastsHelper.description(casts);
             casts.arg("text").allowNull().mustBe(stringValue());
             CastsHelper.open(casts).mustBe(equalTo("").or(equalTo("r").or(equalTo("w").or(equalTo("a")))), RError.Message.UNSUPPORTED_MODE);
             casts.arg("env").mustNotBeNull(RError.Message.USE_NULL_ENV_DEFUNCT).mustBe(instanceOf(REnvironment.class));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 0840afea59..d1515e966d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -13,11 +13,14 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimGt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.or;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix;
@@ -571,7 +574,8 @@ public class LaFunctions {
             casts.arg("a").mustBe(numericValue()).asVector().mustBe(matrix(), Message.MUST_BE_NUMERIC_MATRIX, "a").mustBe(not(dimEq(0, 0)),
                             Message.GENERIC, "'a' is 0-diml").mustBe(squareMatrix(), Message.MUST_BE_SQUARE_MATRIX_SPEC, "a", getDimVal(0), getDimVal(1));
 
-            casts.arg("bin").asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), Message.GENERIC, "no right-hand side in 'b'");
+            casts.arg("bin").returnIf(missingValue().or(nullValue()), emptyDoubleVector()).asDoubleVector(false, true, false).mustBe(or(not(matrix()), not(dimEq(1, 0))), Message.GENERIC,
+                            "no right-hand side in 'b'");
 
             casts.arg("tolin").asDoubleVector().findFirst(RRuntime.DOUBLE_NA);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index 80c1bfd838..bc951e221b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -197,9 +197,9 @@ public final class SeqFunctions {
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode fromCheck) {
             if (isNumericProfile.profile(fromCheck.execute(args.getArgument(0)))) {
                 if (args.getLength() == 1) {
-                    return seqInt.execute(frame, RMissing.instance, RMissing.instance, RMissing.instance, args.getArgument(0), RMissing.instance);
+                    return seqInt.execute(frame, RMissing.instance, RMissing.instance, RMissing.instance, args.getArgument(0), RMissing.instance, RMissing.instance);
                 } else {
-                    return seqInt.execute(frame, args.getArgument(0), RMissing.instance, RMissing.instance, args.getArgument(1), RMissing.instance);
+                    return seqInt.execute(frame, args.getArgument(0), RMissing.instance, RMissing.instance, args.getArgument(1), RMissing.instance, RMissing.instance);
                 }
             } else {
                 return null;
@@ -217,7 +217,7 @@ public final class SeqFunctions {
                         @Cached("createIsMissingOrNumericNode()") @SuppressWarnings("unused") IsMissingOrNumericNode byCheck) {
             Object[] rargs = reorderedArguments(args, seqIntFunction);
             if (isNumericProfile.profile(fromCheck.execute(rargs[0]) && toCheck.execute(rargs[1]) && toCheck.execute(rargs[2]))) {
-                return seqInt.execute(frame, rargs[0], rargs[1], rargs[2], rargs[3], rargs[4]);
+                return seqInt.execute(frame, rargs[0], rargs[1], rargs[2], rargs[3], rargs[4], RMissing.instance);
             } else {
                 return null;
             }
@@ -309,7 +309,7 @@ public final class SeqFunctions {
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode fromCheck,
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode toCheck,
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode byCheck) {
-            return seqInt.execute(frame, fromObj, toObj, byObj, lengthOut, alongWith);
+            return seqInt.execute(frame, fromObj, toObj, byObj, lengthOut, alongWith, RMissing.instance);
         }
 
         /**
@@ -407,7 +407,7 @@ public final class SeqFunctions {
     @ImportStatic({AsRealNodeGen.class, SeqFunctions.class})
     @com.oracle.truffle.r.runtime.builtins.RBuiltin(name = "seq.int", kind = PRIMITIVE, parameterNames = {"from", "to", "by", "length.out", "along.with",
                     "..."}, dispatch = INTERNAL_GENERIC, genericName = "seq", behavior = PURE)
-    public abstract static class SeqInt extends RBuiltinNode.Arg5 {
+    public abstract static class SeqInt extends RBuiltinNode.Arg6 {
         private final BranchProfile error = BranchProfile.create();
         private final boolean seqFastPath;
 
@@ -426,7 +426,7 @@ public final class SeqFunctions {
         }
 
         @Override
-        public abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith);
+        public abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith, Object dotdotdot);
 
         protected SeqInt(boolean seqFastPath) {
             this.seqFastPath = seqFastPath;
@@ -447,7 +447,7 @@ public final class SeqFunctions {
         // No matching args (special case)
 
         @Specialization
-        protected RIntSequence allMissing(RMissing from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RIntSequence allMissing(RMissing from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             // GNU R allows this and returns 1
             return RDataFactory.createIntSequence(1, 1, 1);
         }
@@ -462,7 +462,7 @@ public final class SeqFunctions {
          * Irrespective of the R type, if the length is zero the result is an empty sequence.
          */
         @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) == 0"})
-        protected RIntVector emptySeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RIntVector emptySeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             return RDataFactory.createEmptyIntVector();
         }
 
@@ -473,7 +473,7 @@ public final class SeqFunctions {
          * but the value likely could not be coerced.
          */
         @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) > 1"})
-        protected RIntSequence lenSeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RIntSequence lenSeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             return RDataFactory.createIntSequence(1, 1, getLength(frame, from));
         }
 
@@ -481,7 +481,7 @@ public final class SeqFunctions {
          * A length-1 REAL. Return "1:(int) from" where from is positive integral
          */
         @Specialization(guards = {"fromVec.getLength() == 1", "isPositiveIntegralDouble(fromVec.getDataAt(0))"})
-        protected RAbstractVector seqFromOneArgIntDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RAbstractVector seqFromOneArgIntDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             int len = (int) fromVec.getDataAt(0);
             return RDataFactory.createIntSequence(1, 1, len);
         }
@@ -491,7 +491,7 @@ public final class SeqFunctions {
          * {@code seq(0.2)} is NOT the same as {@code seq(0.0)} (according to GNU R)
          */
         @Specialization(guards = "fromVec.getLength() == 1")
-        protected RAbstractVector seqFromOneArgDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RAbstractVector seqFromOneArgDouble(RAbstractDoubleVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             double from = validateDoubleParam(fromVec.getDataAt(0), fromVec, "from");
             int len = effectiveLength(1, from);
             return RDataFactory.createIntSequence(1, from > 0 ? 1 : -1, len);
@@ -501,7 +501,7 @@ public final class SeqFunctions {
          * A length-1 INT. Return "1:from" (N.B. from may be negative)
          */
         @Specialization(guards = "fromVec.getLength() == 1")
-        protected RIntSequence seqFromOneArgInt(RAbstractIntVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RIntSequence seqFromOneArgInt(RAbstractIntVector fromVec, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             int from = validateIntParam(fromVec.getDataAt(0), "from");
             int len = from > 0 ? from : 2 - from;
             return RDataFactory.createIntSequence(1, from > 0 ? 1 : -1, len);
@@ -514,19 +514,10 @@ public final class SeqFunctions {
          * which would be incorrect as the result is different.
          */
         @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) == 1", "!isNumeric(from)"})
-        protected RIntSequence seqFromOneArgObj(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith) {
+        protected RIntSequence seqFromOneArgObj(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             return RDataFactory.createIntSequence(1, 1, 1);
         }
 
-        /**
-         * Treat {@code lengthOut==NULL} as {@link RMissing}.
-         */
-        @Specialization
-        protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object from, Object to, Object by, RNull lengthOut, RMissing alongWith,
-                        @Cached("createSeqInt()") SeqInt seqIntNodeRecursive) {
-            return (RAbstractVector) seqIntNodeRecursive.execute(frame, from, to, by, RMissing.instance, alongWith);
-        }
-
         /*
          * seq(from,to) but either could be missing. "along.with" is missing and "length.out" is
          * missing (or NULL), and "by" (by) is missing. N.B. we are only interested in the cases
@@ -539,6 +530,7 @@ public final class SeqFunctions {
 
         @Specialization(guards = "validDoubleParams(fromVec, toVec)")
         protected RAbstractVector seqLengthByMissingDouble(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith,
+                        Object dotdotdot,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
             double from = fromVec.getDataAt(0);
             double to = toVec.getDataAt(0);
@@ -547,7 +539,7 @@ public final class SeqFunctions {
         }
 
         @Specialization(guards = "validIntParams(fromVec, toVec)")
-        protected RAbstractVector seqLengthByMissingInt(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith,
+        protected RAbstractVector seqLengthByMissingInt(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
             int from = fromVec.getDataAt(0);
             int to = toVec.getDataAt(0);
@@ -563,7 +555,7 @@ public final class SeqFunctions {
          * previous specializations.
          */
         @Specialization(guards = {"!isMissing(toObj)"})
-        protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object fromObj, Object toObj, RMissing by, RMissing lengthOut, RMissing alongWith,
+        protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object fromObj, Object toObj, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
@@ -589,7 +581,7 @@ public final class SeqFunctions {
          */
 
         @Specialization(guards = {"validDoubleParams(fromVec, toVec)", "!isMissing(byObj)"})
-        protected Object seqLengthMissing(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, Object byObj, RMissing lengthOut, RMissing alongWith,
+        protected Object seqLengthMissing(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealby) {
             validateLength(frame, byObj, "by");
             double by = asRealby.execute(byObj);
@@ -598,6 +590,7 @@ public final class SeqFunctions {
 
         @Specialization(guards = {"validIntParams(fromVec, toVec)", "validIntParam(byVec)", "byVec.getDataAt(0) != 0"})
         protected RAbstractVector seqLengthMissing(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RAbstractIntVector byVec, RMissing lengthOut, RMissing alongWith,
+                        Object dotdotdot,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
             int by = byVec.getDataAt(0);
             int from = fromVec.getDataAt(0);
@@ -626,7 +619,7 @@ public final class SeqFunctions {
          * See comment in {@link #seqLengthByMissing}.
          */
         @Specialization(guards = {"!isMissing(byObj)"})
-        protected Object seqLengthMissing(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, RMissing lengthOut, RMissing alongWith,
+        protected Object seqLengthMissing(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("create()") AsRealNode asRealby) {
@@ -722,7 +715,7 @@ public final class SeqFunctions {
          */
 
         @Specialization(guards = "!isMissing(lengthOut)")
-        protected RAbstractVector seqJustLength(VirtualFrame frame, RMissing from, RMissing to, RMissing by, Object lengthOut, RMissing alongWith,
+        protected RAbstractVector seqJustLength(VirtualFrame frame, RMissing from, RMissing to, RMissing by, Object lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealLen) {
             int n = checkLength(frame, lengthOut, asRealLen);
             return n == 0 ? RDataFactory.createEmptyIntVector() : RDataFactory.createIntSequence(1, 1, n);
@@ -731,7 +724,7 @@ public final class SeqFunctions {
         // seq(along,with=)
 
         @Specialization(guards = "!isMissing(alongWith)")
-        protected RAbstractVector seqFromJustAlong(VirtualFrame frame, RMissing from, RMissing to, RMissing by, RMissing lengthOut, Object alongWith) {
+        protected RAbstractVector seqFromJustAlong(VirtualFrame frame, RMissing from, RMissing to, RMissing by, RMissing lengthOut, Object alongWith, Object dotdotdot) {
             int len = getLength(frame, alongWith);
             return len == 0 ? RDataFactory.createEmptyIntVector() : RDataFactory.createIntSequence(1, 1, len);
         }
@@ -805,7 +798,7 @@ public final class SeqFunctions {
 
         // common idiom
         @Specialization(guards = {"fromCheck.execute(fromObj)", "lengthCheck.execute(lengthOut)"})
-        protected RAbstractVector seqWithFromLengthIntegralNumeric(VirtualFrame frame, Object fromObj, RMissing toObj, RMissing byObj, Object lengthOut, RMissing alongWith,
+        protected RAbstractVector seqWithFromLengthIntegralNumeric(VirtualFrame frame, Object fromObj, RMissing toObj, RMissing byObj, Object lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("createGetIntegralNumericNode()") GetIntegralNumericNode getIntegralNumericNode,
                         @Cached("createIsIntegralNumericNodeNoLengthCheck()") IsIntegralNumericNode fromCheck,
                         @Cached("createIsIntegralNumericNodeLengthCheck()") IsIntegralNumericNode lengthCheck) {
@@ -820,7 +813,7 @@ public final class SeqFunctions {
 
         // "by" missing
         @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(fromObj, toObj)"})
-        protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, Object toObj, RMissing byObj, Object lengthOut, Object alongWith,
+        protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, Object toObj, RMissing byObj, Object lengthOut, Object alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("create()") AsRealNode asRealLen) {
@@ -874,7 +867,7 @@ public final class SeqFunctions {
 
         // "to" missing
         @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(fromObj, byObj)"})
-        protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, RMissing toObj, Object byObj, Object lengthOut, Object alongWith,
+        protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, RMissing toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealby,
                         @Cached("create()") AsRealNode asRealLen) {
@@ -901,7 +894,7 @@ public final class SeqFunctions {
 
         // "from" missing
         @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(toObj, byObj)"})
-        protected RAbstractVector seqWithLength(VirtualFrame frame, RMissing fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith,
+        protected RAbstractVector seqWithLength(VirtualFrame frame, RMissing fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("create()") AsRealNode asRealby,
                         @Cached("create()") AsRealNode asRealLen) {
@@ -922,7 +915,7 @@ public final class SeqFunctions {
         }
 
         @Fallback
-        protected RAbstractVector seqFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith) {
+        protected RAbstractVector seqFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot) {
             error.enter();
             throw error(RError.Message.TOO_MANY_ARGS);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
index e403219f5f..e266bceac2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java
@@ -21,7 +21,6 @@ import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
@@ -39,7 +38,6 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RList;
-import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
@@ -70,6 +68,7 @@ public abstract class Switch extends RBuiltinNode.Arg2 {
         Casts casts = new Casts(Switch.class);
         // first argument must be list or expression or vector of size 1, if it is not String, cast it to integer
         casts.arg("EXPR").defaultError(RError.Message.EXPR_NOT_LENGTH_ONE).
+                mustNotBeMissing(RError.Message.EXPR_MISSING).
                 returnIf(atomicIntegerValue().or(instanceOf(String.class)).or(instanceOf(RExpression.class))).
                 mustBe(abstractVectorValue()).boxPrimitive().mustBe(size(1)).
                 returnIf(stringValue(), findFirst().stringElement()).
@@ -176,13 +175,6 @@ public abstract class Switch extends RBuiltinNode.Arg2 {
         return prepareResult(frame, doSwitchInt(frame, x, optionalArgs));
     }
 
-    @SuppressWarnings("unused")
-    @Specialization
-    protected Object doSwitch(RMissing x, RMissing optionalArgs) {
-        CompilerDirectives.transferToInterpreter();
-        throw error(RError.Message.EXPR_MISSING);
-    }
-
     private Object doSwitchInt(VirtualFrame frame, int index, RArgsValuesAndNames optionalArgs) {
         if (noAlternativesProfile.profile(optionalArgs.getLength() == 0)) {
             warning(RError.Message.NO_ALTERNATIVES_IN_SWITCH);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index b7b963b1e9..62eb8e2620 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -565,7 +565,7 @@ public class TrigExpFunctions {
                             profile);
         }
 
-        @Fallback
+        @Specialization(guards = {"!isDouble(x) || !isDouble(y)"})
         @TruffleBoundary
         protected Object atan2(Object x, Object y) {
             if (x instanceof RAbstractComplexVector || y instanceof RAbstractComplexVector) {
@@ -573,5 +573,9 @@ public class TrigExpFunctions {
             }
             throw error(RError.Message.NON_NUMERIC_MATH);
         }
+
+        protected static boolean isDouble(Object x) {
+            return x instanceof Double || x instanceof RAbstractDoubleVector;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
index 5dc87230fc..043cfb7544 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
@@ -11,6 +11,8 @@
  */
 package com.oracle.truffle.r.nodes.builtin.fastr;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -44,13 +46,13 @@ public abstract class FastrDqrls extends RBuiltinNode.Arg7 {
 
     static {
         Casts casts = new Casts(FastrDqrls.class);
-        casts.arg("x").asDoubleVector(true, true, true);
+        casts.arg("x").mustNotBeMissing().mustNotBeNull().asDoubleVector(true, true, true);
         casts.arg("n").asIntegerVector().findFirst();
         casts.arg("p").asIntegerVector().findFirst();
-        casts.arg("y").asDoubleVector(true, true, true);
+        casts.arg("y").mustNotBeMissing().mustNotBeNull().asDoubleVector(true, true, true);
         casts.arg("ny").asIntegerVector().findFirst();
         casts.arg("tol").asDoubleVector().findFirst();
-        casts.arg("coeff").asDoubleVector(true, true, true);
+        casts.arg("coeff").mustNotBeMissing().mustNotBeNull().asDoubleVector(true, true, true);
 
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
index 745cb3980a..79d3635e48 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
@@ -182,11 +182,6 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
         return ret;
     }
 
-    @Specialization
-    protected RArgsValuesAndNames doArgsValueAndNames(RArgsValuesAndNames values) {
-        return values;
-    }
-
     @Specialization
     protected RMissing doMissing(RMissing missing) {
         return missing;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index e31111eb6f..8583792a6f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -320,7 +320,7 @@ public final class RError extends RuntimeException {
         MUST_BE_POSITIVE_INT("'%s' must be a positive integer"),
         MUST_BE_POSITIVE_SD("%s must be non-negative number"),
         MUST_BE_SQUARE("'%s' (%d x %d) must be square"),
-        MUST_BE_SQUARE_COMPATIBLE("'%s' (%d x %d) must be compatible with '%' (%d x %d)"),
+        MUST_BE_SQUARE_COMPATIBLE("'%s' (%d x %d) must be compatible with '%s' (%d x %d)"),
         INVALID_TFB_SD("invalid (to - from)/by in seq(.)"),
         INVALID_TFB("invalid '(to - from)/by' in 'seq'"),
         WRONG_SIGN_IN_BY("wrong sign in 'by' argument"),
-- 
GitLab


From b4ac6b59736d8bce21170962d193097045d3511f Mon Sep 17 00:00:00 2001
From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com>
Date: Wed, 17 May 2017 16:17:41 +0200
Subject: [PATCH 376/402] The rbdiag tool exists with a non-zero status if a
 cast-pipeline related warning is issued during validation of a builtin

---
 ci.hocon                                      |  2 +-
 .../truffle/r/nodes/test/ChimneySweeping.java |  8 +++-
 .../r/nodes/test/RBuiltinDiagnostics.java     | 39 +++++++++++++++----
 3 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/ci.hocon b/ci.hocon
index ff92a88670..9e85b47df5 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -148,7 +148,7 @@ rbcheck : ${common} {
   run : [
     ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac"]
     ["mx", "rbcheck"]
-    ["mx", "rbdiag", "-n", "-m"]
+    ["mx", "rbdiag"]
   ]
 }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
index 4214170ebf..809bf71bde 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
@@ -236,7 +236,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
     }
 
     @Override
-    public void diagnoseBuiltin() throws Exception {
+    public boolean diagnoseBuiltin() throws Exception {
         // super.diagnoseBuiltin();
 
         if (blacklistedBuiltins.contains(builtinName)) {
@@ -244,10 +244,12 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
         } else {
             sweepChimney();
         }
+
+        return true;
     }
 
     @Override
-    protected void diagnosePipeline(int i) {
+    protected boolean diagnosePipeline(int i) {
         super.diagnosePipeline(i);
 
         print(1, " Samples:");
@@ -256,6 +258,8 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
         if (diagSuite.diagConfig.performPipelineSelfTest) {
             checkPipelines(i);
         }
+
+        return true;
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index 2ab3ac955a..2fce7678ee 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -145,12 +145,13 @@ public class RBuiltinDiagnostics {
 
         boolean ok = true;
         try {
-            diag.init().diagnoseBuiltin();
+            ok = diag.init().diagnoseBuiltin();
 
             print(1, "Finished");
             print(1, "--------");
         } catch (WarningException e) {
             diag.print(0, "Warning: " + e.getMessage());
+            ok = false;
         } catch (InfoException e) {
             print(0, e.getMessage());
         } catch (Throwable e) {
@@ -178,6 +179,7 @@ public class RBuiltinDiagnostics {
                 diag = createBuiltinDiagnostics(new RIntBuiltinDiagFactory((bf)));
             } catch (WarningException e) {
                 print(0, "Warning: " + e.getMessage());
+                ok = false;
                 continue;
             } catch (InfoException e) {
                 print(1, e.getMessage());
@@ -186,12 +188,14 @@ public class RBuiltinDiagnostics {
                 errCounter++;
                 print(0, "Error in initialization of builtin " + bf.getName());
                 t.printStackTrace();
+                ok = false;
                 continue;
             }
             try {
-                diag.init().diagnoseBuiltin();
+                ok &= diag.init().diagnoseBuiltin();
             } catch (WarningException e) {
                 diag.print(0, "Warning: " + e.getMessage());
+                ok = false;
             } catch (InfoException e) {
                 diag.print(1, e.getMessage());
             } catch (Throwable t) {
@@ -209,6 +213,7 @@ public class RBuiltinDiagnostics {
                 diag = createBuiltinDiagnostics(RExtBuiltinDiagFactory.create(extBltCls));
             } catch (WarningException e) {
                 print(0, "Warning: " + e.getMessage());
+                ok = false;
                 continue;
             } catch (InfoException e) {
                 print(1, e.getMessage());
@@ -217,12 +222,14 @@ public class RBuiltinDiagnostics {
                 errCounter++;
                 print(0, "Error in initialization of " + extBltCls.getName() + " builtin");
                 t.printStackTrace();
+                ok = false;
                 continue;
             }
             try {
-                diag.init().diagnoseBuiltin();
+                ok &= diag.init().diagnoseBuiltin();
             } catch (WarningException e) {
                 diag.print(0, "Warning: " + e.getMessage());
+                ok = false;
             } catch (InfoException e) {
                 diag.print(1, e.getMessage());
             } catch (Throwable t) {
@@ -230,6 +237,7 @@ public class RBuiltinDiagnostics {
                 ok = false;
                 diag.print(0, "");
                 t.printStackTrace();
+                ok = false;
             }
         }
 
@@ -422,15 +430,19 @@ public class RBuiltinDiagnostics {
             return nonCovered;
         }
 
-        public void diagnoseBuiltin() throws Exception {
+        public boolean diagnoseBuiltin() throws Exception {
+            boolean ok = true;
+
             print(1, "Argument cast pipelines binding:");
             for (int i = 0; i < argLength; i++) {
-                diagnosePipeline(i);
+                ok &= diagnosePipeline(i);
             }
 
             print(1, "\nUnhandled argument combinations: " + nonCoveredArgsSet.size());
             print(1, "");
 
+            nonCoveredArgsSet.isEmpty();
+
             if (diagSuite.diagConfig.verbose) {
                 for (List<Type> uncoveredArgs : nonCoveredArgsSet) {
                     print(1, uncoveredArgs.stream().map(t -> typeName(t)).collect(Collectors.toList()));
@@ -438,7 +450,9 @@ public class RBuiltinDiagnostics {
             }
             print(1, "");
 
-            printDeadSpecs();
+            ok &= printDeadSpecs();
+
+            return ok;
         }
 
         private void printBuiltinHeader(int level) {
@@ -452,7 +466,8 @@ public class RBuiltinDiagnostics {
             }
         }
 
-        private void printDeadSpecs() {
+        private boolean printDeadSpecs() {
+            boolean ok = true;
             StringBuilder sb = new StringBuilder();
             int deadSpecCnt = 0;
             for (Map.Entry<Method, List<Set<Cast>>> resTpPerSpec : convResultTypePerSpec.entrySet()) {
@@ -471,13 +486,19 @@ public class RBuiltinDiagnostics {
                 }
             }
 
+            ok = deadSpecCnt == 0;
+
             int logLev = deadSpecCnt == 0 ? 1 : 0;
             String msg = deadSpecCnt == 0 ? "Dead specializations: " + deadSpecCnt : "Warning: Dead specializations: " + deadSpecCnt;
             print(logLev, msg);
             print(logLev, sb.toString());
+
+            return ok;
         }
 
-        protected void diagnosePipeline(int i) {
+        protected boolean diagnosePipeline(int i) {
+            boolean ok = true;
+
             TypeExpr argResultSet = argResultSets.get(i);
 
             String pipelineHeader = "Pipeline for '" + parameterNames[i] + "' (arg[" + i + "])";
@@ -501,11 +522,13 @@ public class RBuiltinDiagnostics {
             if (unboundArgTypes.isEmpty()) {
                 print(1, pipelineHeader);
             } else {
+                ok = false;
                 print(0, "Warning: " + pipelineHeader);
                 print(0, "   Unbound types: " + unboundArgTypes.stream().map(argType -> typeName(argType)).collect(Collectors.toSet()));
             }
             print(1, sb.toString());
 
+            return ok;
         }
 
         private List<TypeExpr> createArgResultSets() {
-- 
GitLab


From 28b37c8f2fac66954d2b451cbb21aa76650a8e91 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 12 May 2017 12:06:51 +0200
Subject: [PATCH 377/402] Implemented RScope: An abstract variable scope for
 external tools.

---
 .../truffle/r/runtime/data/RLanguage.java     |  11 +-
 .../oracle/truffle/r/runtime/env/RScope.java  | 244 ++++++++++++++++++
 2 files changed, 254 insertions(+), 1 deletion(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index ed06179415..f3e654297b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -24,12 +24,16 @@ package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.metadata.ScopeProvider;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.env.RScope;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
@@ -47,7 +51,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  *
  */
 @ValueType
-public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
+public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer, ScopeProvider<RContext> {
 
     /*
      * Used for RLanguage construction from separate AST components.
@@ -265,4 +269,9 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
     private void setNamesOnPairList(RStringVector names) {
         list.setNames(names);
     }
+
+    @Override
+    public AbstractScope findScope(RContext langContext, Node node, Frame frame) {
+        return RScope.createScope(node);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
new file mode 100644
index 0000000000..d8f58f0c59
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -0,0 +1,244 @@
+package com.oracle.truffle.r.runtime.env;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.FrameInstance;
+import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.metadata.ScopeProvider.AbstractScope;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RArguments;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.VirtualEvalFrame;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
+
+/**
+ * Represents a variable scope for external tools like a debugger.<br>
+ * This is basically a view on R environments.
+ */
+public class RScope extends AbstractScope {
+
+    private final Node current;
+    private REnvironment env;
+
+    /**
+     * Intended to be used when creating a parent scope where we do not know any associated node.
+     */
+    private RScope(REnvironment env) {
+        this.env = env;
+        this.current = null;
+    }
+
+    private RScope(Node current, REnvironment env) {
+        this.current = current;
+        this.env = env;
+    }
+
+    @Override
+    protected String getName() {
+        // TODO
+        return "function";
+    }
+
+    @Override
+    protected Node getNode() {
+        return current;
+    }
+
+    @Override
+    protected Object getVariables(Frame frame) {
+        return new VariablesMapObject(collectVars(), collectArgs(), env);
+    }
+
+    private static MaterializedFrame getCallerFrame(Frame frame) {
+
+        MaterializedFrame funFrame = RArguments.getCallerFrame(frame);
+        if (funFrame == null) {
+            Frame callerFrame = Utils.getCallerFrame(frame, FrameInstance.FrameAccess.MATERIALIZE);
+            if (callerFrame != null) {
+                return callerFrame.materialize();
+            } else {
+                // S3 method can be dispatched from top-level where there is no caller frame
+                return frame.materialize();
+            }
+        }
+        return funFrame;
+    }
+
+    private static REnvironment getEnv(Frame frame) {
+        // TODO deopt frame
+// PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode();
+
+        MaterializedFrame matFrame = getCallerFrame(frame);
+        matFrame = matFrame instanceof VirtualEvalFrame ? ((VirtualEvalFrame) matFrame).getOriginalFrame() : matFrame;
+// deoptFrameNode.deoptimizeFrame(matFrame);
+        return REnvironment.frameToEnvironment(matFrame);
+    }
+
+    @Override
+    protected Object getArguments(Frame frame) {
+        return new VariablesMapObject(collectVars(), collectArgs(), env);
+    }
+
+    @Override
+    protected AbstractScope findParent() {
+        if (this.env == REnvironment.emptyEnv()) {
+            return null;
+        }
+
+        return new RScope(env.getParent());
+    }
+
+    private String[] collectVars() {
+        RStringVector ls = env.ls(true, null, false);
+        return ls.getDataWithoutCopying();
+    }
+
+    private String[] collectArgs() {
+        ArgumentsSignature signature = RArguments.getSignature(env.getFrame());
+        return signature.getNames();
+    }
+
+    public static RScope createScope(Node node, Frame frame) {
+        return new RScope(node, getEnv(frame));
+    }
+
+    private static Object getInteropValue(Object value) {
+        return value;
+    }
+
+    static final class VariablesMapObject implements TruffleObject {
+
+        final String[] identifiers;
+        final String[] args;
+        final REnvironment frame;
+
+        private VariablesMapObject(String[] identifiers, String[] args, REnvironment frame) {
+            this.identifiers = identifiers;
+            this.args = args;
+            this.frame = frame;
+        }
+
+        @Override
+        public ForeignAccess getForeignAccess() {
+            return VariablesMapMessageResolutionForeign.ACCESS;
+        }
+
+        public static boolean isInstance(TruffleObject obj) {
+            return obj instanceof VariablesMapObject;
+        }
+
+        @MessageResolution(receiverType = VariablesMapObject.class)
+        static final class VariablesMapMessageResolution {
+
+            @Resolve(message = "KEYS")
+            abstract static class VarsMapKeysNode extends Node {
+
+                @TruffleBoundary
+                public Object access(VariablesMapObject varMap) {
+                    return new VariableNamesObject(varMap.identifiers);
+                }
+            }
+
+            @Resolve(message = "READ")
+            abstract static class VarsMapReadNode extends Node {
+
+                @TruffleBoundary
+                public Object access(VariablesMapObject varMap, String name) {
+                    if (varMap.frame == null) {
+                        throw UnsupportedMessageException.raise(Message.READ);
+                    }
+                    Object value = varMap.frame.get(name);
+
+                    // If Java-null is returned, the identifier does not exist !
+                    if (value == null) {
+                        throw UnknownIdentifierException.raise(name);
+                    } else {
+                        return getInteropValue(value);
+                    }
+                }
+            }
+
+            @Resolve(message = "WRITE")
+            abstract static class VarsMapWriteNode extends Node {
+
+                @TruffleBoundary
+                public Object access(VariablesMapObject varMap, String name, Object value) {
+                    if (varMap.frame == null) {
+                        throw UnsupportedMessageException.raise(Message.WRITE);
+                    }
+                    try {
+                        varMap.frame.put(name, value);
+                        return value;
+                    } catch (PutException e) {
+                        throw RInternalError.shouldNotReachHere(e);
+                    }
+                }
+            }
+
+        }
+    }
+
+    static final class VariableNamesObject implements TruffleObject {
+
+        final String[] names;
+
+        private VariableNamesObject(String[] names) {
+            this.names = names;
+        }
+
+        @Override
+        public ForeignAccess getForeignAccess() {
+            return VariableNamesMessageResolutionForeign.ACCESS;
+        }
+
+        public static boolean isInstance(TruffleObject obj) {
+            return obj instanceof VariableNamesObject;
+        }
+
+        @MessageResolution(receiverType = VariableNamesObject.class)
+        static final class VariableNamesMessageResolution {
+
+            @Resolve(message = "HAS_SIZE")
+            abstract static class VarNamesHasSizeNode extends Node {
+
+                @SuppressWarnings("unused")
+                public Object access(VariableNamesObject varNames) {
+                    return true;
+                }
+            }
+
+            @Resolve(message = "GET_SIZE")
+            abstract static class VarNamesGetSizeNode extends Node {
+
+                public Object access(VariableNamesObject varNames) {
+                    return varNames.names.length;
+                }
+            }
+
+            @Resolve(message = "READ")
+            abstract static class VarNamesReadNode extends Node {
+
+                @TruffleBoundary
+                public Object access(VariableNamesObject varNames, int index) {
+                    if (index >= 0 && index < varNames.names.length) {
+                        return varNames.names[index];
+                    } else {
+                        throw UnknownIdentifierException.raise(Integer.toString(index));
+                    }
+                }
+            }
+
+        }
+    }
+
+}
-- 
GitLab


From b19d776a7d5e87800d8afa308c18143f8abf9803 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Fri, 12 May 2017 12:51:18 +0200
Subject: [PATCH 378/402] Modified scope to always query a fresh list of
 variables since they may change on each single debugging step.

---
 .../truffle/r/runtime/data/RLanguage.java     |   2 +-
 .../oracle/truffle/r/runtime/env/RScope.java  | 142 +++++++++++++++---
 2 files changed, 122 insertions(+), 22 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index f3e654297b..669dec8e58 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -272,6 +272,6 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
 
     @Override
     public AbstractScope findScope(RContext langContext, Node node, Frame frame) {
-        return RScope.createScope(node);
+        return RScope.createScope(node, frame);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index d8f58f0c59..7f544c3b3e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package com.oracle.truffle.r.runtime.env;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -18,6 +40,7 @@ import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.VirtualEvalFrame;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 
@@ -25,7 +48,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
  * Represents a variable scope for external tools like a debugger.<br>
  * This is basically a view on R environments.
  */
-public class RScope extends AbstractScope {
+public final class RScope extends AbstractScope {
 
     private final Node current;
     private REnvironment env;
@@ -56,7 +79,7 @@ public class RScope extends AbstractScope {
 
     @Override
     protected Object getVariables(Frame frame) {
-        return new VariablesMapObject(collectVars(), collectArgs(), env);
+        return new VariablesMapObject(env, false);
     }
 
     private static MaterializedFrame getCallerFrame(Frame frame) {
@@ -86,7 +109,7 @@ public class RScope extends AbstractScope {
 
     @Override
     protected Object getArguments(Frame frame) {
-        return new VariablesMapObject(collectVars(), collectArgs(), env);
+        return new VariablesMapObject(env, true);
     }
 
     @Override
@@ -98,12 +121,12 @@ public class RScope extends AbstractScope {
         return new RScope(env.getParent());
     }
 
-    private String[] collectVars() {
+    private static String[] ls(REnvironment env) {
         RStringVector ls = env.ls(true, null, false);
         return ls.getDataWithoutCopying();
     }
 
-    private String[] collectArgs() {
+    private static String[] collectArgs(REnvironment env) {
         ArgumentsSignature signature = RArguments.getSignature(env.getFrame());
         return signature.getNames();
     }
@@ -118,14 +141,12 @@ public class RScope extends AbstractScope {
 
     static final class VariablesMapObject implements TruffleObject {
 
-        final String[] identifiers;
-        final String[] args;
-        final REnvironment frame;
+        private final REnvironment env;
+        private final boolean argumentsOnly;
 
-        private VariablesMapObject(String[] identifiers, String[] args, REnvironment frame) {
-            this.identifiers = identifiers;
-            this.args = args;
-            this.frame = frame;
+        private VariablesMapObject(REnvironment env, boolean argumentsOnly) {
+            this.env = env;
+            this.argumentsOnly = argumentsOnly;
         }
 
         @Override
@@ -145,7 +166,32 @@ public class RScope extends AbstractScope {
 
                 @TruffleBoundary
                 public Object access(VariablesMapObject varMap) {
-                    return new VariableNamesObject(varMap.identifiers);
+                    if (varMap.argumentsOnly) {
+                        return new ArgumentNamesObject(collectArgs(varMap.env));
+                    } else {
+                        return new VariableNamesObject(varMap.env);
+                    }
+                }
+            }
+
+            @Resolve(message = "KEY_INFO")
+            public abstract static class VarMapsKeyInfoNode extends Node {
+
+                private static final int READABLE = 1 << 1;
+                private static final int WRITABLE = 1 << 2;
+                private static final int INVOCABLE = 1 << 3;
+
+                @SuppressWarnings("try")
+                protected Object access(VariablesMapObject receiver, String identifier) {
+                    int info = READABLE;
+
+                    if (!receiver.env.bindingIsLocked(identifier)) {
+                        info += WRITABLE;
+                    }
+                    if (receiver.env.get(identifier) instanceof RFunction) {
+                        info += INVOCABLE;
+                    }
+                    return info;
                 }
             }
 
@@ -154,10 +200,10 @@ public class RScope extends AbstractScope {
 
                 @TruffleBoundary
                 public Object access(VariablesMapObject varMap, String name) {
-                    if (varMap.frame == null) {
+                    if (varMap.env == null) {
                         throw UnsupportedMessageException.raise(Message.READ);
                     }
-                    Object value = varMap.frame.get(name);
+                    Object value = varMap.env.get(name);
 
                     // If Java-null is returned, the identifier does not exist !
                     if (value == null) {
@@ -173,11 +219,11 @@ public class RScope extends AbstractScope {
 
                 @TruffleBoundary
                 public Object access(VariablesMapObject varMap, String name, Object value) {
-                    if (varMap.frame == null) {
+                    if (varMap.env == null) {
                         throw UnsupportedMessageException.raise(Message.WRITE);
                     }
                     try {
-                        varMap.frame.put(name, value);
+                        varMap.env.put(name, value);
                         return value;
                     } catch (PutException e) {
                         throw RInternalError.shouldNotReachHere(e);
@@ -190,10 +236,10 @@ public class RScope extends AbstractScope {
 
     static final class VariableNamesObject implements TruffleObject {
 
-        final String[] names;
+        private final REnvironment env;
 
-        private VariableNamesObject(String[] names) {
-            this.names = names;
+        private VariableNamesObject(REnvironment env) {
+            this.env = env;
         }
 
         @Override
@@ -221,7 +267,7 @@ public class RScope extends AbstractScope {
             abstract static class VarNamesGetSizeNode extends Node {
 
                 public Object access(VariableNamesObject varNames) {
-                    return varNames.names.length;
+                    return ls(varNames.env).length;
                 }
             }
 
@@ -230,6 +276,60 @@ public class RScope extends AbstractScope {
 
                 @TruffleBoundary
                 public Object access(VariableNamesObject varNames, int index) {
+                    String[] names = ls(varNames.env);
+                    if (index >= 0 && index < names.length) {
+                        return names[index];
+                    } else {
+                        throw UnknownIdentifierException.raise(Integer.toString(index));
+                    }
+                }
+            }
+
+        }
+    }
+
+    static final class ArgumentNamesObject implements TruffleObject {
+
+        private final String[] names;
+
+        private ArgumentNamesObject(String[] names) {
+            this.names = names;
+        }
+
+        @Override
+        public ForeignAccess getForeignAccess() {
+            return VariableNamesMessageResolutionForeign.ACCESS;
+        }
+
+        public static boolean isInstance(TruffleObject obj) {
+            return obj instanceof ArgumentNamesObject;
+        }
+
+        @MessageResolution(receiverType = ArgumentNamesObject.class)
+        static final class ArgumentNamesMessageResolution {
+
+            @Resolve(message = "HAS_SIZE")
+            abstract static class ArgNamesHasSizeNode extends Node {
+
+                @SuppressWarnings("unused")
+                public Object access(ArgumentNamesObject varNames) {
+                    return true;
+                }
+            }
+
+            @Resolve(message = "GET_SIZE")
+            abstract static class ArgNamesGetSizeNode extends Node {
+
+                public Object access(ArgumentNamesObject varNames) {
+                    return varNames.names.length;
+                }
+            }
+
+            @Resolve(message = "READ")
+            abstract static class ArgNamesReadNode extends Node {
+
+                @TruffleBoundary
+                public Object access(ArgumentNamesObject varNames, int index) {
                     if (index >= 0 && index < varNames.names.length) {
                         return varNames.names[index];
                     } else {
-- 
GitLab


From 0c42b2ffb98296122f95ef4cdf64287ea6c8626e Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 17 May 2017 09:45:34 +0200
Subject: [PATCH 379/402] Moved method 'findScope' to TruffleRLanguage.

---
 .../com/oracle/truffle/r/engine/TruffleRLanguage.java  | 10 +++++++++-
 .../com/oracle/truffle/r/runtime/data/RLanguage.java   |  7 +------
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index 6c98e3dd2b..7b91b6f224 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -28,11 +28,13 @@ import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
 import com.oracle.truffle.api.instrumentation.ProvidedTags;
 import com.oracle.truffle.api.instrumentation.StandardTags;
+import com.oracle.truffle.api.metadata.ScopeProvider;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.SourceSection;
@@ -54,6 +56,7 @@ import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.env.RScope;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -63,7 +66,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  */
 @TruffleLanguage.Registration(name = "R", version = "0.1", mimeType = {RRuntime.R_APP_MIME, RRuntime.R_TEXT_MIME}, interactive = true)
 @ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, RSyntaxTags.LoopTag.class})
-public final class TruffleRLanguage extends TruffleLanguage<RContext> {
+public final class TruffleRLanguage extends TruffleLanguage<RContext> implements ScopeProvider<RContext> {
 
     /**
      * The choice of {@link RFFIFactory} is made statically so that it is bound into an AOT-compiled
@@ -242,4 +245,9 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
     public RContext actuallyFindContext0(Node contextNode) {
         return findContext(contextNode);
     }
+
+    @Override
+    public AbstractScope findScope(RContext langContext, Node node, Frame frame) {
+        return RScope.createScope(node, frame);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index 669dec8e58..8db4b041c0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -51,7 +51,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  *
  */
 @ValueType
-public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer, ScopeProvider<RContext> {
+public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
 
     /*
      * Used for RLanguage construction from separate AST components.
@@ -269,9 +269,4 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
     private void setNamesOnPairList(RStringVector names) {
         list.setNames(names);
     }
-
-    @Override
-    public AbstractScope findScope(RContext langContext, Node node, Frame frame) {
-        return RScope.createScope(node, frame);
-    }
 }
-- 
GitLab


From d0ae301e0eda4ea090f2020444367031cb957401 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 17 May 2017 09:46:12 +0200
Subject: [PATCH 380/402] Fix: Creating scope for root nodes only.

---
 .../src/com/oracle/truffle/r/runtime/env/RScope.java            | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index 7f544c3b3e..5441086a31 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -132,7 +132,7 @@ public final class RScope extends AbstractScope {
     }
 
     public static RScope createScope(Node node, Frame frame) {
-        return new RScope(node, getEnv(frame));
+        return new RScope(node.getRootNode(), getEnv(frame));
     }
 
     private static Object getInteropValue(Object value) {
-- 
GitLab


From fc4bcc14ed6321d48e7707de33e0c4461dd846f3 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 17 May 2017 11:59:42 +0200
Subject: [PATCH 381/402] Fix: Now using right frame for the scope and the
 right node. Also added a debug test.

---
 .../oracle/truffle/r/runtime/env/RScope.java  | 30 ++-----------
 .../truffle/r/test/tck/FastRDebugTest.java    | 44 ++++++++++++++++++-
 2 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index 5441086a31..ced4f106a5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -24,8 +24,6 @@ package com.oracle.truffle.r.runtime.env;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
-import com.oracle.truffle.api.frame.FrameInstance;
-import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.MessageResolution;
@@ -38,8 +36,6 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.VirtualEvalFrame;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
@@ -68,7 +64,7 @@ public final class RScope extends AbstractScope {
 
     @Override
     protected String getName() {
-        // TODO
+        // TODO promises (= closure)
         return "function";
     }
 
@@ -82,29 +78,9 @@ public final class RScope extends AbstractScope {
         return new VariablesMapObject(env, false);
     }
 
-    private static MaterializedFrame getCallerFrame(Frame frame) {
-
-        MaterializedFrame funFrame = RArguments.getCallerFrame(frame);
-        if (funFrame == null) {
-            Frame callerFrame = Utils.getCallerFrame(frame, FrameInstance.FrameAccess.MATERIALIZE);
-            if (callerFrame != null) {
-                return callerFrame.materialize();
-            } else {
-                // S3 method can be dispatched from top-level where there is no caller frame
-                return frame.materialize();
-            }
-        }
-        return funFrame;
-    }
-
     private static REnvironment getEnv(Frame frame) {
-        // TODO deopt frame
-// PromiseDeoptimizeFrameNode deoptFrameNode = new PromiseDeoptimizeFrameNode();
-
-        MaterializedFrame matFrame = getCallerFrame(frame);
-        matFrame = matFrame instanceof VirtualEvalFrame ? ((VirtualEvalFrame) matFrame).getOriginalFrame() : matFrame;
-// deoptFrameNode.deoptimizeFrame(matFrame);
-        return REnvironment.frameToEnvironment(matFrame);
+        assert RArguments.isRFrame(frame);
+        return REnvironment.frameToEnvironment(frame.materialize());
     }
 
     @Override
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 5edb60b06f..27cc0eaa2b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -38,6 +38,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import com.oracle.truffle.api.debug.Breakpoint;
+import com.oracle.truffle.api.debug.DebugScope;
 import com.oracle.truffle.api.debug.DebugStackFrame;
 import com.oracle.truffle.api.debug.DebugValue;
 import com.oracle.truffle.api.debug.Debugger;
@@ -230,6 +231,42 @@ public class FastRDebugTest {
         assertExecutedOK();
     }
 
+    @Test
+    public void testScope() throws Throwable {
+        final Source srcFunMain = RSource.fromTextInternal("function () {\n" +
+                        "    i = 3L\n" +
+                        "    n = 15\n" +
+                        "    str = \"hello\"\n" +
+                        "    i <- i + 1L\n" +
+                        "    ab <<- i\n" +
+                        "    i\n" +
+                        "}", RSource.Internal.DEBUGTEST_DEBUG);
+        final Source source = RSource.fromTextInternal("x <- 10L\n" +
+                        "makeActiveBinding('ab', function(v) { if(missing(v)) x else x <<- v }, .GlobalEnv)\n" +
+                        "main <- " + srcFunMain.getCode() + "\n",
+                        RSource.Internal.DEBUGTEST_DEBUG);
+        engine.eval(source);
+
+        // @formatter:on
+        run.addLast(() -> {
+            assertNull(suspendedEvent);
+            assertNotNull(debuggerSession);
+            debuggerSession.suspendNextExecution();
+        });
+
+        assertLocation(1, "main()", "x", 10, "ab", 10, "main", srcFunMain.getCode());
+        stepInto(1);
+        assertLocation(4, "i = 3L");
+        stepOut();
+        assertLocation(1, "main()", "x", 4, "ab", 4, "main", srcFunMain.getCode());
+        performWork();
+
+        final Source evalSource = RSource.fromTextInternal("main()\n", RSource.Internal.DEBUGTEST_EVAL);
+        engine.eval(evalSource);
+
+        assertExecutedOK();
+    }
+
     private void performWork() {
         try {
             if (ex == null && !run.isEmpty()) {
@@ -279,17 +316,20 @@ public class FastRDebugTest {
                 });
                 assertEquals(line + ": " + code, expectedFrame.length / 2, numFrameVars.get());
 
+                DebugScope scope = frame.getScope();
                 for (int i = 0; i < expectedFrame.length; i = i + 2) {
                     String expectedIdentifier = (String) expectedFrame[i];
                     Object expectedValue = expectedFrame[i + 1];
                     String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null;
-                    DebugValue value = frame.getValue(expectedIdentifier);
+                    DebugValue value = scope.getDeclaredValue(expectedIdentifier);
                     assertNotNull(value);
                     String valueStr = value.as(String.class);
                     assertEquals(expectedValueStr, valueStr);
                 }
 
-                run.removeFirst().run();
+                if (!run.isEmpty()) {
+                    run.removeFirst().run();
+                }
             } catch (RuntimeException | Error e) {
 
                 final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
-- 
GitLab


From 6df8808a66db6372f0d55d1774b46d76a2058ca5 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 17 May 2017 17:10:43 +0200
Subject: [PATCH 382/402] Modified/added debug test to specifically test the
 RScope methods.

---
 .../truffle/r/runtime/data/RLanguage.java     |   4 -
 .../truffle/r/test/tck/FastRDebugTest.java    | 211 +++++++++++++++---
 2 files changed, 184 insertions(+), 31 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index 8db4b041c0..ed06179415 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -24,16 +24,12 @@ package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
-import com.oracle.truffle.api.frame.Frame;
-import com.oracle.truffle.api.metadata.ScopeProvider;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.env.RScope;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 27cc0eaa2b..cf4d6207f5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -29,7 +29,9 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.HashSet;
 import java.util.LinkedList;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.junit.After;
@@ -55,6 +57,7 @@ import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
 
 public class FastRDebugTest {
@@ -232,10 +235,10 @@ public class FastRDebugTest {
     }
 
     @Test
-    public void testScope() throws Throwable {
+    public void testScopeFunction() throws Throwable {
         final Source srcFunMain = RSource.fromTextInternal("function () {\n" +
                         "    i = 3L\n" +
-                        "    n = 15\n" +
+                        "    n = 15L\n" +
                         "    str = \"hello\"\n" +
                         "    i <- i + 1L\n" +
                         "    ab <<- i\n" +
@@ -257,6 +260,16 @@ public class FastRDebugTest {
         assertLocation(1, "main()", "x", 10, "ab", 10, "main", srcFunMain.getCode());
         stepInto(1);
         assertLocation(4, "i = 3L");
+        stepOver(1);
+        assertLocation(5, "n = 15L", "i", 3);
+        stepOver(1);
+        assertLocation(6, "str = \"hello\"", "i", 3, "n", 15);
+        stepOver(1);
+        assertLocation(7, "i <- i + 1L", "i", 3, "n", 15, "str", "hello");
+        stepOver(1);
+        assertLocation(8, "ab <<- i", "i", 4, "n", 15, "str", "hello");
+        stepOver(1);
+        assertScope(9, "i", true, false, "ab", 4, "x", 4);
         stepOut();
         assertLocation(1, "main()", "x", 4, "ab", 4, "main", srcFunMain.getCode());
         performWork();
@@ -267,6 +280,90 @@ public class FastRDebugTest {
         assertExecutedOK();
     }
 
+    @Test
+    public void testScopePromise() throws Throwable {
+        final Source source = RSource.fromTextInternal("main <- function(e) {\n" +
+                        "   x <- 10L\n" +
+                        "   e()\n" +
+                        "   x\n" +
+                        "}\n" +
+                        "closure <- function() {\n" +
+                        "   x <<- 123L\n" +
+                        "   x\n" +
+                        "}\n",
+
+                        RSource.Internal.DEBUGTEST_DEBUG);
+        engine.eval(source);
+
+        // @formatter:on
+        run.addLast(() -> {
+            assertNull(suspendedEvent);
+            assertNotNull(debuggerSession);
+            debuggerSession.suspendNextExecution();
+        });
+
+        stepOver(1);
+        stepInto(1);
+        stepOver(1);
+        assertScope(3, "e()", false, false, "x", 10);
+        stepInto(1);
+        assertLocation(7, "x <<- 123L");
+        assertScope(7, "x <<- 123L", true, false, "x", 0);
+        stepOver(1);
+        assertScope(8, "x", true, false, "x", 123);
+        continueExecution();
+        performWork();
+
+        final Source evalSource = RSource.fromTextInternal("x <- 0L\nmain(closure)\n", RSource.Internal.DEBUGTEST_EVAL);
+        engine.eval(evalSource);
+
+        assertExecutedOK();
+    }
+
+    @Test
+    public void testChangedScopeChain() throws Throwable {
+        final Source source = RSource.fromTextInternal("main <- function(e) {\n" +
+                        "   x <- 10L\n" +
+                        "   environment(e) <- environment()\n" +
+                        "   e()\n" +
+                        "   x\n" +
+                        "}\n" +
+                        "closure <- function() {\n" +
+                        "   x <<- 123L\n" +
+                        "   x\n" +
+                        "}\n",
+                        RSource.Internal.DEBUGTEST_DEBUG);
+        engine.eval(source);
+
+        // @formatter:on
+        run.addLast(() -> {
+            assertNull(suspendedEvent);
+            assertNotNull(debuggerSession);
+            debuggerSession.suspendNextExecution();
+        });
+
+        stepOver(1);
+        stepInto(1);
+        stepOver(2);
+        assertScope(4, "e()", false, false, "x", 10);
+        stepInto(1);
+        assertLocation(8, "x <<- 123L");
+        assertScope(8, "x <<- 123L", true, false, "x", 10);
+        stepOver(1);
+        stepOut();
+        assertScope(9, "x", false, false, "x", 123);
+        assertIdentifiers(false, "x", "e");
+        stepOut();
+        assertScope(9, "x", false, false, "x", 0);
+        continueExecution();
+        performWork();
+
+        final Source evalSource = RSource.fromTextInternal("x <- 0L\nmain(closure)\n", RSource.Internal.DEBUGTEST_EVAL);
+        engine.eval(evalSource);
+
+        assertExecutedOK();
+    }
+
     private void performWork() {
         try {
             if (ex == null && !run.isEmpty()) {
@@ -283,7 +380,7 @@ public class FastRDebugTest {
     }
 
     private void stepOut() {
-        run.addLast(() -> suspendedEvent.prepareStepOut());
+        run.addLast(() -> suspendedEvent.prepareStepOut(1));
     }
 
     private void continueExecution() {
@@ -294,6 +391,30 @@ public class FastRDebugTest {
         run.addLast(() -> suspendedEvent.prepareStepInto(size));
     }
 
+    private void assertIdentifiers(boolean includeAncestors, String... identifiers) {
+        run.addLast(() -> {
+
+            final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+            DebugScope scope = frame.getScope();
+
+            Set<String> actualIdentifiers = new HashSet<>();
+            do {
+                scope.getDeclaredValues().forEach((x) -> actualIdentifiers.add(x.getName()));
+            } while (includeAncestors && scope != null && !REnvironment.baseEnv().getName().equals(scope.getName()));
+
+            Set<String> expected = new HashSet<>();
+            for (String s : identifiers) {
+                expected.add(s);
+            }
+
+            assertEquals(expected, actualIdentifiers);
+
+            if (!run.isEmpty()) {
+                run.removeFirst().run();
+            }
+        });
+    }
+
     private void assertLocation(final int line, final String code, final Object... expectedFrame) {
         run.addLast(() -> {
             try {
@@ -302,34 +423,33 @@ public class FastRDebugTest {
                 assertEquals(line, currentLine);
                 final String currentCode = suspendedEvent.getSourceSection().getCode().trim();
                 assertEquals(code, currentCode);
-                final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+                compareScope(line, code, false, true, expectedFrame);
+            } catch (RuntimeException | Error e) {
 
-                final AtomicInteger numFrameVars = new AtomicInteger(0);
+                final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
                 frame.forEach(var -> {
-                    // skip synthetic slots
-                    for (RFrameSlot slot : RFrameSlot.values()) {
-                        if (slot.toString().equals(var.getName())) {
-                            return;
-                        }
-                    }
-                    numFrameVars.incrementAndGet();
+                    System.out.println(var);
                 });
-                assertEquals(line + ": " + code, expectedFrame.length / 2, numFrameVars.get());
-
-                DebugScope scope = frame.getScope();
-                for (int i = 0; i < expectedFrame.length; i = i + 2) {
-                    String expectedIdentifier = (String) expectedFrame[i];
-                    Object expectedValue = expectedFrame[i + 1];
-                    String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null;
-                    DebugValue value = scope.getDeclaredValue(expectedIdentifier);
-                    assertNotNull(value);
-                    String valueStr = value.as(String.class);
-                    assertEquals(expectedValueStr, valueStr);
-                }
+                throw e;
+            }
+        });
+    }
 
-                if (!run.isEmpty()) {
-                    run.removeFirst().run();
-                }
+    /**
+     * Ensure that the scope at a certain program position contains an expected set of key-value
+     * pairs.
+     *
+     * @param line line number
+     * @param code the code snippet of the program location
+     * @param includeAncestors Include current scope's ancestors for the identifier lookup.
+     * @param completeMatch {@code true} if the defined key-value pairs should be the only pairs in
+     *            the scope.
+     * @param expectedFrame the key-value pairs (e.g. {@code "id0", 1, "id1", "strValue"})
+     */
+    private void assertScope(final int line, final String code, boolean includeAncestors, boolean completeMatch, final Object... expectedFrame) {
+        run.addLast(() -> {
+            try {
+                compareScope(line, code, includeAncestors, completeMatch, expectedFrame);
             } catch (RuntimeException | Error e) {
 
                 final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
@@ -341,6 +461,43 @@ public class FastRDebugTest {
         });
     }
 
+    private void compareScope(final int line, final String code, boolean includeAncestors, boolean completeMatch, final Object[] expectedFrame) {
+        final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+
+        final AtomicInteger numFrameVars = new AtomicInteger(0);
+        frame.forEach(var -> {
+            // skip synthetic slots
+            for (RFrameSlot slot : RFrameSlot.values()) {
+                if (slot.toString().equals(var.getName())) {
+                    return;
+                }
+            }
+            numFrameVars.incrementAndGet();
+        });
+        if (completeMatch) {
+            assertEquals(line + ": " + code, expectedFrame.length / 2, numFrameVars.get());
+        }
+
+        for (int i = 0; i < expectedFrame.length; i = i + 2) {
+            String expectedIdentifier = (String) expectedFrame[i];
+            Object expectedValue = expectedFrame[i + 1];
+            String expectedValueStr = (expectedValue != null) ? expectedValue.toString() : null;
+            DebugScope scope = frame.getScope();
+            DebugValue value;
+            do {
+                value = scope.getDeclaredValue(expectedIdentifier);
+                scope = scope.getParent();
+            } while (includeAncestors && value == null && scope != null && !REnvironment.baseEnv().getName().equals(scope.getName()));
+            assertNotNull("identifier \"" + expectedIdentifier + "\" not found", value);
+            String valueStr = value.as(String.class);
+            assertEquals(expectedValueStr, valueStr);
+        }
+
+        if (!run.isEmpty()) {
+            run.removeFirst().run();
+        }
+    }
+
     Object getRValue(Object value) {
         // This will only work in simple cases
         if (value instanceof EagerPromise) {
-- 
GitLab


From 7334cdde833aa101a7cee9995bce8725c78554bc Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Wed, 17 May 2017 17:34:04 +0200
Subject: [PATCH 383/402] Updated Truffle version.

---
 mx.fastr/suite.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 75a963bb2e..290ce1773a 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "7d960d6682ef3636cc7455e28132c1e537ea81f0",
+               "version" : "acbe9ec935090e0824372e508563c122b0e46682",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
-- 
GitLab


From 911b6957c054acbe68f2b575082e0c031f9de4a1 Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Tue, 9 May 2017 11:45:40 -0700
Subject: [PATCH 384/402] Modifications for unit tests

---
 .../truffle/r/engine/interop/RContextMR.java  | 42 +++++++++++
 .../interop/RForeignAccessFactoryImpl.java    |  3 +
 .../oracle/truffle/r/engine/shell/RMain.java  | 70 +++++++++++++++++++
 .../truffle/r/runtime/context/RContext.java   |  3 +-
 .../runtime/ffi/managed/Managed_PCRERFFI.java | 12 ++--
 .../truffle/r/test/FastRJUnitWrapper.java     |  5 +-
 mx.fastr/mx_fastr_junit.py                    |  7 +-
 mx.fastr/suite.py                             |  5 +-
 8 files changed, 134 insertions(+), 13 deletions(-)
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java
 create mode 100644 com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java
new file mode 100644
index 0000000000..19ed14c125
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.context.RContext;
+
+@MessageResolution(receiverType = RContext.class, language = TruffleRLanguage.class)
+public class RContextMR {
+    @CanResolve
+    public abstract static class RContext extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RContext;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index d9f4321f1a..9082fefc16 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
 import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_UpCallsRFFIImpl;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -102,6 +103,8 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return CharSXPWrapperMRForeign.ACCESS;
         } else if (obj instanceof RConnection) {
             return RConnectionMRForeign.ACCESS;
+        } else if (obj instanceof RContext) {
+            return RContextMRForeign.ACCESS;
         } else if (obj instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl) {
             return UnameUpCallImplMRForeign.ACCESS;
         } else if (obj instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
new file mode 100644
index 0000000000..4a65dc84db
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.shell;
+
+/**
+ * Convenience class that allows the R/Rscript entry to be chosen by an initial argument.
+ */
+public class RMain {
+
+    public static void main(String[] args) {
+        boolean rscript = false;
+        if (args.length > 0) {
+            String arg = args[0];
+            switch (arg) {
+                case "R":
+                case "r":
+                    break;
+
+                case "Rscript":
+                case "rscript":
+                    rscript = true;
+                    break;
+
+                default:
+                    System.out.println(arg);
+                    usage();
+            }
+            String[] xargs = shiftArgs(args);
+            if (rscript) {
+                RscriptCommand.main(xargs);
+            } else {
+                RCommand.main(xargs);
+            }
+        } else {
+            usage();
+        }
+    }
+
+    private static void usage() {
+        System.out.println("usage: [R|Rscript] ...");
+        System.exit(1);
+    }
+
+    private static String[] shiftArgs(String[] args) {
+        String[] nargs = new String[args.length - 1];
+        System.arraycopy(args, 1, nargs, 0, nargs.length);
+        return nargs;
+    }
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 9b6d4cf9b5..da182ef202 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -71,6 +71,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
@@ -97,7 +98,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  * Contexts can be destroyed
  */
 @SuppressWarnings("deprecation")
-public final class RContext extends com.oracle.truffle.api.ExecutionContext {
+public final class RContext extends com.oracle.truffle.api.ExecutionContext implements RTruffleObject {
 
     public static final int CONSOLE_WIDTH = 80;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
index e060345226..622b78cc0c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
@@ -29,31 +29,31 @@ import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 public class Managed_PCRERFFI implements PCRERFFI {
     @Override
     public MaketablesNode createMaketablesNode() {
-        throw unsupported("PCRER");
+        throw unsupported("PCRE");
     }
 
     @Override
     public CompileNode createCompileNode() {
-        throw unsupported("PCRER");
+        throw unsupported("PCRE");
     }
 
     @Override
     public GetCaptureCountNode createGetCaptureCountNode() {
-        throw unsupported("PCRER");
+        throw unsupported("PCRE");
     }
 
     @Override
     public GetCaptureNamesNode createGetCaptureNamesNode() {
-        throw unsupported("PCRER");
+        throw unsupported("PCRE");
     }
 
     @Override
     public StudyNode createStudyNode() {
-        throw unsupported("PCRER");
+        throw unsupported("PCRE");
     }
 
     @Override
     public ExecNode createExecNode() {
-        throw unsupported("PCRER");
+        throw unsupported("PCRE");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java
index eb1259935f..b38580ea0b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/FastRJUnitWrapper.java
@@ -106,9 +106,8 @@ public class FastRJUnitWrapper {
 
                 ArrayList<Class<?>> tests = new ArrayList<>(1000);
                 try (BufferedReader br = new BufferedReader(new FileReader(testsFile))) {
-                    String className;
-                    while ((className = br.readLine()) != null) {
-                        tests.add(Class.forName(className));
+                    while ((testClassName = br.readLine()) != null) {
+                        tests.add(Class.forName(testClassName));
                     }
                 } catch (IOException ioe) {
                     ioe.printStackTrace();
diff --git a/mx.fastr/mx_fastr_junit.py b/mx.fastr/mx_fastr_junit.py
index 98aa47d398..9f95551497 100644
--- a/mx.fastr/mx_fastr_junit.py
+++ b/mx.fastr/mx_fastr_junit.py
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -76,7 +76,10 @@ def junit(args, harness, parser=None, jdk_default=None):
             if not found:
                 mx.warn('no tests matched by substring "' + t + '"')
 
-    vmArgs += mx.get_runtime_jvm_args([pcp.name for pcp in mx.projects(opt_limit_to_suite=True) if pcp.isJavaProject() and pcp.javaCompliance <= jdk.javaCompliance], jdk=jdk)
+    dists = ['FASTR', 'FASTR_UNIT_TESTS']
+    if mx.suite('r-apptests', fatalIfMissing=False):
+        dists.append('com.oracle.truffle.r.test.apps')
+    vmArgs += mx.get_runtime_jvm_args(dists, jdk=jdk)
 
     if len(classes) != 0:
         if len(classes) == 1:
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 75a963bb2e..b915323c9f 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -319,7 +319,10 @@ suite = {
 
     "FASTR_UNIT_TESTS" : {
       "description" : "unit tests",
-      "dependencies" : ["com.oracle.truffle.r.test"],
+      "dependencies" : [
+        "com.oracle.truffle.r.test",
+        "com.oracle.truffle.r.nodes.test"
+       ],
       "exclude": ["mx:HAMCREST", "mx:JUNIT", "mx:JMH"],
       "distDependencies" : [
         "FASTR",
-- 
GitLab


From 46cdb99b488be40a5f244d544b96d96a6ce58984 Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Thu, 18 May 2017 10:01:47 +0200
Subject: [PATCH 385/402] FastR Grid: window resizing improvements

* warn if the executor used for resizing is not available
* do not execute PolyglotEngine.Value#get if there is no executor
---
 .../truffle/r/engine/shell/RCommand.java      |  7 +++++-
 .../r/library/fastrGrid/WindowDevice.java     | 25 +++++++++++++++----
 .../truffle/r/runtime/context/RContext.java   | 14 ++++++-----
 3 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index acf0b204e5..9f159f8135 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -38,6 +38,7 @@ import java.util.List;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.api.vm.PolyglotEngine.Value;
 import com.oracle.truffle.r.nodes.builtin.base.Quit;
 import com.oracle.truffle.r.runtime.ExitException;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
@@ -223,11 +224,15 @@ public class RCommand {
                     String continuePrompt = getContinuePrompt();
                     StringBuffer sb = new StringBuffer(input);
                     Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
+                    boolean hasExecutor = RContext.getInstance().hasExecutor();
                     while (true) {
                         lastStatus = 0;
                         try {
                             try {
-                                vm.eval(source).get();
+                                Value val = vm.eval(source);
+                                if (hasExecutor) {
+                                    val.get();
+                                }
                                 // checked exceptions are wrapped in RuntimeExceptions
                             } catch (RuntimeException e) {
                                 if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
index a2c5077fa4..6ed69613fc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/WindowDevice.java
@@ -43,15 +43,30 @@ public final class WindowDevice {
 
     public static GridDevice createWindowDevice(int width, int height) {
         JFrameDevice frameDevice = JFrameDevice.create(width, height);
-        frameDevice.setResizeListener(() -> {
-            RContext.getInstance().schedule(() -> {
-                GridContext.getContext().evalInternalRFunction("redrawAll");
-            });
-        });
+        if (RContext.getInstance().hasExecutor()) {
+            frameDevice.setResizeListener(WindowDevice::redrawAll);
+        } else {
+            noSchedulingSupportWarning();
+        }
         return new BufferedJFrameDevice(frameDevice);
     }
 
     public static RError awtNotSupported() {
         throw RError.error(RError.NO_CALLER, Message.GENERIC, "AWT based grid devices are not supported.");
     }
+
+    private static void redrawAll() {
+        RContext ctx = RContext.getInstance();
+        if (ctx.hasExecutor()) {
+            // to be robust we re-check the executor availability
+            ctx.schedule(() -> {
+                GridContext.getContext().evalInternalRFunction("redrawAll");
+            });
+        }
+    }
+
+    private static void noSchedulingSupportWarning() {
+        // Note: the PolyglotEngine was not built with an Executor
+        RError.warning(RError.NO_CALLER, Message.GENERIC, "Grid cannot resize the drawings. If you resize the window, the content will be lost.");
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index da182ef202..6db41563e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -822,15 +822,17 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         return info.getEnv();
     }
 
+    public boolean hasExecutor() {
+        return info.executor != null;
+    }
+
     /**
-     * Allows another thread to schedule some code to be run in this context's thread. The action is
-     * ignored if the current context does not support such scheduling, i.e. the polyglot engine was
-     * not created with an executor.
+     * Allows another thread to schedule some code to be run in this context's thread. The action
+     * can be scheduled only if PolyglotEngine was created with an Executor.
      */
     public void schedule(Runnable action) {
-        if (info.executor != null) {
-            info.executor.execute(action);
-        }
+        assert hasExecutor() : "Cannot run RContext#schedule() when there is no executor.";
+        info.executor.execute(action);
     }
 
     @Override
-- 
GitLab


From cd0361a16898dccfbdcdd2a43d152fdbbbb8474d Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 19 Apr 2017 16:36:12 +0200
Subject: [PATCH 386/402] added specialization for TruffleObject-s to typeof
 builtin

---
 .../com/oracle/truffle/r/nodes/unary/TypeofNode.java   | 10 ++++++++++
 .../src/com/oracle/truffle/r/runtime/RType.java        |  3 ++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
index cf9c38a6aa..1df443ba8c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RMissing;
@@ -81,6 +82,15 @@ public abstract class TypeofNode extends UnaryNode {
         return operand.getRType();
     }
 
+    @Specialization(guards = "isForeignObject(object)")
+    protected RType doTruffleObject(@SuppressWarnings("unused") TruffleObject object) {
+        return RType.TruffleObject;
+    }
+
+    protected static boolean isForeignObject(Object obj) {
+        return RRuntime.isForeignObject(obj);
+    }
+
     public static RType getTypeof(Object operand) {
         CompilerAsserts.neverPartOfCompilation();
         return ((RTypedValue) RRuntime.asAbstractVector(operand)).getRType();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
index 4c08a3aae0..ddf2a1e6c0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
@@ -46,7 +46,8 @@ public enum RType {
     ExternalPtr("externalptr", -1),
     S4Object("S4", -1),
     Connection("connection", -1),
-    Dots("...", -1);
+    Dots("...", -1),
+    TruffleObject("truffle.object", -1);
 
     public static final int NO_PRECEDENCE = -1;
     public static final int NUMBER_OF_PRECEDENCES = 9;
-- 
GitLab


From 6f106d4d6451bc55315a8440043329800d776401 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 19 Apr 2017 17:19:42 +0200
Subject: [PATCH 387/402] names builtin should retrieve also static members
 from a TruffleObject

---
 .../truffle/r/nodes/builtin/base/Names.java   | 59 ++++++++++++++-----
 .../truffle/r/test/ExpectedTestOutput.test    | 32 ++++++++++
 .../r/test/builtins/TestBuiltin_names.java    | 44 +++++++++++++-
 3 files changed, 120 insertions(+), 15 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index 1bdd1932b9..e90f8a20c6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -34,6 +34,9 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
@@ -80,29 +83,57 @@ public abstract class Names extends RBuiltinNode.Arg1 {
                     @Cached("KEYS.createNode()") Node keysNode,
                     @Cached("READ.createNode()") Node readNode,
                     @Cached("IS_BOXED.createNode()") Node isBoxedNode,
-                    @Cached("UNBOX.createNode()") Node unboxNode) {
+                    @Cached("UNBOX.createNode()") Node unboxNode,
+                    @Cached("createExecute(0).createNode()") Node callNode) {
 
         try {
-            TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
-            if (keys != null) {
-                int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
-                String[] names = new String[size];
-                for (int i = 0; i < size; i++) {
-                    Object value;
-                    value = ForeignAccess.sendRead(readNode, keys, i);
-                    if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
-                        value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
-                    }
-                    names[i] = (String) value;
+            String[] names;
+            try {
+                names = readKeys(keysNode, obj, getSizeNode, readNode, isBoxedNode, unboxNode);
+            } catch (UnsupportedMessageException e) {
+                // because it is a java function, java.util.Map (has special handling too) ... ?
+                return RNull.instance;
+            }
+            String[] staticNames = new String[0];
+            try {
+                if (JavaInterop.isJavaObject(Object.class, obj)) {
+                    TruffleObject clazz = JavaInterop.toJavaClass(obj);
+                    staticNames = readKeys(keysNode, clazz, getSizeNode, readNode, isBoxedNode, unboxNode);
                 }
-                return RDataFactory.createStringVector(names, true);
+            } catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) {
+                // because it is a class ... ?
             }
-            return RNull.instance;
+            if (names.length == 0 && staticNames.length == 0) {
+                return RNull.instance;
+            }
+            String[] result = new String[names.length + staticNames.length];
+            System.arraycopy(names, 0, result, 0, names.length);
+            System.arraycopy(staticNames, 0, result, names.length, staticNames.length);
+            return RDataFactory.createStringVector(result, true);
         } catch (InteropException e) {
             throw RInternalError.shouldNotReachHere(e);
         }
     }
 
+    private String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode, Node isBoxedNode, Node unboxNode)
+                    throws UnknownIdentifierException, InteropException, UnsupportedMessageException {
+        TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
+        if (keys != null) {
+            int size = (Integer) ForeignAccess.sendGetSize(getSizeNode, keys);
+            String[] names = new String[size];
+            for (int i = 0; i < size; i++) {
+                Object value;
+                value = ForeignAccess.sendRead(readNode, keys, i);
+                if (value instanceof TruffleObject && ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) value)) {
+                    value = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) value);
+                }
+                names[i] = (String) value;
+            }
+            return names;
+        }
+        return new String[0];
+    }
+
     @Fallback
     protected RNull getNames(@SuppressWarnings("unused") Object operand) {
         return RNull.instance;
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 db2d6cfa5b..384d1e5056 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
@@ -36571,6 +36571,38 @@ Error in k() : argument "y" is missing, with no default
 #argv <- structure(list(x = NA_real_), .Names = 'x');do.call('mode', argv)
 [1] "numeric"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); names(tc$staticField) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); names(tc$staticMethod) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClassNoMembers'); t <- .fastr.interop.new(tc); names(t) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClassNoPublicMembers'); t <- .fastr.interop.new(tc); names(t) }
+NULL
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); t <- .fastr.interop.new(tc); sort(names(t)) }
+[1] "field"        "method"       "staticField"  "staticMethod"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('one', 'two') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClassMap'); t <- .fastr.interop.new(tc); sort(names(t$m())) }
+[1] "one" "two"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); sort(names(tc)) }
+[1] "staticField"  "staticMethod"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testLNames#
 #{ x <- quote(plot(x = age, y = weight)); names(x) }
 [1] ""  "x" "y"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
index cd568a219d..8dd9a197c3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -13,6 +13,8 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import java.util.HashMap;
+import java.util.Map;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_names extends TestBase {
@@ -210,4 +212,44 @@ public class TestBuiltin_names extends TestBase {
     public void testLNames() {
         assertEval("{ x <- quote(plot(x = age, y = weight)); names(x) }");
     }
+
+    public static class TestClass {
+        public Object field;
+        public static Object staticField;
+
+        public void method() {
+        }
+
+        public static void staticMethod() {
+        }
+    }
+
+    public static class TestClassNoMembers {
+
+    }
+
+    public static class TestClassNoPublicMembers {
+        int i;
+    }
+
+    public static class TestClassMap {
+        public static Map<String, String> m() {
+            HashMap<String, String> m = new HashMap<>();
+            m.put("one", "1");
+            m.put("two", "2");
+            return m;
+        }
+    }
+
+    @Test
+    public void testJavaObject() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClassNoMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClassNoPublicMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); names(tc$staticField)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); names(tc$staticMethod)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')");
+        assertEvalFastR("cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')");
+    }
 }
-- 
GitLab


From 18744869c820540e623c809ddc202cb713a32ac5 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 26 Apr 2017 17:16:41 +0200
Subject: [PATCH 388/402] java interopt - some basic functionality regarding -
 instantiation - calling of methods and field access - type conversions

---
 .../r/nodes/builtin/base/BasePackage.java     |   5 +
 .../builtin/base/printer/ValuePrinters.java   |   5 +-
 .../r/nodes/builtin/fastr/FastRInterop.java   | 530 +++++++++++++++-
 .../access/vector/ExtractVectorNode.java      |  98 ++-
 .../access/vector/ReplaceVectorNode.java      |  64 +-
 .../r/nodes/function/ClassHierarchyNode.java  |   6 +
 .../truffle/r/nodes/function/RCallNode.java   |  24 +-
 .../truffle/r/nodes/unary/CastListNode.java   |  12 +
 .../truffle/r/nodes/unary/PrecedenceNode.java |  17 +
 .../com/oracle/truffle/r/runtime/RError.java  |   1 +
 .../oracle/truffle/r/runtime/RRuntime.java    |  73 ++-
 .../com/oracle/truffle/r/runtime/RType.java   |   7 +-
 .../r/runtime/data/RInteropScalar.java        | 204 ++++++
 .../oracle/truffle/r/runtime/data/RTypes.java |  11 +-
 .../truffle/r/test/ExpectedTestOutput.test    | 600 ++++++++++++++++++
 .../com/oracle/truffle/r/test/TestBase.java   |  11 +-
 .../r/test/library/fastr/TestJavaInterop.java | 595 +++++++++++++++++
 17 files changed, 2172 insertions(+), 91 deletions(-)
 create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
 create mode 100644 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 241fd56c01..3fda7060a4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -376,6 +376,11 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
         add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
+        add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
+        add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
+        add(FastRInterop.ToFloat.class, FastRInteropFactory.ToFloatNodeGen::create);
+        add(FastRInterop.ToLong.class, FastRInteropFactory.ToLongNodeGen::create);
+        add(FastRInterop.ToShort.class, FastRInteropFactory.ToShortNodeGen::create);
         add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create);
         add(FastRPkgSource.class, FastRPkgSourceNodeGen::create);
         add(FastRStackTrace.class, FastRStackTraceNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index 4104af4f43..0bd88751d6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -75,7 +76,7 @@ final class ValuePrinters implements ValuePrinter<Object> {
         if (v == RNull.instance) {
             NullPrinter.INSTANCE.print(null, printCtx);
         } else {
-            // handle types that can appear via Truffle interop
+            // handle types that are meant for or can appear via Truffle interop
             Object x = v;
             if (x instanceof Boolean) {
                 x = RRuntime.asLogical((Boolean) x);
@@ -83,6 +84,8 @@ final class ValuePrinters implements ValuePrinter<Object> {
                 x = ((Number) x).doubleValue();
             } else if (x instanceof Character) {
                 x = ((Character) x).toString();
+            } else if (x instanceof RInteropScalar) {
+                x = ((RInteropScalar) x).getRValue();
             }
             // try to box a scalar primitive value to the respective vector
             x = printCtx.printerNode().boxPrimitive(x);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index 912beabdbf..fee1e92a29 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -45,30 +45,50 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.Source.Builder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
+import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
+import static com.oracle.truffle.r.runtime.RType.Array;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public class FastRInterop {
 
@@ -165,7 +185,7 @@ public class FastRInterop {
         @TruffleBoundary
         protected Object exportSymbol(String name, RTypedValue value) {
             if (name == null) {
-                throw error(RError.Message.INVALID_ARG_TYPE, "name");
+                throw error(RError.Message.INVALID_ARGUMENT, "name");
             }
             RContext.getInstance().getExportedSymbols().put(name, value);
             return RNull.instance;
@@ -228,7 +248,7 @@ public class FastRInterop {
         }
 
         @Specialization
-        public byte hasSize(TruffleObject obj) {
+        public byte isNull(TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsNull(node, obj));
         }
     }
@@ -243,11 +263,149 @@ public class FastRInterop {
         }
 
         @Specialization
-        public byte hasSize(TruffleObject obj) {
+        public byte isExecutable(TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, obj));
         }
     }
 
+    @RBuiltin(name = ".fastr.interop.toByte", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToByte extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToByte.class));
+        }
+
+        @Specialization
+        public RInteropByte toByte(int value) {
+            return RInteropByte.valueOf((byte) value);
+        }
+
+        @Specialization
+        public RInteropByte toByte(double value) {
+            return RInteropByte.valueOf((byte) value);
+        }
+
+        @Specialization
+        public RInteropByte toByte(RRaw value) {
+            return RInteropByte.valueOf(value.getValue());
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toChar", visibility = ON, kind = PRIMITIVE, parameterNames = {"value", "pos"}, behavior = COMPLEX)
+    public abstract static class ToChar extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts casts = new Casts(ToChar.class);
+            casts.arg("value").mustBe(integerValue().or(doubleValue().or(stringValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe(
+                            singleElement()).findFirst();
+            casts.arg("pos").allowMissing().mustBe(numericValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "pos", Predef.typeName()).asIntegerVector().mustBe(singleElement()).findFirst();
+        }
+
+        @Specialization
+        public RInteropChar toChar(int value, @SuppressWarnings("unused") RMissing unused) {
+            return RInteropChar.valueOf((char) value);
+        }
+
+        @Specialization
+        public RInteropChar toChar(double value, @SuppressWarnings("unused") RMissing unused) {
+            return RInteropChar.valueOf((char) value);
+        }
+
+        @Specialization
+        public RInteropChar toChar(String value, @SuppressWarnings("unused") RMissing unused) {
+            return toChar(value, 0);
+        }
+
+        @Specialization
+        public RInteropChar toChar(int value, int pos) {
+            throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC);
+        }
+
+        @Specialization
+        public RInteropChar toChar(double value, int pos) {
+            throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC);
+        }
+
+        @Specialization
+        public RInteropChar toChar(String value, int pos) {
+            return RInteropChar.valueOf(value.charAt(pos));
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toFloat", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToFloat extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToFloat.class));
+        }
+
+        @Specialization
+        public RInteropFloat toFloat(int value) {
+            return RInteropFloat.valueOf((float) value);
+        }
+
+        @Specialization
+        public RInteropFloat toFloat(double value) {
+            return RInteropFloat.valueOf((float) value);
+        }
+
+        @Specialization
+        public RInteropFloat toFloat(RRaw value) {
+            return RInteropFloat.valueOf(value.getValue());
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toLong", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToLong extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToLong.class));
+        }
+
+        @Specialization
+        public RInteropLong toLong(int value) {
+            return RInteropLong.valueOf((long) value);
+        }
+
+        @Specialization
+        public RInteropLong toLong(double value) {
+            return RInteropLong.valueOf((long) value);
+        }
+
+        @Specialization
+        public RInteropLong toLong(RRaw value) {
+            return RInteropLong.valueOf(value.getValue());
+        }
+    }
+
+    @RBuiltin(name = ".fastr.interop.toShort", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    public abstract static class ToShort extends RBuiltinNode.Arg1 {
+
+        static {
+            castToJavaNumberType(new Casts(ToShort.class));
+        }
+
+        @Specialization
+        public RInteropShort toShort(double value) {
+            return RInteropShort.valueOf((short) value);
+        }
+
+        @Specialization
+        public RInteropShort toShort(int value) {
+            return RInteropShort.valueOf((short) value);
+        }
+
+        @Specialization
+        public RInteropShort toShort(RRaw value) {
+            return RInteropShort.valueOf(value.getValue());
+        }
+
+    }
+
+    private static void castToJavaNumberType(Casts casts) {
+        casts.arg("value").mustBe(integerValue().or(doubleValue().or(rawValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe(singleElement()).findFirst();
+    }
+
     @RBuiltin(name = ".fastr.interop.toBoolean", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToBoolean extends RBuiltinNode.Arg1 {
 
@@ -281,32 +439,349 @@ public class FastRInterop {
         }
     }
 
-    @ImportStatic({com.oracle.truffle.api.interop.Message.class, RRuntime.class})
-    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
-    public abstract static class InteropNew extends RBuiltinNode.Arg2 {
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.java.isArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
+    public abstract static class IsJavaArray extends RBuiltinNode.Arg1 {
 
         static {
-            Casts.noCasts(InteropNew.class);
+            Casts.noCasts(IsJavaArray.class);
+        }
+
+        private final ConditionProfile isJavaProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
+
+        @Specialization(guards = {"isForeignObject(obj)"})
+        @TruffleBoundary
+        public Object isArray(TruffleObject obj) {
+            // TODO does this return true only for java arrays, or also
+            // js arrays?
+            boolean result = isJavaProfile.profile(JavaInterop.isJavaObject(Object.class, obj)) && isArrayProfile.profile(JavaInterop.isArray(obj));
+            return RRuntime.java2R(result);
+        }
+
+        @Fallback
+        public Object isArray(Object obj) {
+            return RRuntime.java2R(false);
+        }
+    }
+
+    @RBuiltin(name = ".fastr.java.newArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "dim"}, behavior = COMPLEX)
+    public abstract static class NewJavaArray extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts casts = new Casts(NewJavaArray.class);
+            casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
+            casts.arg("dim").mustBe(integerValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "dim", typeName()).asIntegerVector();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object newArray(String clazz, int length) {
+            try {
+                // TODO new via ForeignAccess
+                return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), length));
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
         }
 
-        private static Object toJava(Object value) {
-            Object vector = RRuntime.asAbstractVector(value);
-            if (vector instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) vector).getLength() == 1) {
-                if (vector instanceof RAbstractDoubleVector) {
-                    RAbstractDoubleVector v = (RAbstractDoubleVector) vector;
-                    return v.getDataAt(0);
-                } else if (vector instanceof RAbstractLogicalVector) {
-                    RAbstractLogicalVector v = (RAbstractLogicalVector) vector;
-                    return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
-                } else if (vector instanceof RAbstractRawVector) {
-                    RAbstractRawVector v = (RAbstractRawVector) vector;
-                    return v.getDataAt(0).getValue();
-                } else if (vector instanceof RAbstractStringVector) {
-                    RAbstractStringVector v = (RAbstractStringVector) vector;
-                    return v.getDataAt(0);
+        @Specialization
+        @TruffleBoundary
+        public Object newArray(String clazz, RAbstractIntVector dim) {
+            try {
+                int[] dima = new int[dim.getLength()];
+                // TODO new via ForeignAccess
+                return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), dima));
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.java.toArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"x", "className", "flat"}, behavior = COMPLEX)
+    public abstract static class ToJavaArray extends RBuiltinNode.Arg3 {
+
+        static {
+            Casts casts = new Casts(ToJavaArray.class);
+            casts.arg("x").mustNotBeMissing();
+            casts.arg("className").allowMissing().mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
+            casts.arg("flat").mapMissing(Predef.constant(RRuntime.asLogical(true))).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
+                            notLogicalNA()).map(Predef.toBoolean());
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractLogicalVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, boolean.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractLogicalVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractIntVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, int.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractIntVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractDoubleVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, double.class, (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractDoubleVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractStringVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, String.class, (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractStringVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i)));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, Object.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RAbstractVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RInteropScalar ri, String className, boolean flat) {
+            RList list = RDataFactory.createList(new Object[]{ri});
+            return toArray(list, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i))));
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(RInteropScalar ri, RMissing className, boolean flat) {
+            RList list = RDataFactory.createList(new Object[]{ri});
+            return toArray(list, flat, ri.getJavaType(), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i))));
+        }
+
+        private Class<?> getClazz(String className) throws RError {
+            if (className.equals(Byte.TYPE.getName())) {
+                return Byte.TYPE;
+            }
+            if (className.equals(Boolean.TYPE.getName())) {
+                return Boolean.TYPE;
+            }
+            if (className.equals(Character.TYPE.getName())) {
+                return Character.TYPE;
+            }
+            if (className.equals(Double.TYPE.getName())) {
+                return Double.TYPE;
+            }
+            if (className.equals(Float.TYPE.getName())) {
+                return Float.TYPE;
+            }
+            if (className.equals(Integer.TYPE.getName())) {
+                return Integer.TYPE;
+            }
+            if (className.equals(Long.TYPE.getName())) {
+                return Long.TYPE;
+            }
+            if (className.equals(Short.TYPE.getName())) {
+                return Short.TYPE;
+            }
+            try {
+                return Class.forName(className);
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+
+        private int[] getDim(boolean flat, RAbstractVector vec) {
+            int[] dims;
+            if (flat) {
+                dims = new int[]{vec.getLength()};
+            } else {
+                dims = vec.getDimensions();
+                if (dims == null) {
+                    dims = new int[]{vec.getLength()};
                 }
             }
-            return value;
+            return dims;
+        }
+
+        private Object toArray(RAbstractVector vec, boolean flat, Class<?> clazz, VecElementToArray vecToArray) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+            int[] dims = getDim(flat, vec);
+            final Object array = Array.newInstance(clazz, dims);
+            for (int d = 0; d < dims.length; d++) {
+                int dim = dims[d];
+                // TODO works only for flat
+                for (int i = 0; i < dim; i++) {
+                    vecToArray.toArray(array, i);
+                }
+            }
+            return JavaInterop.asTruffleObject(array);
+        }
+
+        private interface VecElementToArray {
+            void toArray(Object array, Integer i);
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public Object toArray(TruffleObject obj, @SuppressWarnings("unused") RMissing missing, @SuppressWarnings("unused") boolean flat,
+                        @Cached("WRITE.createNode()") Node write) {
+            if (JavaInterop.isJavaObject(Object.class, obj)) {
+                if (JavaInterop.isArray(obj)) {
+                    // TODO should return copy?
+                    return obj;
+                }
+                try {
+                    // TODO should create array with the same component type as the JavaObject
+                    TruffleObject array = JavaInterop.asTruffleObject(Array.newInstance(Object.class, 1));
+                    ForeignAccess.sendWrite(write, array, 0, obj);
+                    return array;
+                } catch (UnsupportedMessageException | UnknownIdentifierException e) {
+                    throw error(RError.Message.GENERIC, "error while creating array: " + e.getMessage());
+                } catch (UnsupportedTypeException ex) {
+                    Logger.getLogger(FastRInterop.class.getName()).log(Level.SEVERE, null, ex);
+                }
+            }
+            throw error(RError.Message.GENERIC, "can't create array from " + obj);
+        }
+
+        @Fallback
+        public Object toArray(Object o, @SuppressWarnings("unused") Object className, @SuppressWarnings("unused") Object flat) {
+            throw error(RError.Message.GENERIC, "unsupported type");
+        }
+
+    }
+
+    @RBuiltin(name = ".fastr.java.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array"}, behavior = COMPLEX)
+    public abstract static class FromJavaArray extends RBuiltinNode.Arg1 {
+        @Child Node getSize = Message.GET_SIZE.createNode();
+        @Child Node read;
+        @Child Node isNull;
+        @Child Node isBoxed;
+        @Child Node unbox;
+        static {
+            Casts casts = new Casts(FromJavaArray.class);
+            casts.arg("array").mustNotBeMissing();
+        }
+
+        protected boolean isJavaArray(TruffleObject obj) {
+            return JavaInterop.isJavaObject(Object.class, obj) && JavaInterop.isArray(obj);
+        }
+
+        @Specialization(guards = {"isJavaArray(obj)"})
+        @TruffleBoundary
+        public Object fromArray(TruffleObject obj) {
+            int size;
+            try {
+                size = (int) ForeignAccess.sendGetSize(getSize, obj);
+                if (size == 0) {
+                    return RDataFactory.createList();
+                }
+                Object[] elements = new Object[size];
+                boolean allBoolean = true;
+                boolean allInteger = true;
+                boolean allDouble = true;
+                boolean allString = true;
+                for (int i = 0; i < size; i++) {
+                    if (read == null) {
+                        read = insert(Message.READ.createNode());
+                    }
+                    Object element = ForeignAccess.sendRead(read, obj, i);
+                    if (element instanceof TruffleObject) {
+                        if (isNull == null) {
+                            isNull = insert(Message.IS_NULL.createNode());
+                        }
+                        if (ForeignAccess.sendIsNull(isNull, (TruffleObject) element)) {
+                            element = null;
+                        } else {
+                            if (isBoxed == null) {
+                                isBoxed = insert(Message.IS_BOXED.createNode());
+                            }
+                            if (ForeignAccess.sendIsBoxed(isBoxed, (TruffleObject) element)) {
+                                if (unbox == null) {
+                                    unbox = insert(Message.UNBOX.createNode());
+                                }
+                                element = ForeignAccess.sendIsBoxed(unbox, (TruffleObject) element);
+                            }
+                        }
+                    }
+                    allBoolean &= element instanceof Boolean;
+                    allInteger &= element instanceof Byte || element instanceof Integer || element instanceof Short;
+                    allDouble &= element instanceof Double || element instanceof Float || element instanceof Long;
+                    allString &= element instanceof Character || element instanceof String;
+
+                    elements[i] = RRuntime.java2R(element);
+                }
+                if (allBoolean) {
+                    byte[] ret = new byte[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = ((Number) elements[i]).byteValue();
+                    }
+                    return RDataFactory.createLogicalVector(ret, true);
+                }
+                if (allInteger) {
+                    int[] ret = new int[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = ((Number) elements[i]).intValue();
+                    }
+                    return RDataFactory.createIntVector(ret, true);
+                }
+                if (allDouble) {
+                    double[] ret = new double[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = ((Number) elements[i]).doubleValue();
+                    }
+                    return RDataFactory.createDoubleVector(ret, true);
+                }
+                if (allString) {
+                    String[] ret = new String[size];
+                    for (int i = 0; i < size; i++) {
+                        ret[i] = String.valueOf(elements[i]);
+                    }
+                    return RDataFactory.createStringVector(ret, true);
+                }
+                return RDataFactory.createList(elements);
+            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
+                throw error(RError.Message.GENERIC, "error while converting array: " + e.getMessage());
+            }
+        }
+
+        @Fallback
+        public Object fromArray(@SuppressWarnings("unused") Object obj) {
+            throw error(RError.Message.GENERIC, "not a java array");
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
+    public abstract static class InteropNew extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts.noCasts(InteropNew.class);
         }
 
         @Specialization(limit = "99", guards = {"isForeignObject(clazz)", "length == args.getLength()"})
@@ -317,9 +792,10 @@ public class FastRInterop {
             try {
                 Object[] argValues = new Object[args.getLength()];
                 for (int i = 0; i < argValues.length; i++) {
-                    argValues[i] = toJava(args.getArgument(i));
+                    argValues[i] = RRuntime.r2Java(args.getArgument(i));
                 }
-                return ForeignAccess.sendNew(sendNew, clazz, argValues);
+                Object result = ForeignAccess.sendNew(sendNew, clazz, argValues);
+                return RRuntime.java2R(result);
             } catch (SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
                 throw error(Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index 89b0358664..c3de219932 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -23,14 +23,20 @@
 package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.KeyInfo;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
@@ -41,6 +47,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -48,6 +55,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
+@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 public abstract class ExtractVectorNode extends Node {
 
     protected static final int CACHE_LIMIT = 5;
@@ -88,51 +96,89 @@ public abstract class ExtractVectorNode extends Node {
 
     protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object exact, Object dropDimensions);
 
-    protected Node createForeignRead(Object[] positions) {
-        if (positions.length != 1) {
-            throw RError.error(this, RError.Message.GENERIC, "Invalid number positions for foreign access.");
-        }
-        return Message.READ.createNode();
-    }
-
     protected static boolean isForeignObject(TruffleObject object) {
         return RRuntime.isForeignObject(object);
     }
 
     protected static FirstStringNode createFirstString() {
-        return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot corce position to character for foreign access.");
+        return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot coerce position to character for foreign access.");
     }
 
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions,
-                    @Cached("createForeignRead(positions)") Node foreignRead,
+                    @Cached("READ.createNode()") Node foreignRead,
+                    @Cached("KEY_INFO.createNode()") Node keyInfoNode,
                     @Cached("positions.length") @SuppressWarnings("unused") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString,
-                    @Cached("createClassProfile()") ValueProfile positionProfile) {
-        Object position = positionProfile.profile(positions[0]);
+                    @Cached("createClassProfile()") ValueProfile positionProfile,
+                    @Cached("IS_NULL.createNode()") Node isNullNode,
+                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
+                    @Cached("UNBOX.createNode()") Node unboxNode) {
+        if (positions.length == 0) {
+            throw RError.error(this, RError.Message.GENERIC, "No positions for foreign access.");
+        }
+        positions = positionProfile.profile(positions);
         try {
-            if (position instanceof Integer) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((int) position) - 1});
-            } else if (position instanceof Double) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((double) position) - 1});
-            } else if (position instanceof String) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{position});
-            } else if (position instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.doCast(position));
-                return ForeignAccess.send(foreignRead, object, new Object[]{string});
-            } else if (position instanceof RAbstractDoubleVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1});
-            } else if (position instanceof RAbstractIntVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1});
-            } else {
-                throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+            try {
+                // TODO implicite unboxing ok? method calls seem to behave this way
+                Object result = object;
+                for (int i = 0; i < positions.length; i++) {
+                    result = send(positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
+                    if (positions.length > 1 && i < positions.length - 1) {
+                        assert result instanceof TruffleObject;
+                    }
+                }
+                return unbox(result, isNullNode, isBoxedNode, unboxNode);
+            } catch (UnknownIdentifierException | NoSuchFieldError e) {
+                throw RError.interopError(RError.findParentRBase(this), e, object);
             }
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
+    private Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode) throws UnsupportedMessageException {
+        if (RRuntime.isForeignObject(obj)) {
+            if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) {
+                return RNull.instance;
+            }
+            Boolean isBoxed = (Boolean) ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj);
+            if (isBoxed) {
+                return RRuntime.java2R(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj));
+            }
+        }
+        return RRuntime.java2R(obj);
+    }
+
+    private Object send(Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode) throws RError, InteropException {
+        if (position instanceof Integer) {
+            position = ((int) position) - 1;
+        } else if (position instanceof Double) {
+            position = ((double) position) - 1;
+        } else if (position instanceof RAbstractDoubleVector) {
+            position = ((RAbstractDoubleVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractIntVector) {
+            position = ((RAbstractIntVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractStringVector) {
+            position = firstString.executeString(castNode.doCast(position));
+        } else if (!(position instanceof String)) {
+            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+        }
+
+        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
+        if (KeyInfo.isReadable(info)) {
+            return ForeignAccess.sendRead(foreignRead, object, position);
+        } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
+            TruffleObject clazz = JavaInterop.toJavaClass(object);
+            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
+            if (KeyInfo.isReadable(info)) {
+                return ForeignAccess.sendRead(foreignRead, clazz, position);
+            }
+        }
+        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+    }
+
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"})
     protected Object doExtractSameDimensions(VirtualFrame frame, RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index d85926100c..5c4fa8b774 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -25,12 +25,15 @@ package com.oracle.truffle.r.nodes.access.vector;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.KeyInfo;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
@@ -38,8 +41,6 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.FirstStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.RDouble;
-import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -49,6 +50,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 /**
  * Syntax node for element writes.
  */
+@ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
 public abstract class ReplaceVectorNode extends Node {
 
     protected static final int CACHE_LIMIT = 5;
@@ -97,40 +99,50 @@ public abstract class ReplaceVectorNode extends Node {
 
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, Object value,
-                    @Cached("createForeignWrite(positions)") Node foreignRead,
+                    @Cached("WRITE.createNode()") Node foreignWrite,
+                    @Cached("KEY_INFO.createNode()") Node keyInfo,
                     @SuppressWarnings("unused") @Cached("positions.length") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString) {
-
-        Object writtenValue = value;
-        if (writtenValue instanceof RInteger) {
-            writtenValue = ((RInteger) writtenValue).getValue();
-        } else if (writtenValue instanceof RDouble) {
-            writtenValue = ((RDouble) writtenValue).getValue();
-        }
+        Object writtenValue = RRuntime.r2Java(value);
         Object position = positions[0];
         try {
-            if (position instanceof Integer) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((Integer) position) - 1, writtenValue});
-            } else if (position instanceof Double) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((Double) position) - 1, writtenValue});
-            } else if (position instanceof String) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{position, writtenValue});
-            } else if (position instanceof RAbstractStringVector) {
-                String string = firstString.executeString(castNode.doCast(position));
-                return ForeignAccess.send(foreignRead, object, new Object[]{string, writtenValue});
-            } else if (position instanceof RAbstractDoubleVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractDoubleVector) position).getDataAt(0) - 1, writtenValue});
-            } else if (position instanceof RAbstractIntVector) {
-                return ForeignAccess.send(foreignRead, object, new Object[]{((RAbstractIntVector) position).getDataAt(0) - 1, writtenValue});
-            } else {
-                throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
-            }
+            return write(position, foreignWrite, keyInfo, object, writtenValue, firstString, castNode);
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
+    private Object write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
+                    throws InteropException, RError {
+        if (position instanceof Integer) {
+            position = ((Integer) position) - 1;
+        } else if (position instanceof Double) {
+            position = ((Double) position) - 1;
+        } else if (position instanceof RAbstractDoubleVector) {
+            position = ((RAbstractDoubleVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractIntVector) {
+            position = ((RAbstractIntVector) position).getDataAt(0) - 1;
+        } else if (position instanceof RAbstractStringVector) {
+            String string = firstString.executeString(castNode.doCast(position));
+            position = string;
+        } else if (!(position instanceof String)) {
+            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+        }
+
+        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
+        if (KeyInfo.isWritable(info)) {
+            return ForeignAccess.sendWrite(foreignWrite, object, position, writtenValue);
+        } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
+            TruffleObject clazz = JavaInterop.toJavaClass(object);
+            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
+            if (KeyInfo.isWritable(info)) {
+                return ForeignAccess.sendWrite(foreignWrite, clazz, position, writtenValue);
+            }
+        }
+        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+    }
+
     @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(vector, positions)"})
     protected Object doRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object value,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveReplaceSubscriptNode cached) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
index fd54fa745c..29c1453ada 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java
@@ -48,6 +48,7 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -148,6 +149,11 @@ public abstract class ClassHierarchyNode extends UnaryNode {
         return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null;
     }
 
+    @Specialization
+    protected RStringVector getClassHr(@SuppressWarnings("unused") RInteropScalar arg) {
+        return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(arg.getRType()) : null;
+    }
+
     @Specialization
     protected RStringVector getClassHr(@SuppressWarnings("unused") REmpty arg) {
         return withImplicitTypes ? ImplicitClassHierarchyNode.getImplicitClass(RType.Null) : null;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index a2bf334242..7fa4270828 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -40,9 +40,12 @@ import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
 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.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
@@ -90,6 +93,7 @@ import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -526,6 +530,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
 
         @Child private CallArgumentsNode arguments;
         @Child private Node foreignCall;
+        @Child private Node isNullCall;
         @CompilationFinal private int foreignCallArgCount;
 
         public ForeignCall(CallArgumentsNode arguments) {
@@ -540,15 +545,20 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                 foreignCallArgCount = argumentsArray.length;
             }
             try {
-                Object result = ForeignAccess.sendExecute(foreignCall, function, argumentsArray);
-                if (result instanceof Boolean) {
-                    // convert to R logical
-                    // TODO byte/short convert to int?
-                    result = RRuntime.asLogical((boolean) result);
+                Object result = ForeignAccess.sendExecute(foreignCall, function, RRuntime.r2Java(argumentsArray));
+                if (RRuntime.isForeignObject(result)) {
+                    if (isNullCall == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        isNullCall = insert(Message.IS_NULL.createNode());
+                    }
+                    if (ForeignAccess.sendIsNull(isNullCall, (TruffleObject) result)) {
+                        return RNull.instance;
+                    }
                 }
-                return result;
-            } catch (Throwable e) {
+                return RRuntime.java2R(result);
+            } catch (ArityException | UnsupportedMessageException | UnsupportedTypeException e) {
                 CompilerDirectives.transferToInterpreter();
+                RInternalError.reportError(e);
                 throw RError.interopError(RError.findParentRBase(this), e, function);
             }
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index 5b442a98d5..2ea4c2b07e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -26,6 +26,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
@@ -37,6 +38,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -147,6 +149,16 @@ public abstract class CastListNode extends CastBaseNode {
         return RDataFactory.createList(new Object[]{s});
     }
 
+    @Specialization
+    protected RList doRInterop(RInteropScalar ri) {
+        return RDataFactory.createList(new Object[]{ri});
+    }
+
+    @Specialization(guards = {"isForeignObject(to)"})
+    protected RList doForeignObject(TruffleObject to) {
+        return RDataFactory.createList(new Object[]{to});
+    }
+
     public static CastListNode create() {
         return CastListNodeGen.create(true, true, true);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
index 03eda37330..1d8a29e9d0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
@@ -151,6 +153,11 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
+    @Specialization
+    protected int doRInteroptFloat(RInterop b, boolean recursive) {
+        return NO_PRECEDENCE;
+    }
+
     @Specialization(guards = "recursive")
     protected int doListRecursive(RList val, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
@@ -205,6 +212,16 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
+    @Specialization
+    protected int doRInterop(RInteropScalar ri, boolean recursive) {
+        return LIST_PRECEDENCE;
+    }
+
+    @Specialization(guards = {"isForeignObject(to)"})
+    protected int doForeignObject(TruffleObject to, boolean recursive) {
+        return LIST_PRECEDENCE;
+    }
+
     @Specialization(guards = {"!recursive", "args.getLength() == 1"})
     protected int doArgsValuesAndNames(RArgsValuesAndNames args, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index 8583792a6f..fbb3953558 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -613,6 +613,7 @@ public final class RError extends RuntimeException {
         UNRECOGNIZED_FORMAT("unrecognized format specification '%s'"),
         INVALID_FORMAT_LOGICAL("invalid format '%s'; use format %%d or %%i for logical objects"),
         INVALID_FORMAT_INTEGER("invalid format '%s'; use format %%d, %%i, %%o, %%x or %%X for integer objects"),
+        POS_NOT_ALLOWED_WITH_NUMERIC("pos argument not allowed with a numeric value"),
         // the following list is incomplete (but like GNU-R)
         INVALID_FORMAT_DOUBLE("invalid format '%s'; use format %%f, %%e, %%g or %%a for numeric objects"),
         INVALID_LOGICAL("'%s' must be TRUE or FALSE"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 542a7976db..d80fe43d1b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,22 +21,31 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
 import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -312,7 +321,7 @@ public class RRuntime {
     }
 
     public static String logicalToStringNoCheck(byte operand) {
-        assert operand == LOGICAL_TRUE || operand == LOGICAL_FALSE;
+        assert operand == LOGICAL_TRUE || operand == LOGICAL_FALSE : "operand: " + operand;
         return operand == LOGICAL_TRUE ? STRING_TRUE : STRING_FALSE;
     }
 
@@ -918,4 +927,66 @@ public class RRuntime {
         return xa.hasDimensions();
     }
 
+    public static Object java2R(Object obj) {
+        if (obj == null) {
+            obj = RNull.instance;
+        } else if (obj instanceof Boolean) {
+            obj = RRuntime.asLogical((boolean) obj);
+        } else if (obj instanceof Byte) {
+            obj = ((Byte) obj).intValue();
+        } else if (obj instanceof Short) {
+            obj = ((Short) obj).intValue();
+        } else if (obj instanceof Long) {
+            obj = (((Long) obj).doubleValue());
+        } else if (obj instanceof Float) {
+            obj = (((Float) obj).doubleValue());
+        } else if (obj instanceof Character) {
+            obj = ((Character) obj).toString();
+        }
+        return obj;
+    }
+
+    public static Object[] r2Java(Object[] objects) {
+        Object[] ret = new Object[objects.length];
+        for (int i = 0; i < objects.length; i++) {
+            ret[i] = RRuntime.r2Java(objects[i]);
+        }
+        return ret;
+    }
+
+    public static Object r2Java(Object obj) {
+        if (obj == RNull.instance) {
+            return JavaInterop.asTruffleObject(null);
+        } else if (obj instanceof Byte) {
+            return RRuntime.fromLogical((byte) obj);
+        } else if (obj instanceof RInteropByte) {
+            return ((RInteropByte) obj).getValue();
+        } else if (obj instanceof RInteropChar) {
+            return ((RInteropChar) obj).getValue();
+        } else if (obj instanceof RInteropFloat) {
+            return ((RInteropFloat) obj).getValue();
+        } else if (obj instanceof RInteropLong) {
+            return ((RInteropLong) obj).getValue();
+        } else if (obj instanceof RInteropShort) {
+            return ((RInteropShort) obj).getValue();
+        } else if (obj instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) obj).getLength() == 1) {
+            if (obj instanceof RAbstractDoubleVector) {
+                RAbstractDoubleVector v = (RAbstractDoubleVector) obj;
+                return v.getDataAt(0);
+            } else if (obj instanceof RAbstractIntVector) {
+                RAbstractIntVector v = (RAbstractIntVector) obj;
+                return v.getDataAt(0);
+            } else if (obj instanceof RAbstractLogicalVector) {
+                RAbstractLogicalVector v = (RAbstractLogicalVector) obj;
+                return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
+            } else if (obj instanceof RAbstractRawVector) {
+                RAbstractRawVector v = (RAbstractRawVector) obj;
+                return v.getDataAt(0).getValue();
+            } else if (obj instanceof RAbstractStringVector) {
+                RAbstractStringVector v = (RAbstractStringVector) obj;
+                return v.getDataAt(0);
+            }
+        }
+        return obj;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
index ddf2a1e6c0..c4d03652bf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
@@ -47,7 +47,12 @@ public enum RType {
     S4Object("S4", -1),
     Connection("connection", -1),
     Dots("...", -1),
-    TruffleObject("truffle.object", -1);
+    TruffleObject("truffle.object", -1),
+    RInteropByte("interopt.byte", -1),
+    RInteropChar("interopt.char", -1),
+    RInteropFloat("interopt.float", -1),
+    RInteropLong("interopt.long", -1),
+    RInteropShort("interopt.short", -1);
 
     public static final int NO_PRECEDENCE = -1;
     public static final int NUMBER_OF_PRECEDENCES = 9;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
new file mode 100644
index 0000000000..e2f4a3bc4f
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.data;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.r.runtime.RType;
+
+@ValueType
+public abstract class RInteropScalar extends RScalar {
+
+    public abstract Object getRValue();
+
+    @ValueType
+    public static final class RInteropByte extends RInteropScalar {
+
+        private final byte value;
+
+        private RInteropByte(byte value) {
+            this.value = value;
+        }
+
+        public static RInteropByte valueOf(byte value) {
+            return new RInteropByte(value);
+        }
+
+        public byte getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Byte) value).intValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropByte;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Byte.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropChar extends RInteropScalar {
+
+        private final char value;
+
+        private RInteropChar(char value) {
+            this.value = value;
+        }
+
+        public static RInteropChar valueOf(char value) {
+            return new RInteropChar(value);
+        }
+
+        public char getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return Character.toString(value);
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropChar;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Character.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropFloat extends RInteropScalar {
+
+        private final float value;
+
+        private RInteropFloat(float value) {
+            this.value = value;
+        }
+
+        public static RInteropFloat valueOf(float value) {
+            return new RInteropFloat(value);
+        }
+
+        public float getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Float) value).doubleValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropFloat;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Float.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropLong extends RInteropScalar {
+
+        private final long value;
+
+        private RInteropLong(long value) {
+            this.value = value;
+        }
+
+        public static RInteropLong valueOf(long value) {
+            return new RInteropLong(value);
+        }
+
+        public long getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Long) value).doubleValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropLong;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Long.toString(value);
+        }
+    }
+
+    @ValueType
+    public static final class RInteropShort extends RInteropScalar {
+
+        private final short value;
+
+        private RInteropShort(short value) {
+            this.value = value;
+        }
+
+        public static RInteropShort valueOf(short value) {
+            return new RInteropShort(value);
+        }
+
+        public short getValue() {
+            return value;
+        }
+
+        @Override
+        public Object getRValue() {
+            return ((Short) value).intValue();
+        }
+
+        @Override
+        public RType getRType() {
+            return RType.RInteropShort;
+        }
+
+        @Override
+        public String toString() {
+            CompilerAsserts.neverPartOfCompilation();
+            return Short.toString(value);
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
index c7c9a3819d..f11da3d123 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java
@@ -26,6 +26,11 @@ import com.oracle.truffle.api.dsl.ImplicitCast;
 import com.oracle.truffle.api.dsl.TypeCast;
 import com.oracle.truffle.api.dsl.TypeCheck;
 import com.oracle.truffle.api.dsl.TypeSystem;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -47,7 +52,11 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
  * @see RNode
  */
 @TypeSystem({
-                byte.class, RAbstractLogicalVector.class,
+                byte.class, RAbstractLogicalVector.class, RInteropByte.class,
+                RInteropChar.class,
+                RInteropFloat.class,
+                RInteropLong.class,
+                RInteropShort.class,
                 int.class, RAbstractIntVector.class,
                 double.class, RAbstractDoubleVector.class,
                 String.class, RAbstractStringVector.class,
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 384d1e5056..23d2b3fefd 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
@@ -130560,6 +130560,606 @@ attr(,"is.truffle.object")
 attr(,"is.truffle.object")
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAllTypes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
+[1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAllTypes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
+[1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringObject }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringObject }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldChar }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharObject }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticChar }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharObject }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDouble }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleObject }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDouble }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleObject }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByte }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteObject }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByte }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteObject }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldInteger }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntegerObject }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticInteger }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntegerObject }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloat }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatObject }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloat }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatObject }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShort }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortObject }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShort }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortObject }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLong }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongObject }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLong }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongObject }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldNullObject }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNullObject }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaN }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaNObject }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanObject }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanObject }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringObject() }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringObject() }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodChar() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodCharObject() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticChar() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticCharObject() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDouble() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDoubleObject() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDouble() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDoubleObject() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByte() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByteObject() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByte() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByteObject() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodInteger() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntegerObject() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticInteger() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntegerObject() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloat() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloatObject() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloat() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloatObject() }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShort() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShortObject() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShort() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShortObject() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLong() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLongObject() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLong() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLongObject() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodReturnsNull() }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticReturnsNull() }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBoolean() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBooleanObject() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBoolean() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBooleanObject() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringArray() }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringArray() }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntArray() }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntArray() }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { tc <- .fastr.java.class('java.lang.Character'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'abc' } else { tc <- .fastr.java.class('java.lang.String'); t <- .fastr.interop.new(tc, 'abc'); t }
+[1] "abc"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNullClass'); t <- .fastr.interop.new(tc, NULL); class(t) }
+[1] "truffle.object"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Byte'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Integer'); t <- .fastr.interop.new(tc, 1L); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Long'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Short'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Double'); t <- .fastr.interop.new(tc, 1.1); t }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Float'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('java.lang.Boolean'); t <- .fastr.interop.new(tc, TRUE); t }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNonPrimitiveParameter#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$equals(t) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.Long } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull(1) }
+Error: object 'java.lang.Long' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull('string') }
+Error: object 'java.lang.String' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { boolean } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE) }
+Error: object 'boolean' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded('string') }
+Error: object 'java.lang.String' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); class(v); }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); typeof(v); }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(1.7976931348623157E308); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(2147483647); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -128 } else { v <- .fastr.interop.toByte(-128); v; }
+[1] -128
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(-2147483648); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { v <- .fastr.interop.toByte(127); v; }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar('a'); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97.1); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1); v; }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1.1); v; }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97); class(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97); typeof(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); class(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); typeof(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0.0 } else { v <- .fastr.interop.toFloat(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { v <- .fastr.interop.toFloat(1.1); v; }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.401298464324817E-45 } else { v <- .fastr.interop.toFloat(1.4E-45); v; }
+[1] 1.401298e-45
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { v <- .fastr.interop.toFloat(3.4028235E38); v; }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { Inf } else { v <- .fastr.interop.toFloat(1.7976931348623157E308); v; }
+[1] Inf
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); class(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); typeof(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -2147483648 } else { v <- .fastr.interop.toLong(-2147483648); v; }
+[1] -2147483648
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toLong(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { v <- .fastr.interop.toLong(2147483647); v; }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { v <- .fastr.interop.toLong(1.7976931348623157E308); v; }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); class(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); typeof(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(1.7976931348623157E308); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(2147483647); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { -32768 } else { v <- .fastr.interop.toShort(-32768); v; }
+[1] -32768
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(-2147483648); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { v <- .fastr.interop.toShort(32767); v; }
+[1] 32767
+
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { { f<-function(x) .fastr.refcountinfo(x); f(c(1,2)) } }
 [1] 1
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 21d6e39b32..1eb1faf9b6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -49,6 +49,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.test.generate.FastRSession;
 import com.oracle.truffle.r.test.generate.GnuROneShotRSession;
 import com.oracle.truffle.r.test.generate.TestOutputManager;
+import java.io.OutputStream;
 
 /**
  * Base class for all unit tests. The unit tests are actually arranged as a collection of
@@ -469,8 +470,16 @@ public class TestBase {
     }
 
     // support testing of FastR-only functionality (equivalent GNU R output provided separately)
+    protected void assertEvalFastR(TestTrait trait1, String input, String gnuROutput) {
+        evalAndCompare(getAssertEvalFastR(gnuROutput, input), trait1);
+    }
+
     protected void assertEvalFastR(String input, String gnuROutput) {
-        evalAndCompare(new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"});
+        evalAndCompare(getAssertEvalFastR(gnuROutput, input));
+    }
+
+    private static String[] getAssertEvalFastR(String gnuROutput, String input) {
+        return new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"};
     }
 
     /*
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
new file mode 100644
index 0000000000..22d14b31b4
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.library.fastr;
+
+import com.oracle.truffle.r.runtime.RType;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class TestJavaInterop extends TestBase {
+
+    private static final String TEST_CLASS = TestClass.class.getName();
+
+    @Test
+    public void testToByte() {
+        assertEvalFastR("v <- .fastr.interop.toByte(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toByte(1.1); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toByte(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toByte(1.1); class(v);", "'" + RType.RInteropByte.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toByte(1.1); typeof(v);", "'" + RType.RInteropByte.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MAX_VALUE + "); v;", "" + Byte.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MIN_VALUE + "); v;", "" + Byte.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).byteValue());
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).byteValue());
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).byteValue());
+        assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).byteValue());
+    }
+
+    @Test
+    public void testToFloat() {
+        assertEvalFastR("v <- .fastr.interop.toFloat(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); v;", "1.1");
+        assertEvalFastR("v <- .fastr.interop.toFloat(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); class(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1L); class(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(1L); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MAX_VALUE + "); v;", "" + Float.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MIN_VALUE + "); v;", "" + (double) Float.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MAX_VALUE + "); v;", "Inf");
+        assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).floatValue());
+    }
+
+    @Test
+    public void testToLong() {
+        assertEvalFastR("v <- .fastr.interop.toLong(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toLong(1.1); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toLong(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toLong(1.1); class(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(1.1); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(1L); class(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(1L); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MAX_VALUE + "); v;", "" + Integer.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MIN_VALUE + "); v;", "" + Integer.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).longValue());
+        assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).longValue());
+    }
+
+    @Test
+    public void testToShort() {
+        assertEvalFastR("v <- .fastr.interop.toShort(1L); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toShort(1.1); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toShort(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- .fastr.interop.toShort(1.1); class(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(1.1); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(1L); class(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(1L); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MAX_VALUE + "); v;", "" + Short.MAX_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MIN_VALUE + "); v;", "" + Short.MIN_VALUE);
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).shortValue());
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).shortValue());
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).shortValue());
+        assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).shortValue());
+    }
+
+    @Test
+    public void testToChar() {
+        assertEvalFastR("v <- .fastr.interop.toChar(97L); v;", "'a'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1); v;", "'a'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1, 1); v;", "cat('Error in .fastr.interop.toChar(97.1, 1) : ', '\n', ' pos argument not allowed with a numeric value', '\n')");
+        assertEvalFastR("v <- .fastr.interop.toChar(97L, 1); v;", "cat('Error in .fastr.interop.toChar(97L, 1) : ','\n',' pos argument not allowed with a numeric value', '\n')");
+        assertEvalFastR("v <- .fastr.interop.toChar('abc', 1); v;", "'b'");
+        assertEvalFastR("v <- .fastr.interop.toChar('abc', 1.1); v;", "'b'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1); class(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97.1); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97L); class(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar(97L); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- .fastr.interop.toChar('a'); v;", "'a'");
+    }
+
+    @Test
+    public void testNew() {
+        assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); t <- .fastr.interop.new(tc, TRUE); t", "TRUE");
+        assertEvalFastR("tc <- .fastr.java.class('" + Byte.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Character.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t", "'a'");
+        assertEvalFastR("tc <- .fastr.java.class('" + Double.class.getName() + "'); t <- .fastr.interop.new(tc, 1.1); t", "1.1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Float.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t", "1.1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Integer.class.getName() + "'); t <- .fastr.interop.new(tc, 1L); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Long.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + Short.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + String.class.getName() + "'); t <- .fastr.interop.new(tc, 'abc'); t", "'abc'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNullClass.class.getName() + "'); t <- .fastr.interop.new(tc, NULL); class(t)", "'" + RType.TruffleObject.getName() + "'");
+    }
+
+    @Test
+    public void testFields() throws IllegalArgumentException, IllegalAccessException {
+        TestClass t = new TestClass();
+        Field[] fields = t.getClass().getDeclaredFields();
+        for (Field f : fields) {
+            String name = f.getName();
+            if (name.startsWith("field")) {
+                testForValue(name, f.get(t));
+            }
+        }
+    }
+
+    @Test
+    public void testMethods() throws IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException {
+        TestClass t = new TestClass();
+        Method[] methods = t.getClass().getDeclaredMethods();
+        for (Method m : methods) {
+            if (m.getParameterCount() == 0) {
+                String name = m.getName();
+                if (name.startsWith("method")) {
+                    testForValue(name + "()", m.invoke(t));
+                }
+            }
+        }
+    }
+
+    private void testForValue(String member, Object value) {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + member, getRValue(value));
+    }
+
+    @Test
+    public void testAllTypes() {
+        getValueForAllTypesMethod("allTypesMethod");
+        getValueForAllTypesMethod("allTypesStaticMethod");
+    }
+
+    @Test
+    public void testNonPrimitiveParameter() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", getRValue(true));
+    }
+
+    private void getValueForAllTypesMethod(String method) {
+        boolean bo = true;
+        byte bt = Byte.MAX_VALUE;
+        char c = 'a';
+        short sh = Short.MAX_VALUE;
+        int i = Integer.MAX_VALUE;
+        long l = Long.MAX_VALUE;
+        double d = Double.MAX_VALUE;
+        float f = Float.MAX_VALUE;
+        String s = "testString";
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValue(bo, bt, c, sh, i, l, d, f, s) + ")",
+                        getRValue("" + bo + bt + c + sh + i + l + d + f + s));
+    }
+
+    @Test
+    public void testNullParameter() {
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull('string')", "java.lang.String");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull(1)", "java.lang.Long");
+    }
+
+    @Test
+    public void testOverloaded() {
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE)", "boolean");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded('string')", String.class.getName());
+        // TODO add remaining isOverloaded(...) calls once this is fixed
+    }
+
+    private String getRValue(Object value) {
+        if (value == null) {
+            return "NULL";
+        }
+        if (value instanceof Boolean) {
+            return value.toString().toUpperCase();
+        }
+        if (value instanceof String) {
+            return "\"" + value.toString() + "\"";
+        }
+        if (value instanceof Character) {
+            return "\"" + ((Character) value).toString() + "\"";
+        }
+        if (value.getClass().isArray()) {
+            StringBuilder sb = new StringBuilder();
+            int l = Array.getLength(value);
+            sb.append("cat('[1] ");
+            for (int i = 0; i < l; i++) {
+                sb.append(getRValue(Array.get(value, i)));
+                if (i < l - 1) {
+                    sb.append(" ");
+                }
+            }
+            sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')");
+            return sb.toString();
+        }
+
+        return value.toString();
+    }
+
+    private String getRValue(Object... values) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < values.length; i++) {
+            Object v = values[i];
+            sb.append(getRValue(v));
+            if (i < values.length - 1) {
+                sb.append(",");
+            }
+        }
+        return sb.toString();
+    }
+
+    public static class TestNullClass {
+        public TestNullClass(Object o) {
+            assert o == null;
+        }
+    }
+
+    public static class TestClass {
+
+        public static boolean fieldStaticBoolean = true;
+        public static byte fieldStaticByte = Byte.MAX_VALUE;
+        public static char fieldStaticChar = 'a';
+        public static short fieldStaticShort = Short.MAX_VALUE;
+        public static int fieldStaticInteger = Integer.MAX_VALUE;
+        public static long fieldStaticLong = Long.MAX_VALUE;
+        public static double fieldStaticDouble = Double.MAX_VALUE;
+        public static float fieldStaticFloat = Float.MAX_VALUE;
+
+        public static Boolean fieldStaticBooleanObject = fieldStaticBoolean;
+        public static Byte fieldStaticByteObject = fieldStaticByte;
+        public static Character fieldStaticCharObject = fieldStaticChar;
+        public static Short fieldStaticShortObject = fieldStaticShort;
+        public static Integer fieldStaticIntegerObject = fieldStaticInteger;
+        public static Long fieldStaticLongObject = fieldStaticLong;
+        public static Double fieldStaticDoubleObject = fieldStaticDouble;
+        public static Float fieldStaticFloatObject = fieldStaticFloat;
+        public static String fieldStaticStringObject = "a string";
+
+        public boolean fieldBoolean = fieldStaticBoolean;
+        public byte fieldByte = fieldStaticByte;
+        public char fieldChar = fieldStaticChar;
+        public short fieldShort = fieldStaticShort;
+        public int fieldInteger = fieldStaticInteger;
+        public long fieldLong = fieldStaticLong;
+        public double fieldDouble = fieldStaticDouble;
+        public float fieldFloat = fieldStaticFloat;
+
+        public Boolean fieldBooleanObject = fieldBoolean;
+        public Byte fieldByteObject = fieldByte;
+        public Character fieldCharObject = fieldChar;
+        public Short fieldShortObject = fieldShort;
+        public Integer fieldIntegerObject = fieldInteger;
+        public Long fieldLongObject = fieldLong;
+        public Double fieldDoubleObject = fieldDouble;
+        public Float fieldFloatObject = fieldFloat;
+        public String fieldStringObject = fieldStaticStringObject;
+
+        public static Double fieldStaticNaNObject = Double.NaN;
+        public static double fieldStaticNaN = Double.NaN;
+
+        public static int[] fieldStaticIntArray = new int[]{1, 2, 3};
+        public static String[] fieldStaticStringArray = new String[]{"a", "b", "c"};
+
+        public int[] fieldIntArray = fieldStaticIntArray;
+        public String[] fieldStringArray = fieldStaticStringArray;
+
+        public static Object fieldStaticNullObject = null;
+        public Object fieldNullObject = null;
+
+        public TestClass() {
+            this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, Float.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string");
+        }
+
+        public TestClass(boolean bo, byte bt, char c, double d, float f, int i, long l, short sh, String st) {
+            fieldStaticBoolean = bo;
+            fieldStaticByte = bt;
+            fieldStaticChar = c;
+            fieldStaticDouble = d;
+            fieldStaticFloat = f;
+            fieldStaticInteger = i;
+            fieldStaticLong = l;
+            fieldStaticShort = sh;
+            fieldStaticStringObject = st;
+
+            // fieldStaticIntArray = ia;
+            // fieldStaticStringArray = sta;
+
+            fieldStaticBooleanObject = fieldStaticBoolean;
+            fieldStaticByteObject = fieldStaticByte;
+            fieldStaticCharObject = fieldStaticChar;
+            fieldStaticShortObject = fieldStaticShort;
+            fieldStaticIntegerObject = fieldStaticInteger;
+            fieldStaticLongObject = fieldStaticLong;
+            fieldStaticDoubleObject = fieldStaticDouble;
+            fieldStaticFloatObject = fieldStaticFloat;
+
+            this.fieldBoolean = fieldStaticBoolean;
+            this.fieldByte = fieldStaticByte;
+            this.fieldChar = fieldStaticChar;
+            this.fieldShort = fieldStaticShort;
+            this.fieldInteger = fieldStaticInteger;
+            this.fieldLong = fieldStaticLong;
+            this.fieldDouble = fieldStaticDouble;
+            this.fieldFloat = fieldStaticFloat;
+
+            this.fieldBooleanObject = fieldBoolean;
+            this.fieldByteObject = fieldByte;
+            this.fieldCharObject = fieldChar;
+            this.fieldShortObject = fieldShort;
+            this.fieldIntegerObject = fieldInteger;
+            this.fieldLongObject = fieldLong;
+            this.fieldDoubleObject = fieldDouble;
+            this.fieldFloatObject = fieldFloat;
+            this.fieldStringObject = fieldStaticStringObject;
+
+            this.fieldIntArray = fieldStaticIntArray;
+            this.fieldStringArray = fieldStaticStringArray;
+        }
+
+        public static boolean methodStaticBoolean() {
+            return fieldStaticBoolean;
+        }
+
+        public static byte methodStaticByte() {
+            return fieldStaticByte;
+        }
+
+        public static char methodStaticChar() {
+            return fieldStaticChar;
+        }
+
+        public static short methodStaticShort() {
+            return fieldStaticShort;
+        }
+
+        public static int methodStaticInteger() {
+            return fieldStaticInteger;
+        }
+
+        public static long methodStaticLong() {
+            return fieldStaticLong;
+        }
+
+        public static double methodStaticDouble() {
+            return fieldStaticDouble;
+        }
+
+        public static float methodStaticFloat() {
+            return fieldStaticFloat;
+        }
+
+        public static String methodStaticStringObject() {
+            return fieldStaticStringObject;
+        }
+
+        public static String[] methodStaticStringArray() {
+            return fieldStaticStringArray;
+        }
+
+        public static int[] methodStaticIntArray() {
+            return fieldStaticIntArray;
+        }
+
+        public boolean methodBoolean() {
+            return fieldBoolean;
+        }
+
+        public byte methodByte() {
+            return fieldByte;
+        }
+
+        public char methodChar() {
+            return fieldChar;
+        }
+
+        public short methodShort() {
+            return fieldShort;
+        }
+
+        public int methodInteger() {
+            return fieldInteger;
+        }
+
+        public long methodLong() {
+            return fieldLong;
+        }
+
+        public double methodDouble() {
+            return fieldDouble;
+        }
+
+        public float methodFloat() {
+            return fieldFloat;
+        }
+
+        public String methodStringObject() {
+            return fieldStringObject;
+        }
+
+        public String[] methodStringArray() {
+            return fieldStringArray;
+        }
+
+        public int[] methodIntArray() {
+            return fieldIntArray;
+        }
+
+        public static Boolean methodStaticBooleanObject() {
+            return fieldStaticBooleanObject;
+        }
+
+        public static Byte methodStaticByteObject() {
+            return fieldStaticByteObject;
+        }
+
+        public static Character methodStaticCharObject() {
+            return fieldStaticCharObject;
+        }
+
+        public static Short methodStaticShortObject() {
+            return fieldStaticShortObject;
+        }
+
+        public static Integer methodStaticIntegerObject() {
+            return fieldStaticIntegerObject;
+        }
+
+        public static Long methodStaticLongObject() {
+            return fieldStaticLongObject;
+        }
+
+        public static Double methodStaticDoubleObject() {
+            return fieldStaticDoubleObject;
+        }
+
+        public static Float methodStaticFloatObject() {
+            return fieldStaticFloatObject;
+        }
+
+        public Boolean methodBooleanObject() {
+            return fieldBoolean;
+        }
+
+        public Byte methodByteObject() {
+            return fieldByteObject;
+        }
+
+        public Character methodCharObject() {
+            return fieldCharObject;
+        }
+
+        public Short methodShortObject() {
+            return fieldShortObject;
+        }
+
+        public Integer methodIntegerObject() {
+            return fieldIntegerObject;
+        }
+
+        public Long methodLongObject() {
+            return fieldLongObject;
+        }
+
+        public Double methodDoubleObject() {
+            return fieldDoubleObject;
+        }
+
+        public Float methodFloatObject() {
+            return fieldFloatObject;
+        }
+
+        public static Object methodStaticReturnsNull() {
+            return null;
+        }
+
+        public Object methodReturnsNull() {
+            return null;
+        }
+
+        public String allTypesMethod(boolean bo, byte bt, char ch, short sh, int in, long lo, double db, float fl, String st) {
+            return "" + bo + bt + ch + sh + in + lo + db + fl + st;
+        }
+
+        public static Object allTypesStaticMethod(boolean bo, byte bt, char ch, short sh, int in, long lo, double db, float fl, String st) {
+            return "" + bo + bt + ch + sh + in + lo + db + fl + st;
+        }
+
+        public String isNull(String s) {
+            return s == null ? String.class.getName() : null;
+        }
+
+        public String isNull(Long l) {
+            return l == null ? Long.class.getName() : null;
+        }
+
+        public boolean equals(TestClass tc) {
+            return tc == this;
+        }
+
+        public String isOverloaded(boolean b) {
+            return "boolean";
+        }
+
+        public String isOverloaded(Boolean b) {
+            return Boolean.class.getName();
+        }
+
+        public String isOverloaded(byte b) {
+            return "byte";
+        }
+
+        public String isOverloaded(Byte b) {
+            return Byte.class.getName();
+        }
+
+        public String isOverloaded(char c) {
+            return "char";
+        }
+
+        public String isOverloaded(Character c) {
+            return Character.class.getName();
+        }
+
+        public String isOverloaded(double l) {
+            return "double";
+        }
+
+        public String isOverloaded(Double l) {
+            return Double.class.getName();
+        }
+
+        public String isOverloaded(Float f) {
+            return Float.class.getName();
+        }
+
+        public String isOverloaded(float f) {
+            return "float";
+        }
+
+        public String isOverloaded(int c) {
+            return "int";
+        }
+
+        public String isOverloaded(Integer c) {
+            return Integer.class.getName();
+        }
+
+        public String isOverloaded(long l) {
+            return "long";
+        }
+
+        public String isOverloaded(Long l) {
+            return Long.class.getName();
+        }
+
+        public String isOverloaded(short c) {
+            return "short";
+        }
+
+        public String isOverloaded(Short c) {
+            return Short.class.getName();
+        }
+
+        public String isOverloaded(String s) {
+            return String.class.getName();
+        }
+    }
+}
-- 
GitLab


From fc436af336dcf260a7a3b18b3e0b01c5d8126b3e Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Thu, 27 Apr 2017 13:56:58 +0200
Subject: [PATCH 389/402] handle foreign objects in CastListNode and
 PrecedenceNode

---
 .../truffle/r/nodes/unary/CastListNode.java   |  4 +++
 .../truffle/r/nodes/unary/PrecedenceNode.java |  9 +++---
 .../truffle/r/test/ExpectedTestOutput.test    | 32 +++++++++++++++++++
 .../r/test/library/fastr/TestJavaInterop.java | 13 ++++++++
 4 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index 2ea4c2b07e..9a868b06d2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -166,4 +166,8 @@ public abstract class CastListNode extends CastBaseNode {
     public static CastListNode createForRFFI(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         return CastListNodeGen.create(preserveNames, preserveDimensions, preserveAttributes, true);
     }
+
+    protected boolean isForeignObject(TruffleObject to) {
+        return RRuntime.isForeignObject(to);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
index 1d8a29e9d0..52c861931e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
@@ -153,11 +153,6 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
-    @Specialization
-    protected int doRInteroptFloat(RInterop b, boolean recursive) {
-        return NO_PRECEDENCE;
-    }
-
     @Specialization(guards = "recursive")
     protected int doListRecursive(RList val, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
@@ -227,4 +222,8 @@ public abstract class PrecedenceNode extends RBaseNode {
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
         return precedenceNode.executeInteger(args.getArgument(0), recursive);
     }
+
+    protected boolean isForeignObject(TruffleObject to) {
+        return RRuntime.isForeignObject(to);
+    }
 }
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 23d2b3fefd..002c9113b1 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
@@ -130568,6 +130568,38 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { class(c(.fastr.interop.toByte(123))) }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234))) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), 1)) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(1, .fastr.interop.toByte(123))) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(1, t)) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t, 1)) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1)) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t)) }
+[1] "truffle.object"
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringObject }
 [1] "a string"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 22d14b31b4..2a7bbe8986 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -126,6 +126,19 @@ public class TestJavaInterop extends TestBase {
         assertEvalFastR("tc <- .fastr.java.class('" + TestNullClass.class.getName() + "'); t <- .fastr.interop.new(tc, NULL); class(t)", "'" + RType.TruffleObject.getName() + "'");
     }
 
+    @Test
+    public void testCombine() {
+        assertEvalFastR("class(c(.fastr.interop.toByte(123)))", "'interopt.byte'");
+        assertEvalFastR("class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234)))", "'list'");
+        assertEvalFastR("class(c(.fastr.interop.toByte(123), 1))", "'list'");
+        assertEvalFastR("class(c(1, .fastr.interop.toByte(123)))", "'list'");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(t))", "'truffle.object'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1))", "'list'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(1, t))", "'list'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(t, 1))", "'list'");
+    }
+
     @Test
     public void testFields() throws IllegalArgumentException, IllegalAccessException {
         TestClass t = new TestClass();
-- 
GitLab


From b615c85b976af0adfd9dec47179a191bd75178d9 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Tue, 16 May 2017 14:13:03 +0200
Subject: [PATCH 390/402] print a TruffleObject character array the same way as
 a String array

---
 .../r/nodes/builtin/base/printer/ValuePrinterNode.java      | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index c9437d56e4..6beeea072e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -129,7 +129,7 @@ public final class ValuePrinterNode extends RBaseNode {
                     } catch (UnknownIdentifierException | UnsupportedMessageException e) {
                         throw RInternalError.shouldNotReachHere(e);
                     }
-                    return (String) value;
+                    return String.valueOf(value);
                 }
 
                 @Override
@@ -143,6 +143,7 @@ public final class ValuePrinterNode extends RBaseNode {
                     boolean allBoolean = true;
                     boolean allInteger = true;
                     boolean allNumber = true;
+                    boolean allCharacter = true;
                     boolean allString = true;
                     for (int i = 0; i < size; i++) {
                         Object value = ForeignAccess.sendRead(readNode, obj, i);
@@ -152,6 +153,7 @@ public final class ValuePrinterNode extends RBaseNode {
                         allBoolean &= value instanceof Boolean;
                         allInteger &= value instanceof Integer;
                         allNumber &= value instanceof Number;
+                        allCharacter &= value instanceof Character;
                         allString &= value instanceof String;
                     }
                     if (allBoolean) {
@@ -250,7 +252,7 @@ public final class ValuePrinterNode extends RBaseNode {
                             }
                         }
                         return new RDoubleWrapper(size);
-                    } else if (allString) {
+                    } else if (allString || allCharacter) {
                         return new RStringWrapper(size, obj);
                     } else {
                         class RListWrapper extends TruffleObjectWrapper implements RAbstractListVector {
-- 
GitLab


From 8fd909722530955a5e31d5ea97f3cd22df5fec35 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Tue, 16 May 2017 16:56:43 +0200
Subject: [PATCH 391/402] fastr interop - some basic builtins to create/convert
 java arrays

---
 .../r/nodes/builtin/base/BasePackage.java     |   4 +
 .../r/nodes/builtin/fastr/FastRInterop.java   |  26 +--
 .../r/runtime/data/RInteropScalar.java        |  26 +++
 .../r/test/library/fastr/TestJavaInterop.java | 160 ++++++++++++++++--
 4 files changed, 189 insertions(+), 27 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 3fda7060a4..eb9ccf0a2d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -375,6 +375,10 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create);
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
         add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
+        add(FastRInterop.IsJavaArray.class, FastRInteropFactory.IsJavaArrayNodeGen::create);
+        add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create);
+        add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
+        add(FastRInterop.FromJavaArray.class, FastRInteropFactory.FromJavaArrayNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
         add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
         add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index fee1e92a29..0857f0b531 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -44,6 +44,7 @@ import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
@@ -63,10 +64,8 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
-import static com.oracle.truffle.r.runtime.RType.Array;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -87,6 +86,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import java.lang.reflect.Array;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -108,7 +108,7 @@ public class FastRInterop {
             try {
                 return RContext.getInstance().getEnv().parse(sourceObject);
             } catch (Throwable t) {
-                throw error(Message.GENERIC, "Error while parsing: " + t.getMessage());
+                throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage());
             }
         }
 
@@ -153,9 +153,9 @@ public class FastRInterop {
                 Source sourceObject = sourceBuilder.build();
                 return RContext.getInstance().getEnv().parse(sourceObject);
             } catch (IOException e) {
-                throw error(Message.GENERIC, "Error reading file: " + e.getMessage());
+                throw error(RError.Message.GENERIC, "Error reading file: " + e.getMessage());
             } catch (Throwable t) {
-                throw error(Message.GENERIC, "Error while parsing: " + t.getMessage());
+                throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage());
             }
         }
 
@@ -194,13 +194,13 @@ public class FastRInterop {
         @Specialization
         @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) {
-            throw error(Message.ARGUMENT_MISSING, "value");
+            throw error(RError.Message.ARGUMENT_MISSING, "value");
         }
 
         @Fallback
         @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") Object name, @SuppressWarnings("unused") Object value) {
-            throw error(Message.GENERIC, "only R language objects can be exported");
+            throw error(RError.Message.GENERIC, "only R language objects can be exported");
         }
     }
 
@@ -226,7 +226,7 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.hasSize", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class HasSize extends RBuiltinNode.Arg1 {
 
-        @Child private Node node = com.oracle.truffle.api.interop.Message.HAS_SIZE.createNode();
+        @Child private Node node = Message.HAS_SIZE.createNode();
 
         static {
             Casts.noCasts(HasSize.class);
@@ -241,7 +241,7 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.isNull", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class IsNull extends RBuiltinNode.Arg1 {
 
-        @Child private Node node = com.oracle.truffle.api.interop.Message.IS_NULL.createNode();
+        @Child private Node node = Message.IS_NULL.createNode();
 
         static {
             Casts.noCasts(IsNull.class);
@@ -256,7 +256,7 @@ public class FastRInterop {
     @RBuiltin(name = ".fastr.interop.isExecutable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class IsExecutable extends RBuiltinNode.Arg1 {
 
-        @Child private Node node = com.oracle.truffle.api.interop.Message.IS_EXECUTABLE.createNode();
+        @Child private Node node = Message.IS_EXECUTABLE.createNode();
 
         static {
             Casts.noCasts(IsExecutable.class);
@@ -434,7 +434,7 @@ public class FastRInterop {
             try {
                 return JavaInterop.asTruffleObject(Class.forName(clazz));
             } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) {
-                throw error(Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
             }
         }
     }
@@ -797,13 +797,13 @@ public class FastRInterop {
                 Object result = ForeignAccess.sendNew(sendNew, clazz, argValues);
                 return RRuntime.java2R(result);
             } catch (SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
-                throw error(Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
+                throw error(RError.Message.GENERIC, "error during Java object instantiation: " + e.getMessage());
             }
         }
 
         @Fallback
         public Object interopNew(@SuppressWarnings("unused") Object clazz, @SuppressWarnings("unused") Object args) {
-            throw error(Message.GENERIC, "interop object needed as receiver of NEW message");
+            throw error(RError.Message.GENERIC, "interop object needed as receiver of NEW message");
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
index e2f4a3bc4f..ff5c016239 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteropScalar.java
@@ -31,6 +31,8 @@ public abstract class RInteropScalar extends RScalar {
 
     public abstract Object getRValue();
 
+    public abstract Class<?> getJavaType();
+
     @ValueType
     public static final class RInteropByte extends RInteropScalar {
 
@@ -63,6 +65,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Byte.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Byte.TYPE;
+        }
     }
 
     @ValueType
@@ -97,6 +104,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Character.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Character.TYPE;
+        }
     }
 
     @ValueType
@@ -131,6 +143,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Float.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Float.TYPE;
+        }
     }
 
     @ValueType
@@ -165,6 +182,11 @@ public abstract class RInteropScalar extends RScalar {
             CompilerAsserts.neverPartOfCompilation();
             return Long.toString(value);
         }
+
+        @Override
+        public Class<?> getJavaType() {
+            return Long.TYPE;
+        }
     }
 
     @ValueType
@@ -200,5 +222,9 @@ public abstract class RInteropScalar extends RScalar {
             return Short.toString(value);
         }
 
+        @Override
+        public Class<?> getJavaType() {
+            return Short.TYPE;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 2a7bbe8986..05eda5ef59 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -112,6 +112,81 @@ public class TestJavaInterop extends TestBase {
         assertEvalFastR("v <- .fastr.interop.toChar('a'); v;", "'a'");
     }
 
+    @Test
+    public void testToArray() {
+        assertEvalFastR("a <- .fastr.java.toArray(1L); a;", getRValue(new int[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L)); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(1L,,T); a;", getRValue(new int[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L),,T); a;", getRValue(new int[]{1, 2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(1.1); a;", getRValue(new double[]{1.1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2)); a;", getRValue(new double[]{1.1, 1.2}));
+        assertEvalFastR("a <- .fastr.java.toArray(1.1,,T); a;", getRValue(new double[]{1.1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2),,T); a;", getRValue(new double[]{1.1, 1.2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(T); a;", getRValue(new boolean[]{true}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(T, F)); a;", getRValue(new boolean[]{true, false}));
+        assertEvalFastR("a <- .fastr.java.toArray(T,,T); a;", getRValue(new boolean[]{true}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(T, F),,T); a;", getRValue(new boolean[]{true, false}));
+
+        assertEvalFastR("a <- .fastr.java.toArray('a'); a;", getRValue(new String[]{"a"}));
+        assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b')); a;", getRValue(new String[]{"a", "b"}));
+        assertEvalFastR("a <- .fastr.java.toArray('a',,T); a;", getRValue(new String[]{"a"}));
+        assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b'),,T); a;", getRValue(new String[]{"a", "b"}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a;", getRValue(new short[]{1, 2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a;", getRValue(new short[]{1, 2}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a;", getRValue(new double[]{1.123, 2.123}));
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a;", getRValue(new double[]{1}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a);", getRValue(new int[]{1}));
+        assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T);", getRValue(new int[]{1}));
+
+        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a);", getRValue(new short[]{1}));
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a)", "TRUE");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a)", "TRUE");
+        
+        assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1}));
+    }
+
+    @Test
+    public void testFromArray() {
+        testFromArray("fieldStaticBooleanArray", "logical");
+        testFromArray("fieldStaticByteArray", "integer");
+        testFromArray("fieldStaticCharArray", "character");
+        testFromArray("fieldStaticDoubleArray", "double");
+        testFromArray("fieldStaticFloatArray", "double");
+        testFromArray("fieldStaticIntArray", "integer");
+        testFromArray("fieldStaticLongArray", "double");
+        testFromArray("fieldStaticShortArray", "integer");
+        testFromArray("fieldStaticStringArray", "character");
+
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$objectArray); is.list(v)", "TRUE");
+        testFromArray("objectIntArray", "integer");
+        testFromArray("objectDoubleArray", "double");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v)", "TRUE");
+
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v)", "TRUE");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1]", "list(1)");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2]", "list(NULL)");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3]", "list(3)");
+    }
+
+    public void testFromArray(String field, String type) {
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); is.vector(v)", "TRUE");
+        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); typeof(v)", getRValue(type));
+    }
+
     @Test
     public void testNew() {
         assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); t <- .fastr.interop.new(tc, TRUE); t", "TRUE");
@@ -127,7 +202,7 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testCombine() {
+    public void testCombineInteropTypes() {
         assertEvalFastR("class(c(.fastr.interop.toByte(123)))", "'interopt.byte'");
         assertEvalFastR("class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234)))", "'list'");
         assertEvalFastR("class(c(.fastr.interop.toByte(123), 1))", "'list'");
@@ -177,7 +252,13 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testNonPrimitiveParameter() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", getRValue(true));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", "TRUE");
+    }
+    
+    @Test
+    public void testClassAsParameter() {
+        // needs to be implemented in truffle
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
     }
 
     private void getValueForAllTypesMethod(String method) {
@@ -190,7 +271,7 @@ public class TestJavaInterop extends TestBase {
         double d = Double.MAX_VALUE;
         float f = Float.MAX_VALUE;
         String s = "testString";
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValue(bo, bt, c, sh, i, l, d, f, s) + ")",
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValuesAsString(bo, bt, c, sh, i, l, d, f, s) + ")",
                         getRValue("" + bo + bt + c + sh + i + l + d + f + s));
     }
 
@@ -207,6 +288,21 @@ public class TestJavaInterop extends TestBase {
         // TODO add remaining isOverloaded(...) calls once this is fixed
     }
 
+    @Test
+    public void testArrayAccess() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2]", "2");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]]", "2");
+
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1]", "123");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]]", "123");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2]", "1234");
+        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]]", "1234");
+    }
+
     private String getRValue(Object value) {
         if (value == null) {
             return "NULL";
@@ -214,6 +310,14 @@ public class TestJavaInterop extends TestBase {
         if (value instanceof Boolean) {
             return value.toString().toUpperCase();
         }
+        if (value instanceof Double) {
+            if (((Double) value) == (((Double) value).intValue())) {
+                return Integer.toString(((Double) value).intValue());
+            }
+        }
+        if (value instanceof String) {
+            return "\"" + value.toString() + "\"";
+        }
         if (value instanceof String) {
             return "\"" + value.toString() + "\"";
         }
@@ -222,22 +326,25 @@ public class TestJavaInterop extends TestBase {
         }
         if (value.getClass().isArray()) {
             StringBuilder sb = new StringBuilder();
-            int l = Array.getLength(value);
             sb.append("cat('[1] ");
-            for (int i = 0; i < l; i++) {
+            int lenght = Array.getLength(value);
+            for (int i = 0; i < lenght; i++) {
+                if (lenght > 1 && value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) {
+                    // what the heck?
+                    sb.append(" ");
+                }
                 sb.append(getRValue(Array.get(value, i)));
-                if (i < l - 1) {
+                if (i < lenght - 1) {
                     sb.append(" ");
                 }
             }
             sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')");
             return sb.toString();
         }
-
         return value.toString();
     }
 
-    private String getRValue(Object... values) {
+    private String getRValuesAsString(Object... values) {
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < values.length; i++) {
             Object v = values[i];
@@ -298,12 +405,33 @@ public class TestJavaInterop extends TestBase {
         public static Double fieldStaticNaNObject = Double.NaN;
         public static double fieldStaticNaN = Double.NaN;
 
+        public static boolean[] fieldStaticBooleanArray = new boolean[]{true, false, true};
+        public static byte[] fieldStaticByteArray = new byte[]{1, 2, 3};
+        public static char[] fieldStaticCharArray = new char[]{'a', 'b', 'c'};
+        public static double[] fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
+        public static float[] fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
         public static int[] fieldStaticIntArray = new int[]{1, 2, 3};
+        public static long[] fieldStaticLongArray = new long[]{1, 2, 3};
+        public static short[] fieldStaticShortArray = new short[]{1, 2, 3};
         public static String[] fieldStaticStringArray = new String[]{"a", "b", "c"};
 
+        public boolean[] fieldBooleanArray = fieldStaticBooleanArray;
+        public byte[] fieldByteArray = fieldStaticByteArray;
+        public char[] fieldCharArray = fieldStaticCharArray;
+        public double[] fieldDoubleArray = fieldStaticDoubleArray;
+        public float[] fieldFloatArray = fieldStaticFloatArray;
         public int[] fieldIntArray = fieldStaticIntArray;
+        public long[] fieldLongArray = fieldStaticLongArray;
+        public short[] fieldShortArray = fieldStaticShortArray;
         public String[] fieldStringArray = fieldStaticStringArray;
 
+        public int[][] int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}};
+        public Object[] objectArray = new Object[]{new Object(), new Object(), new Object()};
+        public Object[] objectIntArray = new Object[]{1, 2, 3};
+        public Object[] objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
+        public Object[] mixedTypesArray = new Object[]{1, 2.1, 'a'};
+        public Integer[] hasNullIntArray = new Integer[]{1, null, 3};
+
         public static Object fieldStaticNullObject = null;
         public Object fieldNullObject = null;
 
@@ -322,9 +450,6 @@ public class TestJavaInterop extends TestBase {
             fieldStaticShort = sh;
             fieldStaticStringObject = st;
 
-            // fieldStaticIntArray = ia;
-            // fieldStaticStringArray = sta;
-
             fieldStaticBooleanObject = fieldStaticBoolean;
             fieldStaticByteObject = fieldStaticByte;
             fieldStaticCharObject = fieldStaticChar;
@@ -352,9 +477,6 @@ public class TestJavaInterop extends TestBase {
             this.fieldDoubleObject = fieldDouble;
             this.fieldFloatObject = fieldFloat;
             this.fieldStringObject = fieldStaticStringObject;
-
-            this.fieldIntArray = fieldStaticIntArray;
-            this.fieldStringArray = fieldStaticStringArray;
         }
 
         public static boolean methodStaticBoolean() {
@@ -517,6 +639,10 @@ public class TestJavaInterop extends TestBase {
             return null;
         }
 
+        public String classAsArg(Class<?> c) {
+            return c.getName();
+        }
+
         public String allTypesMethod(boolean bo, byte bt, char ch, short sh, int in, long lo, double db, float fl, String st) {
             return "" + bo + bt + ch + sh + in + lo + db + fl + st;
         }
@@ -605,4 +731,10 @@ public class TestJavaInterop extends TestBase {
             return String.class.getName();
         }
     }
+
+    public static class TestArrayClass {
+        public static TestArrayClass[] testArray = new TestArrayClass[]{new TestArrayClass(), new TestArrayClass(), new TestArrayClass()};
+
+    }
+
 }
-- 
GitLab


From 7bb7ee2a246c93eb539d7283b0f09543a5d1e873 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Tue, 16 May 2017 17:29:56 +0200
Subject: [PATCH 392/402] generated test output

---
 .../truffle/r/test/ExpectedTestOutput.test    | 460 +++++++++++++++++-
 1 file changed, 452 insertions(+), 8 deletions(-)

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 002c9113b1..7fe7f9ae12 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
@@ -130568,35 +130568,83 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1] }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]] }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1] }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]] }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2] }
+[1] 1234
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]] }
+[1] 1234
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2] }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]] }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1] }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]] }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$classAsArg(tc) }
+[1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { class(c(.fastr.interop.toByte(123))) }
 [1] "interopt.byte"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234))) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), 1)) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(1, .fastr.interop.toByte(123))) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(1, t)) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t, 1)) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1)) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombine#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t)) }
 [1] "truffle.object"
 
@@ -130752,6 +130800,30 @@ NULL
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanObject }
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE  TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanArray }
+[1]  TRUE FALSE  TRUE
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE  TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanArray }
+[1]  TRUE FALSE  TRUE
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharArray }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharArray }
+[1] "a" "b" "c"
+attr(,"is.truffle.object")
+[1] TRUE
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray }
 [1] "a" "b" "c"
@@ -130764,18 +130836,196 @@ attr(,"is.truffle.object")
 attr(,"is.truffle.object")
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray }
 [1] 1 2 3
 attr(,"is.truffle.object")
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray }
 [1] 1 2 3
 attr(,"is.truffle.object")
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortArray }
+[1] 1 2 3
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleArray }
+[1] 1.1 2.1 3.1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatArray }
+[1] 1.1 2.1 3.1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleArray }
+[1] 1.1 2.1 3.1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatArray }
+[1] 1.1 2.1 3.1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "character" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticCharArray); typeof(v) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "character" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticStringArray); typeof(v) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticDoubleArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticFloatArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticLongArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectDoubleArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticByteArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticIntArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticShortArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectIntArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { "logical" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticBooleanArray); typeof(v) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticBooleanArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticByteArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticCharArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticDoubleArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticFloatArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticIntArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticLongArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticShortArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticStringArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectDoubleArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectIntArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(1) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1] }
+[[1]]
+[1] 1
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(3) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3] }
+[[1]]
+[1] 3
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(NULL) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2] }
+[[1]]
+NULL
+
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringObject() }
 [1] "a string"
@@ -131004,6 +131254,200 @@ Error: object 'boolean' not found
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded('string') }
 Error: object 'java.lang.String' not found
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(T, F)); a; }
+[1]  TRUE FALSE
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(T, F),,T); a; }
+[1]  TRUE FALSE
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c('a', 'b')); a; }
+[1] "a" "b"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c('a', 'b'),,T); a; }
+[1] "a" "b"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray('a'); a; }
+[1] "a"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray('a',,T); a; }
+[1] "a"
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1L, 2L)); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1L, 2L),,T); a; }
+[1] 1 2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 1.2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2)); a; }
+[1] 1.1 1.2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 1.2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2),,T); a; }
+[1] 1.1 1.2
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.123 2.123\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a; }
+[1] 1.123 2.123
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1.1); a; }
+[1] 1.1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1.1,,T); a; }
+[1] 1.1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a); }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a); }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T); }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#Ignored.Unimplemented#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L,,F); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L,,T); a; }
+[1] 1
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T); a; }
+[1] TRUE
+attr(,"is.truffle.object")
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T,,T); a; }
+[1] TRUE
+attr(,"is.truffle.object")
+[1] TRUE
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); class(v); }
 [1] "interopt.byte"
-- 
GitLab


From f975777e749c429200417024998990c66bf3c57e Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 17 May 2017 15:44:17 +0200
Subject: [PATCH 393/402] moved javaobject tests from TestBuiltin_names to
 TestJavaInterop

---
 .../r/test/builtins/TestBuiltin_names.java    | 42 -----------------
 .../r/test/library/fastr/TestJavaInterop.java | 46 ++++++++++++++++++-
 2 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
index 8dd9a197c3..2088466650 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_names.java
@@ -13,8 +13,6 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
-import java.util.HashMap;
-import java.util.Map;
 
 // Checkstyle: stop line length check
 public class TestBuiltin_names extends TestBase {
@@ -212,44 +210,4 @@ public class TestBuiltin_names extends TestBase {
     public void testLNames() {
         assertEval("{ x <- quote(plot(x = age, y = weight)); names(x) }");
     }
-
-    public static class TestClass {
-        public Object field;
-        public static Object staticField;
-
-        public void method() {
-        }
-
-        public static void staticMethod() {
-        }
-    }
-
-    public static class TestClassNoMembers {
-
-    }
-
-    public static class TestClassNoPublicMembers {
-        int i;
-    }
-
-    public static class TestClassMap {
-        public static Map<String, String> m() {
-            HashMap<String, String> m = new HashMap<>();
-            m.put("one", "1");
-            m.put("two", "2");
-            return m;
-        }
-    }
-
-    @Test
-    public void testJavaObject() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClassNoMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClassNoPublicMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); names(tc$staticField)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); names(tc$staticMethod)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClass.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')");
-        assertEvalFastR("cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')");
-    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 05eda5ef59..583f289e98 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -30,6 +30,8 @@ import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
 
 public class TestJavaInterop extends TestBase {
 
@@ -155,7 +157,7 @@ public class TestJavaInterop extends TestBase {
 
         assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a)", "TRUE");
         assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a)", "TRUE");
-        
+
         assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1}));
     }
 
@@ -254,7 +256,7 @@ public class TestJavaInterop extends TestBase {
     public void testNonPrimitiveParameter() {
         assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", "TRUE");
     }
-    
+
     @Test
     public void testClassAsParameter() {
         // needs to be implemented in truffle
@@ -303,6 +305,18 @@ public class TestJavaInterop extends TestBase {
         assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]]", "1234");
     }
 
+    @Test
+    public void testNamesForJavaObject() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoPublicMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticField)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticMethod)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')");
+        assertEvalFastR("cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em)", "NULL");
+        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')");
+    }
+
     private String getRValue(Object value) {
         if (value == null) {
             return "NULL";
@@ -356,6 +370,34 @@ public class TestJavaInterop extends TestBase {
         return sb.toString();
     }
 
+    public static class TestNamesClass {
+        public Object field;
+        public static Object staticField;
+
+        public void method() {
+        }
+
+        public static void staticMethod() {
+        }
+    }
+
+    public static class TestNamesClassNoMembers {
+
+    }
+
+    public static class TestNamesClassNoPublicMembers {
+        int i;
+    }
+
+    public static class TestNamesClassMap {
+        public static Map<String, String> m() {
+            HashMap<String, String> m = new HashMap<>();
+            m.put("one", "1");
+            m.put("two", "2");
+            return m;
+        }
+    }
+
     public static class TestNullClass {
         public TestNullClass(Object o) {
             assert o == null;
-- 
GitLab


From ff12c8dc675d3c9b32c6e4fff70f4244942bb890 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 17 May 2017 16:50:59 +0200
Subject: [PATCH 394/402] generated test output

---
 .../truffle/r/test/ExpectedTestOutput.test    | 144 +++++++++++-------
 1 file changed, 93 insertions(+), 51 deletions(-)

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 7fe7f9ae12..fcc7c6994e 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
@@ -36571,38 +36571,6 @@ Error in k() : argument "y" is missing, with no default
 #argv <- structure(list(x = NA_real_), .Names = 'x');do.call('mode', argv)
 [1] "numeric"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) }
-NULL
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); names(tc$staticField) }
-NULL
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); names(tc$staticMethod) }
-NULL
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClassNoMembers'); t <- .fastr.interop.new(tc); names(t) }
-NULL
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClassNoPublicMembers'); t <- .fastr.interop.new(tc); names(t) }
-NULL
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); t <- .fastr.interop.new(tc); sort(names(t)) }
-[1] "field"        "method"       "staticField"  "staticMethod"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('one', 'two') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClassMap'); t <- .fastr.interop.new(tc); sort(names(t$m())) }
-[1] "one" "two"
-
-##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testJavaObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.builtins.TestBuiltin_names$TestClass'); sort(names(tc)) }
-[1] "staticField"  "staticMethod"
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_names.testLNames#
 #{ x <- quote(plot(x = age, y = weight)); names(x) }
 [1] ""  "x" "y"
@@ -77781,14 +77749,6 @@ Read 4 items
 Summary of Residuals:
 
 
-##com.oracle.truffle.r.test.library.base.TestConnections.testChannelConnection#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('hi there', zz); close(zz); NULL  }
-NULL
-
-##com.oracle.truffle.r.test.library.base.TestConnections.testChannelConnection#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('Hello, World!', 'second line') } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res }
-[1] "Hello, World!" "second line"
-
 ##com.oracle.truffle.r.test.library.base.TestConnections.testEncoding#
 #fin <- file('', "w+", encoding = "___inexistingCharSet___")
 Error in file("", "w+", encoding = "___inexistingCharSet___") :
@@ -130472,6 +130432,14 @@ a b c d e
 #{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing4.R") }
 [1] 24 42
 
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testChannelConnection#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('hi there', zz); close(zz); NULL  }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testChannelConnection#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('Hello, World!', 'second line') } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res }
+[1] "Hello, World!" "second line"
+
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { .fastr.interop.eval('application/x-r', '1') }
 [1] 1
@@ -131194,6 +131162,38 @@ attr(,"is.truffle.object")
 attr(,"is.truffle.object")
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticField) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticMethod) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoMembers'); t <- .fastr.interop.new(tc); names(t) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoPublicMembers'); t <- .fastr.interop.new(tc); names(t) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); t <- .fastr.interop.new(tc); sort(names(t)) }
+[1] "field"        "method"       "staticField"  "staticMethod"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('one', 'two') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassMap'); t <- .fastr.interop.new(tc); sort(names(t$m())) }
+[1] "one" "two"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); sort(names(tc)) }
+[1] "staticField"  "staticMethod"
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNew#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { tc <- .fastr.java.class('java.lang.Character'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t }
 [1] "a"
@@ -131477,11 +131477,11 @@ attr(,"is.truffle.object")
 [1] 0
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1.1); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1.1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1L); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
@@ -131497,11 +131497,11 @@ attr(,"is.truffle.object")
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97.1); v; }
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97.1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97L); v; }
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
@@ -131513,13 +131513,31 @@ attr(,"is.truffle.object")
 [1] "b"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97); class(v); }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97.1); class(v); }
 [1] "interopt.char"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97); typeof(v); }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97.1); typeof(v); }
 [1] "interopt.char"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97L); class(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97L); typeof(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.toChar(97.1, 1) : ', '<<<NEWLINE>>>', ' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- .fastr.interop.toChar(97.1, 1); v; }
+Error in .fastr.interop.toChar(97.1, 1) :
+  pos argument not allowed with a numeric value
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.toChar(97L, 1) : ','<<<NEWLINE>>>',' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- .fastr.interop.toChar(97L, 1); v; }
+Error in .fastr.interop.toChar(97L, 1) :
+  pos argument not allowed with a numeric value
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); class(v); }
 [1] "interopt.float"
@@ -131528,12 +131546,20 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); typeof(v); }
 [1] "interopt.float"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1L); class(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1L); typeof(v); }
+[1] "interopt.float"
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 0.0 } else { v <- .fastr.interop.toFloat(4.9E-324); v; }
 [1] 0
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(1L); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
@@ -131564,6 +131590,14 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); typeof(v); }
 [1] "interopt.long"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1L); class(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1L); typeof(v); }
+[1] "interopt.long"
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { -2147483648 } else { v <- .fastr.interop.toLong(-2147483648); v; }
 [1] -2147483648
@@ -131573,11 +131607,11 @@ attr(,"is.truffle.object")
 [1] 0
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1.1); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1.1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1L); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
@@ -131600,6 +131634,14 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); typeof(v); }
 [1] "interopt.short"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1L); class(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1L); typeof(v); }
+[1] "interopt.short"
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(1.7976931348623157E308); v; }
 [1] -1
@@ -131621,11 +131663,11 @@ attr(,"is.truffle.object")
 [1] 0
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1.1); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1.1); v; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1L); v; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-- 
GitLab


From 01fce3a9c11465df9940b6ec7db03ada2b280795 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 17 May 2017 18:20:17 +0200
Subject: [PATCH 395/402] fixed deprecation warnings in FastRDebugTest

---
 testScript.R | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 testScript.R

diff --git a/testScript.R b/testScript.R
new file mode 100644
index 0000000000..7237eba327
--- /dev/null
+++ b/testScript.R
@@ -0,0 +1,2 @@
+x<-c(1)
+cat(x)
-- 
GitLab


From 7971e5a5c78744fe7b8799844cc64832929a9d19 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Wed, 17 May 2017 18:20:17 +0200
Subject: [PATCH 396/402] fixed deprecation warnings in FastRDebugTest

---
 testScript.R | 2 --
 1 file changed, 2 deletions(-)
 delete mode 100644 testScript.R

diff --git a/testScript.R b/testScript.R
deleted file mode 100644
index 7237eba327..0000000000
--- a/testScript.R
+++ /dev/null
@@ -1,2 +0,0 @@
-x<-c(1)
-cat(x)
-- 
GitLab


From bba9bfb3e20fe106e3e05cfd789ad19cba9b9f3e Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 18 May 2017 15:41:42 +0200
Subject: [PATCH 397/402] Fix: NPE when retrieving arguments from top-level
 scope.

---
 .../oracle/truffle/r/runtime/env/RScope.java  | 22 +++++--
 .../truffle/r/test/tck/FastRDebugTest.java    | 60 +++++++++++++++++++
 2 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index ced4f106a5..977affc8f0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
@@ -64,8 +65,7 @@ public final class RScope extends AbstractScope {
 
     @Override
     protected String getName() {
-        // TODO promises (= closure)
-        return "function";
+        return isPromiseScope() ? "promise" : "function";
     }
 
     @Override
@@ -103,8 +103,22 @@ public final class RScope extends AbstractScope {
     }
 
     private static String[] collectArgs(REnvironment env) {
-        ArgumentsSignature signature = RArguments.getSignature(env.getFrame());
-        return signature.getNames();
+        assert RArguments.isRFrame(env.getFrame());
+        RFunction f = RArguments.getFunction(env.getFrame());
+        if (f != null) {
+            return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames();
+        } else {
+            ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame());
+            if (suppliedSignature != null) {
+                return suppliedSignature.getNames();
+            }
+        }
+        return new String[0];
+    }
+
+    private boolean isPromiseScope() {
+        Frame frame = env.getFrame();
+        return RArguments.getFunction(frame) == null && RArguments.getSuppliedSignature(frame) != null;
     }
 
     public static RScope createScope(Node node, Frame frame) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index cf4d6207f5..9adb1d9053 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Set;
@@ -320,6 +321,36 @@ public class FastRDebugTest {
         assertExecutedOK();
     }
 
+    @Test
+    public void testScopeArguments() throws Throwable {
+        final Source source = RSource.fromTextInternal("main <- function(a, b, c, d) {\n" +
+                        "   x <- 10L\n" +
+                        "}\n" +
+                        "closure <- function() {\n" +
+                        "   x <<- 123L\n" +
+                        "   x\n" +
+                        "}\n",
+
+                        RSource.Internal.DEBUGTEST_DEBUG);
+        engine.eval(source);
+
+        // @formatter:on
+        run.addLast(() -> {
+            assertNull(suspendedEvent);
+            assertNotNull(debuggerSession);
+            debuggerSession.suspendNextExecution();
+        });
+
+        assertArguments(2, "x <- 10L", "a", "b", "c", "d");
+        continueExecution();
+        performWork();
+
+        final Source evalSource = RSource.fromTextInternal("main(1, 2, 3, 4)\n", RSource.Internal.DEBUGTEST_EVAL);
+        engine.eval(evalSource);
+
+        assertExecutedOK();
+    }
+
     @Test
     public void testChangedScopeChain() throws Throwable {
         final Source source = RSource.fromTextInternal("main <- function(e) {\n" +
@@ -461,6 +492,35 @@ public class FastRDebugTest {
         });
     }
 
+    private void assertArguments(final int line, final String code, final String... expectedArgs) {
+        run.addLast(() -> {
+            try {
+                final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+
+                DebugScope scope = frame.getScope();
+
+                Set<String> actualIdentifiers = new HashSet<>();
+                scope.getArguments().forEach((x) -> actualIdentifiers.add(x.getName()));
+
+                assertEquals(line + ": " + code, expectedArgs.length, actualIdentifiers.size());
+
+                Set<String> expectedIds = new HashSet<>(Arrays.asList(expectedArgs));
+                Assert.assertEquals(expectedIds, actualIdentifiers);
+
+                if (!run.isEmpty()) {
+                    run.removeFirst().run();
+                }
+            } catch (RuntimeException | Error e) {
+
+                final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
+                frame.forEach(var -> {
+                    System.out.println(var);
+                });
+                throw e;
+            }
+        });
+    }
+
     private void compareScope(final int line, final String code, boolean includeAncestors, boolean completeMatch, final Object[] expectedFrame) {
         final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
 
-- 
GitLab


From a6fd6a2b681a708d121946085fc4ce8d1d7faca6 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Wed, 17 May 2017 15:32:25 +0200
Subject: [PATCH 398/402] fix cast in bitwiseShiftL

---
 .../truffle/r/nodes/builtin/base/BitwiseFunctions.java   | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
index 5d5314d20b..fd08cfc07a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
@@ -228,8 +228,7 @@ public class BitwiseFunctions {
             Casts casts = new Casts(BitwiseShiftL.class);
             casts.arg("a").defaultError(RError.Message.UNIMPLEMENTED_TYPE_IN_FUNCTION, typeName(), Operation.SHIFTL.name).mustBe(
                             doubleValue().or(integerValue())).asIntegerVector();
-            casts.arg("n").allowNull().mustBe(missingValue().not()).mapIf(stringValue(), chain(asStringVector()).with(shouldBe(anyValue().not(), RError.Message.NA_INTRODUCED_COERCION)).end(),
-                            asIntegerVector());
+            casts.arg("n").allowNull().mustNotBeMissing().asIntegerVector();
         }
 
         @Specialization
@@ -242,12 +241,6 @@ public class BitwiseFunctions {
         protected Object bitwShiftL(RAbstractIntVector a, RNull n) {
             return RDataFactory.createEmptyIntVector();
         }
-
-        @Specialization
-        @SuppressWarnings("unused")
-        protected Object bitwShiftLChar(RAbstractVector a, RAbstractStringVector n) {
-            return makeNA(a.getLength());
-        }
     }
 
     @RBuiltin(name = "bitwiseNot", kind = INTERNAL, parameterNames = {"a"}, behavior = PURE)
-- 
GitLab


From 647280dce87a1f16b84a78d713a3d00d872402ee Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 18 May 2017 16:00:01 +0200
Subject: [PATCH 399/402] Fix: Returned wrong foreign access.

---
 .../oracle/truffle/r/runtime/env/RScope.java  | 41 ++++++++++++-------
 .../truffle/r/test/tck/FastRDebugTest.java    |  3 ++
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index 977affc8f0..d44fd73c87 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -65,7 +65,20 @@ public final class RScope extends AbstractScope {
 
     @Override
     protected String getName() {
-        return isPromiseScope() ? "promise" : "function";
+        // just to be sure
+        if (env == REnvironment.emptyEnv()) {
+            return "empty environment";
+        }
+
+        assert env.getFrame() != null;
+        RFunction function = RArguments.getFunction(env.getFrame());
+        if (function != null) {
+            String name = function.getName();
+            return "function environment" + (name != null ? " for function " + name : "");
+        } else {
+            String name = env.getName();
+            return "explicit environment" + (name != null ? ": " + name : "");
+        }
     }
 
     @Override
@@ -103,24 +116,22 @@ public final class RScope extends AbstractScope {
     }
 
     private static String[] collectArgs(REnvironment env) {
-        assert RArguments.isRFrame(env.getFrame());
-        RFunction f = RArguments.getFunction(env.getFrame());
-        if (f != null) {
-            return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames();
-        } else {
-            ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame());
-            if (suppliedSignature != null) {
-                return suppliedSignature.getNames();
+
+        if (env != REnvironment.emptyEnv()) {
+            assert RArguments.isRFrame(env.getFrame());
+            RFunction f = RArguments.getFunction(env.getFrame());
+            if (f != null) {
+                return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames();
+            } else {
+                ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame());
+                if (suppliedSignature != null) {
+                    return suppliedSignature.getNames();
+                }
             }
         }
         return new String[0];
     }
 
-    private boolean isPromiseScope() {
-        Frame frame = env.getFrame();
-        return RArguments.getFunction(frame) == null && RArguments.getSuppliedSignature(frame) != null;
-    }
-
     public static RScope createScope(Node node, Frame frame) {
         return new RScope(node.getRootNode(), getEnv(frame));
     }
@@ -288,7 +299,7 @@ public final class RScope extends AbstractScope {
 
         @Override
         public ForeignAccess getForeignAccess() {
-            return VariableNamesMessageResolutionForeign.ACCESS;
+            return ArgumentNamesMessageResolutionForeign.ACCESS;
         }
 
         public static boolean isInstance(TruffleObject obj) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 9adb1d9053..134b0b01d3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -341,6 +341,9 @@ public class FastRDebugTest {
             debuggerSession.suspendNextExecution();
         });
 
+        assertArguments(1, "main(1, 2, 3, 4)");
+
+        stepInto(1);
         assertArguments(2, "x <- 10L", "a", "b", "c", "d");
         continueExecution();
         performWork();
-- 
GitLab


From 765a5916c5f0cf2286578abf726d3c1a6a98b340 Mon Sep 17 00:00:00 2001
From: Florian Angerer <florian.angerer@oracle.com>
Date: Thu, 18 May 2017 18:38:24 +0200
Subject: [PATCH 400/402] Fix: Removed root source section filter to enable
 step debugging for promises.

---
 .../instrumentation/RInstrumentation.java      |  1 -
 .../truffle/r/test/ExpectedTestOutput.test     | 18 ++++++++++++++++++
 .../library/utils/TestInteractiveDebug.java    |  6 ++++++
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java
index 80b3544234..4f8856e8c6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java
@@ -77,7 +77,6 @@ public class RInstrumentation {
         SourceSection fdns = fdn.getSourceSection();
         builder.indexIn(fdns.getCharIndex(), fdns.getCharLength());
         builder.sourceIs(fdns.getSource());
-        builder.rootSourceSectionEquals(fdns);
         return builder;
     }
 
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 fcc7c6994e..3f97cdba2b 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
@@ -144653,6 +144653,24 @@ debug: print(x)
 [1] 5
 exiting from: f(5)
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testPromise#Ignored.ImplementationError#
+#fun <- function(x) { cat({ cat(x); cat('<<<NEWLINE>>>') }) }; debug(fun); fun(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debugging in: fun(3)
+debug at #1: {
+    cat({
+        cat(x)
+        cat("\n")
+    })
+}
+debug at #1: cat({
+    cat(x)
+    cat("\n")
+})
+debug at #1: cat(x)
+3debug at #1: cat("\n")
+
+exiting from: fun(3)
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSimple#
 #f <- function(x) {<<<NEWLINE>>>  t <- x + 1<<<NEWLINE>>>  print(t)<<<NEWLINE>>>  t}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>t<<<NEWLINE>>>n<<<NEWLINE>>>n
 debugging in: f(5)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index e74647fcf2..0d5d1b076f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -59,6 +59,12 @@ public class TestInteractiveDebug extends TestBase {
         assertEval("bar <- function(x) { for(i in seq(x)) print(x) }; foo <- function(x) { cat('foo entry\\n'); bar(x); cat('foo exit\\n') }; debug(foo); foo(5)\n\n\ns\nn\n\n\nf\n\n");
     }
 
+    @Test
+    public void testPromise() {
+        // TODO enable test as soon as Truffle support is available
+        assertEval(Ignored.ImplementationError, "fun <- function(x) { cat({ cat(x); cat('\n') }) }; debug(fun); fun(3)\n\n\n\n\n");
+    }
+
     @Test
     public void testNestedDebugging() {
         assertEval(Output.IgnoreDebugPath,
-- 
GitLab


From f6507a7488f0252f60f78ced012aaf5bf2be27c8 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Thu, 18 May 2017 19:19:52 +0200
Subject: [PATCH 401/402] cleanup generated testfile

---
 .../truffle/r/test/library/fastr/TestInterop.java      | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index aa9ffbca00..0997d603ee 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -32,12 +32,22 @@ import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.conn.SeekableMemoryByteChannel;
 import com.oracle.truffle.r.test.TestBase;
+import java.io.File;
+import org.junit.After;
 
 public class TestInterop extends TestBase {
 
     private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel();
     private static final String CHANNEL_NAME = "_fastr_channel0";
 
+    @After
+    public void cleanup() {
+        File f = new File("testScript.R");
+        if (f.exists()) {
+            f.delete();
+        }
+    }
+
     @Test
     public void testInteropEval() {
         assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16");
-- 
GitLab


From a03b5a03501119a083ca45381f43daf97490be71 Mon Sep 17 00:00:00 2001
From: Tomas Stupka <tomas.stupka@oracle.com>
Date: Thu, 18 May 2017 19:36:39 +0200
Subject: [PATCH 402/402] GR-4122 issues when writing into interop object

---
 .../access/vector/ExtractVectorNode.java      |   9 +-
 .../access/vector/ReplaceVectorNode.java      |  17 +-
 .../truffle/r/test/ExpectedTestOutput.test    |  70 ++++--
 .../r/test/library/fastr/TestJavaInterop.java | 201 +++++++++++-------
 4 files changed, 194 insertions(+), 103 deletions(-)

diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index c3de219932..0cf2cec1a7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -124,7 +124,7 @@ public abstract class ExtractVectorNode extends Node {
                 // TODO implicite unboxing ok? method calls seem to behave this way
                 Object result = object;
                 for (int i = 0; i < positions.length; i++) {
-                    result = send(positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
+                    result = read(this, positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
                     if (positions.length > 1 && i < positions.length - 1) {
                         assert result instanceof TruffleObject;
                     }
@@ -151,7 +151,8 @@ public abstract class ExtractVectorNode extends Node {
         return RRuntime.java2R(obj);
     }
 
-    private Object send(Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode) throws RError, InteropException {
+    public static Object read(Node caller, Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode)
+                    throws RError, InteropException {
         if (position instanceof Integer) {
             position = ((int) position) - 1;
         } else if (position instanceof Double) {
@@ -163,7 +164,7 @@ public abstract class ExtractVectorNode extends Node {
         } else if (position instanceof RAbstractStringVector) {
             position = firstString.executeString(castNode.doCast(position));
         } else if (!(position instanceof String)) {
-            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+            throw RError.error(caller, RError.Message.GENERIC, "invalid index during foreign access");
         }
 
         int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
@@ -176,7 +177,7 @@ public abstract class ExtractVectorNode extends Node {
                 return ForeignAccess.sendRead(foreignRead, clazz, position);
             }
         }
-        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+        throw RError.error(caller, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
     }
 
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"})
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index 5c4fa8b774..77ce1d830a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -100,20 +100,25 @@ public abstract class ReplaceVectorNode extends Node {
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, Object value,
                     @Cached("WRITE.createNode()") Node foreignWrite,
+                    @Cached("READ.createNode()") Node foreignRead,
                     @Cached("KEY_INFO.createNode()") Node keyInfo,
                     @SuppressWarnings("unused") @Cached("positions.length") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
                     @Cached("createFirstString()") FirstStringNode firstString) {
         Object writtenValue = RRuntime.r2Java(value);
-        Object position = positions[0];
         try {
-            return write(position, foreignWrite, keyInfo, object, writtenValue, firstString, castNode);
+            TruffleObject result = object;
+            for (int i = 0; i < positions.length - 1; i++) {
+                result = (TruffleObject) ExtractVectorNode.read(this, positions[i], foreignRead, keyInfo, result, firstString, castNode);
+            }
+            write(positions[positions.length - 1], foreignWrite, keyInfo, result, writtenValue, firstString, castNode);
+            return object;
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
-    private Object write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
+    private void write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
                     throws InteropException, RError {
         if (position instanceof Integer) {
             position = ((Integer) position) - 1;
@@ -132,12 +137,14 @@ public abstract class ReplaceVectorNode extends Node {
 
         int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
         if (KeyInfo.isWritable(info)) {
-            return ForeignAccess.sendWrite(foreignWrite, object, position, writtenValue);
+            ForeignAccess.sendWrite(foreignWrite, object, position, RRuntime.r2Java(writtenValue));
+            return;
         } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
             TruffleObject clazz = JavaInterop.toJavaClass(object);
             info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
             if (KeyInfo.isWritable(info)) {
-                return ForeignAccess.sendWrite(foreignWrite, clazz, position, writtenValue);
+                ForeignAccess.sendWrite(foreignWrite, clazz, position, RRuntime.r2Java(writtenValue));
+                return;
             }
         }
         throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
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 fcc7c6994e..cb7d9614dd 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
@@ -130536,51 +130536,71 @@ attr(,"is.truffle.object")
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1]; }
 [1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]]; }
 [1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] }
 [1] 123
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] }
 [1] 123
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]] }
 [1] 1234
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2] }
 [1] 1234
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 12345 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]] }
+[1] 12345
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] }
 [1] 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] }
 [1] 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1] }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1] }
 [1] 1 2 3
 attr(,"is.truffle.object")
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAccess#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]] }
 [1] 1 2 3
 attr(,"is.truffle.object")
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$classAsArg(tc) }
 [1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
 
@@ -131238,11 +131258,15 @@ NULL
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$equals(t) }
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) {  } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.Long } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull(1) }
 Error: object 'java.lang.Long' not found
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameter#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull('string') }
 Error: object 'java.lang.String' not found
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 583f289e98..05db254460 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -32,6 +32,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
+import org.junit.Assert;
 
 public class TestJavaInterop extends TestBase {
 
@@ -259,8 +260,7 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testClassAsParameter() {
-        // needs to be implemented in truffle
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
     }
 
     private void getValueForAllTypesMethod(String method) {
@@ -278,7 +278,9 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testNullParameter() {
+    public void testNullParameters() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL)", "");
+
         assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull('string')", "java.lang.String");
         assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull(1)", "java.lang.Long");
     }
@@ -291,18 +293,38 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testArrayAccess() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1]", getRValue(new int[]{1, 2, 3}));
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1]]", getRValue(new int[]{1, 2, 3}));
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[1,2]", "2");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$int2DimArray; a[[1,2]]", "2");
-
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1]<-123; a[1]", "123");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1]]<-123; a[[1]]", "123");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[1,2]<-1234; a[1,2]", "1234");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); a <- t$fieldIntArray; a[[1,2]]<-1234; a[[1,2]]", "1234");
+    public void testArrayReadWrite() {
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1]", "1");
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]]", "1");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1];", "1");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]];", "1");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2]", "2");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]]", "2");
+
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1]", "123");
+        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]]", "123");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1]", "123");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]]", "1234");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1]", "NULL");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2]", "1234");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]]", "12345");
+    }
+
+    public void testMap() {
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']", "'1'");
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['two']", "'2'");
+
+        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']<-'11'; m['one']", "'11'");
+
+        // truffle
+        assertEvalFastR(Ignored.Unimplemented, "how to put into map?", "'11'");
     }
 
     @Test
@@ -406,56 +428,53 @@ public class TestJavaInterop extends TestBase {
 
     public static class TestClass {
 
-        public static boolean fieldStaticBoolean = true;
-        public static byte fieldStaticByte = Byte.MAX_VALUE;
-        public static char fieldStaticChar = 'a';
-        public static short fieldStaticShort = Short.MAX_VALUE;
-        public static int fieldStaticInteger = Integer.MAX_VALUE;
-        public static long fieldStaticLong = Long.MAX_VALUE;
-        public static double fieldStaticDouble = Double.MAX_VALUE;
-        public static float fieldStaticFloat = Float.MAX_VALUE;
-
-        public static Boolean fieldStaticBooleanObject = fieldStaticBoolean;
-        public static Byte fieldStaticByteObject = fieldStaticByte;
-        public static Character fieldStaticCharObject = fieldStaticChar;
-        public static Short fieldStaticShortObject = fieldStaticShort;
-        public static Integer fieldStaticIntegerObject = fieldStaticInteger;
-        public static Long fieldStaticLongObject = fieldStaticLong;
-        public static Double fieldStaticDoubleObject = fieldStaticDouble;
-        public static Float fieldStaticFloatObject = fieldStaticFloat;
-        public static String fieldStaticStringObject = "a string";
-
-        public boolean fieldBoolean = fieldStaticBoolean;
-        public byte fieldByte = fieldStaticByte;
-        public char fieldChar = fieldStaticChar;
-        public short fieldShort = fieldStaticShort;
-        public int fieldInteger = fieldStaticInteger;
-        public long fieldLong = fieldStaticLong;
-        public double fieldDouble = fieldStaticDouble;
-        public float fieldFloat = fieldStaticFloat;
-
-        public Boolean fieldBooleanObject = fieldBoolean;
-        public Byte fieldByteObject = fieldByte;
-        public Character fieldCharObject = fieldChar;
-        public Short fieldShortObject = fieldShort;
-        public Integer fieldIntegerObject = fieldInteger;
-        public Long fieldLongObject = fieldLong;
-        public Double fieldDoubleObject = fieldDouble;
-        public Float fieldFloatObject = fieldFloat;
-        public String fieldStringObject = fieldStaticStringObject;
-
-        public static Double fieldStaticNaNObject = Double.NaN;
-        public static double fieldStaticNaN = Double.NaN;
-
-        public static boolean[] fieldStaticBooleanArray = new boolean[]{true, false, true};
-        public static byte[] fieldStaticByteArray = new byte[]{1, 2, 3};
-        public static char[] fieldStaticCharArray = new char[]{'a', 'b', 'c'};
-        public static double[] fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
-        public static float[] fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
-        public static int[] fieldStaticIntArray = new int[]{1, 2, 3};
-        public static long[] fieldStaticLongArray = new long[]{1, 2, 3};
-        public static short[] fieldStaticShortArray = new short[]{1, 2, 3};
-        public static String[] fieldStaticStringArray = new String[]{"a", "b", "c"};
+        public static boolean fieldStaticBoolean;
+        public static byte fieldStaticByte;
+        public static char fieldStaticChar;
+        public static short fieldStaticShort;
+        public static int fieldStaticInteger;
+        public static long fieldStaticLong;
+        public static double fieldStaticDouble;
+        public static float fieldStaticFloat;
+
+        public static Boolean fieldStaticBooleanObject;
+        public static Byte fieldStaticByteObject;
+        public static Character fieldStaticCharObject;
+        public static Short fieldStaticShortObject;
+        public static Integer fieldStaticIntegerObject;
+        public static Long fieldStaticLongObject;
+        public static Double fieldStaticDoubleObject;
+        public static Float fieldStaticFloatObject;
+        public static String fieldStaticStringObject;
+
+        public boolean fieldBoolean;
+        public byte fieldByte;
+        public char fieldChar;
+        public short fieldShort;
+        public int fieldInteger;
+        public long fieldLong;
+        public double fieldDouble;
+        public float fieldFloat;
+
+        public Boolean fieldBooleanObject;
+        public Byte fieldByteObject;
+        public Character fieldCharObject;
+        public Short fieldShortObject;
+        public Integer fieldIntegerObject;
+        public Long fieldLongObject;
+        public Double fieldDoubleObject;
+        public Float fieldFloatObject;
+        public String fieldStringObject;
+
+        public static boolean[] fieldStaticBooleanArray;
+        public static byte[] fieldStaticByteArray;
+        public static char[] fieldStaticCharArray;
+        public static double[] fieldStaticDoubleArray;
+        public static float[] fieldStaticFloatArray;
+        public static int[] fieldStaticIntArray;
+        public static long[] fieldStaticLongArray;
+        public static short[] fieldStaticShortArray;
+        public static String[] fieldStaticStringArray;
 
         public boolean[] fieldBooleanArray = fieldStaticBooleanArray;
         public byte[] fieldByteArray = fieldStaticByteArray;
@@ -467,16 +486,21 @@ public class TestJavaInterop extends TestBase {
         public short[] fieldShortArray = fieldStaticShortArray;
         public String[] fieldStringArray = fieldStaticStringArray;
 
-        public int[][] int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}};
-        public Object[] objectArray = new Object[]{new Object(), new Object(), new Object()};
-        public Object[] objectIntArray = new Object[]{1, 2, 3};
-        public Object[] objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
-        public Object[] mixedTypesArray = new Object[]{1, 2.1, 'a'};
-        public Integer[] hasNullIntArray = new Integer[]{1, null, 3};
+        public int[][] int2DimArray;
+        public Object[] objectArray;
+        public Object[] objectIntArray;
+        public Object[] objectDoubleArray;
+        public Object[] mixedTypesArray;
+        public Integer[] hasNullIntArray;
+
+        public static Double fieldStaticNaNObject = Double.NaN;
+        public static double fieldStaticNaN = Double.NaN;
 
         public static Object fieldStaticNullObject = null;
         public Object fieldNullObject = null;
 
+        public Map<String, String> map;
+
         public TestClass() {
             this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, Float.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string");
         }
@@ -519,6 +543,37 @@ public class TestJavaInterop extends TestBase {
             this.fieldDoubleObject = fieldDouble;
             this.fieldFloatObject = fieldFloat;
             this.fieldStringObject = fieldStaticStringObject;
+
+            fieldStaticBooleanArray = new boolean[]{true, false, true};
+            fieldStaticByteArray = new byte[]{1, 2, 3};
+            fieldStaticCharArray = new char[]{'a', 'b', 'c'};
+            fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
+            fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
+            fieldStaticIntArray = new int[]{1, 2, 3};
+            fieldStaticLongArray = new long[]{1, 2, 3};
+            fieldStaticShortArray = new short[]{1, 2, 3};
+            fieldStaticStringArray = new String[]{"a", "b", "c"};
+
+            fieldBooleanArray = fieldStaticBooleanArray;
+            fieldByteArray = fieldStaticByteArray;
+            fieldCharArray = fieldStaticCharArray;
+            fieldDoubleArray = fieldStaticDoubleArray;
+            fieldFloatArray = fieldStaticFloatArray;
+            fieldIntArray = fieldStaticIntArray;
+            fieldLongArray = fieldStaticLongArray;
+            fieldShortArray = fieldStaticShortArray;
+            fieldStringArray = fieldStaticStringArray;
+
+            int2DimArray = new int[][]{new int[]{1, 2, 3}, new int[]{4, 5, 5}};
+            objectArray = new Object[]{new Object(), new Object(), new Object()};
+            objectIntArray = new Object[]{1, 2, 3};
+            objectDoubleArray = new Object[]{1.1, 2.1, 3.1};
+            mixedTypesArray = new Object[]{1, 2.1, 'a'};
+            hasNullIntArray = new Integer[]{1, null, 3};
+
+            map = new HashMap<>();
+            map.put("one", "1");
+            map.put("two", "2");
         }
 
         public static boolean methodStaticBoolean() {
@@ -681,6 +736,10 @@ public class TestJavaInterop extends TestBase {
             return null;
         }
 
+        public void methodAcceptsOnlyNull(Object o) {
+            Assert.assertNull(o);
+        }
+
         public String classAsArg(Class<?> c) {
             return c.getName();
         }
-- 
GitLab